Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:MUMPS СУБД. Практика применения и опыт программирования.pdf
X
- •Предисловие
- •Введение
- •Среда исполнения
- •Команды
- •Команды присваивания
- •Условные команды
- •Команды передачи управления
- •Команды ввода-вывода
- •Служебные команды
- •Постусловия
- •Операторы
- •Переменные
- •Числа и строки
- •Функции
- •$DATA
- •$GET
- •$ORDER
- •$NEXT
- •$QUERY
- •$NAME
- •$QLENGTH
- •$QSUBSCRIPT
- •$ASCII
- •$CHAR
- •$EXTRACT
- •$PIECE
- •$LENGTH
- •$REVERSE
- •$FIND
- •$TRANSLATE
- •$JUSTIFY
- •$FNUMBER
- •$TEXT
- •$RANDOM
- •$VIEW
- •$SELECT
- •$STACK
- •Списковые функции
- •Битовые функции
- •Модули
- •Рутины
- •Передача параметров
- •Неопределенные значения
- •Шаблоны
- •Косвенность
- •Косвенность имени
- •Косвенность индексов
- •Косвенность метки
- •Косвенность аргумента
- •Косвенность шаблона
- •Интерпретатор
- •Голая ссылка
- •Очередность выполнения
- •Очередность вычисления выражений
- •Очередность вычисления имен
- •Стекование $test
- •Комментарий
- •Стандарт и расширения
- •Глобалы
- •B-дерево
- •Кодирование индексов
- •Размер блока
- •Кеширование блоков
- •Структуры
- •Индексация
- •Группировка
- •Каноничность индексов
- •Маппинг
- •Индексация данных
- •Общие принципы
- •Механизм поддержки индекса
- •Простой индекс
- •Составной индекс
- •Покрывающий индекс
- •Кластерный индекс
- •Хеш-индекс
- •Битмап индекс (bitmap)
- •Битслайс индекс (bitslice)
- •Нормирование значений
- •Выборки по индексу
- •Многоиндексная выборка (zig-zag)
- •Дифференциальное индексирование
- •Индексация длинных атрибутов
- •Межтабличный индекс
- •Индекс с условием на вставку
- •Индекс на вычисляемый атрибут
- •Индекс поиска по фрагменту
- •Индексация для шаблона (like)
- •Индексация уникального атрибута
- •Массовое перестроение индексов
- •Операции с древовидными индексами
- •Операции с битовыми индексами
- •Сортировка по индексу
- •Статистики и кардинальность
- •Конкурентный доступ
- •Параллельность выполнения
- •Блокировки
- •Функция $INCREMENT
- •Транзакции
- •Блокировки в транзакциях
- •Функция $BIT
- •Дедлоки
- •Обработка ошибок
- •Состояние ошибки
- •ZTRAP
- •GT.M
- •MiniM
- •ETRAP
- •Определение
- •$ETRAP
- •$ECODE
- •$ESTACK
- •Ошибки в обработчике ошибок
- •$STACK()
- •Трассировка
- •BREAK
- •MiniM Debugger
- •Serenji Debugger
- •Внешний мир
- •Общие принципы
- •Терминальный интерфейс
- •Сокеты
- •HTTP клиент
- •Вебсервер на MUMPS
- •WebLink
- •Проблемы HTTP
- •Поверх HTTP
- •Подключаемые DLL (SO)
- •Файлы
- •Внешние процессы
- •Порты
- •Практика применения
- •Терминальный режим
- •Редакторы рутин
- •Экспорт и импорт
- •Препроцессор
- •Формат $HOROLOG
- •Опции устройств
- •$X и $Y
- •Возврат результатов
- •Возврат по значению ($$)
- •Возврат по ссылке
- •Запись в предопределенную переменную
- •Возврат значений косвенно
- •Итеративный возврат
- •Потоковый возврат
- •%Z - рутины
- •Планирование файлов
- •Память и сборка мусора

1.5. ФУНКЦИИ 111
команды, и в этом случае строковые возвраты функции $SELECT и
строковый вариант функции $CASE более гибки.
При необходимости выполнить замену функции $CASE как аргумен-
та команды DO, например кода
do $case(a,1:proc1(a),2:proc2(a),:proc3(a))
можно использовать постусловия на аргументы команды DO:
do proc1(a):a=1,proc2(a):a=2,proc3(a):(a’=1)&(a’=2)
В этом случае необходимо учесть, что в случае использования функции $CASE будет лишь один вызов команды DO, а при перечислении
аргументов через запятую команда DO проверяет каждое из постусловий слева направо и, в зависимости от их формулировки, может вызвать несколько подпрограмм из списка. Кроме того, при вычислении
постусловия, на результат могут оказать влияние побочные эффекты от
вычисления предыдущих постусловий.
Очередность вычисления в функции $CASE и проявление побочных
эффектов не определены стандартом и фиксируются производителем системы Cach´e.
В отличие от конструкций переключателя switch в языке C или case
в языке Pascal в языке MUMPS в функциях $SELECT и $CASE условия
не обязательно константы, это произвольные вычисляемые выражения и
функция $SELECT для вычисления истинности условия может использовать произвольные операторы и функции.
1.5.23 $STACK
Функция $STACK ($ST) возвращает состояние стека текущего процесса
с заданного уровня.
Новый уровень стека создается вызовом подпрограммы командой DO,
вызовом пользовательской функции, или выполнением команды XECUTE.
При старте процесса уровень стека равен 0, при создании каждого нового стекового фрейма уровень стека увеличивается на 1, и при
возврате на предыдущий уровень уменьшается на 1.
Функция $STACK традиционно используется в паре с системной переменной $STACK, возвращающей текущий уровень стека.
Функция поддерживает две формы - одноаргументную и двухаргументную. В одноаргументной форме функция принимает номер уровня
стека и возвращает строку с одним из предопределенных значений, означающих способ как был сформирован этот уровень:

112 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
DO Если текущий контекст образован выполнением ко-
манды do с параметрами или без них.
XECUTE Если текущий контекст образован выполнением ко-
манды xecute.
$$ Если текущий контекст образован вызовом подпро-
граммы с возвращаемым значением.
В двухаргументной форме функция дополнительно принимает второй
аргумент, который должен быть одним из следующих значений:
PLACE Возвращается место программы, которое исполняет
строку на указанном уровне исполнения программы.
MCODE Возвращается строка программы, которая исполняет-
ся на указанном уровне исполнения.
ECODE Возвращается строка с ошибкой, если на этом уровне
стека произошла ошибка.
В некоторых нестандартных случаях у функции $STACK действуют
дополнительные правила возврата.
Если на запрошенном уровне стека исполняется команда xecute, то
при задании второго параметра равном "PLACE" функция возвращает
строку из одного символа @. Контекст создания стекового фрейма командой XECUTE отличается от вызова подпрограммы тем, что стек создается, но у исполняемой строки команд нет положения в рутине.
В случае если исполняется строка без метки, то при втором параметре равном "PLACE" функция формирует возврат как метка + смещение
+ имя рутины. Метка и смещение в этом случае отсчитываются от последней пройденной процессом метки при выполнении программы.
Функция $STACK вместе с системной переменной $STACK входит
в стандартные функции, ее поведение жестко определено стандартом и
поддерживается всеми современными реализациями.
У MUMPS систем есть особенность поведения функции $STACK при
возникновении ошибки. От момента возникновения ошибки до присваивания переменной $ECODE пустой строки функция $STACK возвращает
значения для копии стека, замороженного состояния бывшего на момент
возникновения ошибки. После присваивания пустой строки переменной
$ECODE функция $STACK продолжает возвращать значения о реальном состоянии стека текущего процесса.
Традиционно состояние стека анализируется при отладке и зачастую
дополнительно протоколируется в обработчике ошибки, чтобы при чтении дампа состояния разработчики могли найти место проявления про-

1.6. СПИСКОВЫЕ ФУНКЦИИ 113
блемы и увидеть ход выполнения процесса.
1.6 Списковые функции
Списковые функции семейства $LIST не входят в стандарт языка MUMPS
и были самостоятельно разработаны и предложены в MUMPS системе
Cach´e фирмой производителем. Разработчики высоко оценили их практичность и полноту, и списковые функции в настоящее время широко
применяются в различных разработках. В дальнейшем списковые функции в точно таком же определении были реализованы также в MUMPS
системе MiniM.
При использовании списковых функций и необходимости в дальнейшем портирования кода нужно проверить, поддерживаются ли они на
целевой системе или версии системы.
Структурно списковые функции рассматривают строку с значением
как последовательность байт, в которой присутствуют отдельные элементы, следующие друг за другом. Каждый элемент содержит специальный тег, последовательность байт, описывающую длину элемента и тип
содержащегося в нем значения (для кодирования чисел).
Кодирование списков предусматривает специальный индикатор, описывающий что элемент в списке есть, но имеет неопределенное значение.
При вычислении элемента списка списковые функции последовательно просматривают элементы списка. Если задана операция с элементом
списка номер N, то функция последовательно пропускает N - 1 элементов.
Каждый из элементов может иметь произвольную длину, ограничение накладывается на общую длину значения полного списка как строки.
Любой элемент может содержать любые значения символов, в том числе сами в свою очередь могут рассматриваться программно как списки.
Такое кодирование значения подволяет преодолеть недостатки позиционного структурирования функции $EXTRACT и резервирования специального значения для разделителя для функции $PIECE.
Пустая строка списковыми функциями считается не состоящей ни из
одного элемента.
Каждая из строк, которые рассматривают списковые функции, не
имеет индикатора, каким образом получена эта последовательность байт.
Это могут быть константы, результат строковых функций, списковых
функций, чтения из устройства, арифметических или любых других операций. Если строка по своему формату не подходит под определение
списка, то списковые функции генерируют ошибку.

114 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
Основным способом получения списка является специальная функция $LISTBUILD ($LB). Эта функция принимает переменное число аргументов, в том числе нулевое. Любое число аргументов могут быть
опущены. Для опущенных аргументов функция генерирует в соответствующей позиции элемент с неопределенным значением. Примеры:
USER>s list=$lb(1,12,123,,12345)
USER>f i=1:1:$ll(list) w $lg(list,i,"undefined value"),!
1
12
123
undefined value
12345
Здесь функция $LISTBUILD составила список из значений 1, 12, 123,
неопределенного, и 12345. Затем в цикле по числу имеющихся элементов
($LISTLENGTH, $LL) были выведены значения списка, для неопределенных его значений использована строка "undefined value".
Структурно список есть последовательность элементов списка, следущих друг за другом. Поэтому список можно получить также конкатенацией двух списков. В результате получается новый список, в котором
сначала идут элементы из первого списка, и сразу за ними элементы из
второго списка, включая неопределенные.
USER>s list1=$lb("a","b","c")
USER>s list2=$lb(11,22,33)
USER>s list3=list1_list2
USER>f i=1:1:$ll(list3) w $lg(list3,i,"undefined"),!
a
b
c
11
22
33
Для получения значения элемента списка используются функции
$LIST ($LI) и $LISTGET ($LG). Им нужно указать значение списка
и номер позиции элемента. Позиции отсчитываются от единицы. Для
этих функций действует специальное соглашение о значении -1 как о
синониме позиции последнего элемента.

1.6. СПИСКОВЫЕ ФУНКЦИИ 115
Обе функции возвращают значение элемента списка. Отличие в том,
что если элемент имеет неопределенное значение, то функция $LIST генерирует ошибку, а функция $LISTGET возвращает значение по умолчанию. Если оно не было указано, то функция использует в качестве
значения по умолчанию пустую строку.
Для обеих этих функций элемент имеет неопределенное значение,
если элемент присутствует, но имеет специальное неопределенное значение и если номер позиции находится за пределами существующего
числа элементов.
При этом различается неопределенное значение списка и неопределенное значение переменной, передаваемое в качестве списка. Во втором случае управление до самой списковой функции не доходит, так
как MUMPS система самостоятельно обнаруживает неопределенность
значения.
Для замены элемента списка нужно использовать левостороннюю
форму функции $LIST и указать номер позиции для замены и значение для замены. Функция может заменить как имеющиеся, так и еще
несуществующие элементы. если указанной переменной не существовало, то она автоматически будет создана и исходное состояние такого
списка будет считаться пустым, не имеющим ни одного элемента.
USER>s list=$lb(,,)
USER>f i=1:1:$ll(list) w $lg(list,i,"no exist"),!
no exist
no exist
no exist
USER>s $list(list,2)=222
USER>f i=1:1:$ll(list) w $lg(list,i,"no exist"),!
no exist
222
no exist
USER>s $list(list,4)=444
USER>f i=1:1:$ll(list) w $lg(list,i,"no exist"),!
no exist
222
no exist
444
USER>s $list(list,7)=777

116 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
USER>f i=1:1:$ll(list) w $lg(list,i,"no exist"),!
no exist
222
no exist
444
no exist
no exist
777
Что интересно, функция $LIST поддерживает также трехаргументную форму, в которой функция рассматривает не одно значение, а подсписок. При присваивании в левосторонней форме функция заменяет
подсписок, а при возврате значения возвращает подсписок.
В частности, поскольку нельзя присвоить неопределенное значение,
можно выполнить ту же операцию путем замены на элемент с неопределенным значением:
USER>s list=$lb(11,22,33)
USER>f i=1:1:$ll(list) w $lg(list,i,"no exist"),!
11
22
33
USER>s $list(list,2,2)=$lb()
USER>f i=1:1:$ll(list) w $lg(list,i,"no exist"),!
11
no exist
33
Обе формы присваивания функции $LIST, и двухаргументная, и трехаргументная, автоматически дополняют список, если выполняется присваивание или замена несуществующих элементов списка. Дополнение
производится специальными элементами неопределенного значения.
Трехаргументная форма функции $LIST при присваивании также может быть использована для удаления элемента списка или произвольного
подсписка из любого числа элементов. Например, для удаления элементов с второго по четвертый включительно:
USER>s list=$lb(11,22,33,44,55)
USER>s $list(list,2,4)=""
USER>f i=1:1:$ll(list) w $lg(list,i,"no exist"),!
11
55

1.6. СПИСКОВЫЕ ФУНКЦИИ 117
Для удаления одного элемента списка в качестве начального и конечного номера элемента указывается одно и то же число, например для
удаления пятого и третьего элементов списка:
USER>s list=$lb(11,22,33,44,55,66,77)
USER>s $li(list,5,5)=""
USER>f i=1:1:$ll(list) w $lg(list,i,"no exist"),!
11
22
33
44
66
77
USER>s $li(list,3,3)=""
USER>f i=1:1:$ll(list) w $lg(list,i,"no exist"),!
11
22
44
66
77
USER>
Удалить элемент списка с использованием двуаргументной формы не
получится, поскольку она заменяет значение в позиции списка.
С помощью трехаргументной формы функции $LIST также можно
заменить элемент или несколько элементов списка на элемент с неопределенным значением, выполнив замену на список из одного или нескольких неопределенных значений:
USER>s list=$lb(11,22,33,44,55,66,77)
USER>s $li(list,3,3)=$lb()
USER>s $li(list,5,6)=$lb(,)
USER>f i=1:1:$ll(list) w $lg(list,i,"undefined"),!
11
22
undefined
44
undefined
undefined

118 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
77
USER>
К списковым функциям, поддерживаемым системами MiniM и Cach´e,
относятся функции:
1. $LISTBUILD - создает список из указанных значений.
2. $LIST - возвращает значение элемента списка или подсписок, присваивает значение элементу списка или подсписку.
3. $LISTGET - возвращает значение элемента списка или значение
по умолчанию.
4. $LISTDATA - возвращает индикатор, определен ли элемент списка
или нет.
5. $LISTFIND - выполняет поиск значения среди элементов списка.
6. $LISLENGTH - возвращает число элементов списка.
7. $LISTSAME - сравнивает списки с учетом возможного различия
кодирований чисел и строк.
Дополнительно система Cach´e в зависимости от версии поддержива-
ет, а система MiniM не поддерживает следующие функции:
1. $LISTFROMSTRING - формирует список по исходной строке с разделителями.
2. $LISTNEXT - возвращает следующий элемент списка, используя
специальный итератор, позволяющий не просматривать весь список
с самого начала.
3. $LISTTOSTRING - по заданному списку формирует строку с заданным раделителем.
4. $LISTVALID - проверяет является ли значение корректным списком.
Насколько известно, другие реализации MUMPS систем не поддерживают в настоящее время списковые функции. Хотя в свое время для
GT.M предлагался отдельный патч, реализующий упрощенную поддержку списковых функций, в релиз GT.M они не были внесены.

1.7. БИТОВЫЕ ФУНКЦИИ 119
1.7 Битовые функции
Битовые функции семейства $BITXXX были разработаны производителем MUMPS системы Cach´e и впоследствии также и в том же виде и
поведении были реализованы в MUMPS системе MiniM. Отличие этих
реализаций состоит в формате хранения собственно битовых строк. Если
в MiniM функции $LISTXXX были выполнены в точном соответствии
и с форматом хранения Cach´e и данные могут быть перенесены без изменений, то при переносе данных битовых строк с MiniM на Cach´e или
обратно они должны быть перегенерированы.
Первоначально различные реализации MUMPS систем поддерживали (и сейчас поддерживают для совместимости) битовые строки для семейства функций $ZBITXXX. Это функции, оперирующие строками как
последовательностями бит. У этого семейства функций есть ключевые
недостатки, не позволяющие их применять для построения битовых индексов, но допустимые для передачи битовых значений как состояния
данных:
1. Любые операции над строками $ZBITXXX есть также строки, поэтому запись в базу данных результата есть запись целой строки.
2. Чтобы хранить биты, необходимо предварительно создать битовую
строку необходимой длины.
Оба семейства битовых функций, и $BITXXX и $ZBITXXX не входят в стандарт, но различные реализации MUMPS систем принимают
меры по переносимости кода и, во многих случаях, по совместимости
форматов, таким как используемым функциями $ZBITXXX.
Основными отличиями битовых строк этих двух реализаций являются:
$ZBITXXX $BITXXX
Для установки бита необходимо начальное значение переменной.
Битовая строка должна быть
создана на необходимое количество битов.
Для изменения бита возвращается новое значение битовой
строки отдельной $ZBITSET
функцией.
Для установки бита начальное
значение переменной не требуется.
Можно устанавливать и читать
бит за пределами имеющегося
количества битов.
Для изменения бита используется команда set с левосторонней формой функции $BIT,
указывающей позицию для изменения.

120 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
Журналирование записи в глобал выполняется для всего нового значения целиком.
При откате транзакции откатывается все значение записанное
в глобал целиком.
Битовые строки хранятся в
несжатом виде.
Именно внутренние технологические решения функций семейства
$BITXXX и позволили использовать битовые индексы в транзакционных системах, или в задачах OLAP в режиме read / write, а не только в
традиционных задачах OLAP read only на отдельных серверах.
Для установки одного бита используется функция $BIT в двухаргументной форме. Первый аргумент - это имя локальной или глобальной
переменной, второй аргумент - позиция в битовой строке. Присваиваемое
значение приводится к булевскому (0 или 1) и переменная устанавливается в значение так чтобы все остальные имеющиеся биты сохранили
свое значение, а бит в указанной позиции принял заданное значение.
Если переменной не было, то она создается, а если позиция выходит за
пределы существовавших битов, битовая строка дополняется нулевыми
битами.
Та же функция $BIT в двухаргументной форме используется для чтения бита. Для единичного возвращает значение 1, для нулевого значение
0. Если переменной не существовало, то она не создается, и возвращается значение 0. Если запрашивается бит за пределами имеющегося числа
битов, то возвращается значение 0.
Определение поведения функции $BIT построено так, чтобы быть
наиболее практичным для битовых индексов. Традиционно в битовых
индексах значение 1 означает существование записи с идентификатором
с номером равным позиции бита. При создании записи записывается
значение 1. При удалении - 0. Если не было записи, то это логически
означает эквивалент нуля.
Теми же соглашениями пользуется функция битовых операций над
битовыми строками $BITLOGIC. При этом надо быть внимательным с
интерпретацией инверсии битовой строки - функция получает инверсию
только для имеющегося числа битов без расширения битовой строки до
максимума. В частности, если есть битовый индекс поддерживаемый для
индикатора существования объектов (extent - index), то по нему нельзя
определить множество объектов, в которое входят несуществующие объ-
Журналирование записи в глобал выполняется только для измененного бита.
При откате транзакции откатывается только определенное изменение бита.
Cach´e хранит битовые строки в
компрессированном по необходимости формате.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
