Добавил:
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.1. КОМАНДЫ 51
Неприятность второго случая в том, что если округление дало нулевую величину, то задержка не выполняется и команда может вообще не
выполнить обращение к процедуре приостанова. В случае если задержка
на малую величину вставляется в цикл для отдачи процессорного времени, то в этом случае процесс может вообще не отдать процессорное
время на время своего ожидания.
При этом характер отсчета задержки также может варьироваться в
зависимости от реализации:
1. Задержка отсчитывается от начала выполнения команды.
2. Задержка прерывается при достижении соответствующего внутреннего кванта переключения контекстов job.
Во втором случае проявляется эффект нестабильного времени задержки с непредсказуемым характером округления как в меньшую, так
и в большую сторону. И чем меньше время задержки, тем больше относительная погрешность ее выполнения.
Если частью сервера приложений, написанного на MUMPS, является
фрагмент игрового характера, для которого важен таймаут с величинами менее секунды, то разработчикам необходимо проверять поведение
задержек на каждой из MUMPS систем, которые предполагается использовать. Характер реализации задержки может совпадать также для
других команд, использующих таймауты, для таких команд как LOCK,
JOB, READ или OPEN.
Команда HANG выполняет безусловную задержку. В случае если
пользователю нужно дать возможность прервать выполнение задержки,
рекомендуется использовать команду чтения символа READ с задержкой. При ее выполнении, если произошел ввод символа с клавиатуры, то
команда возвращает управление до истечения задержки.
Команда JOB (J) полностью аналогична команде DO (D) за двумя
исключениями:
1. После выполнения команды порождается новый процесс MUMPS
и управление возвращается вызвавшему процессу.
2. Нельзя передать локальные переменные по ссылке.
Если есть подпрограмма, например такая:
label(param,...)
; commands
...
q

52 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
то ее можно вызвать как подпрограмму командой DO и тогда она выполнится как часть последовательного выполнения процесса. Либо ее
же можно вызвать командой JOB, и тогда породится новый процесс и
его выполнение начнется с этой метки в этой рутине и параметры param
станут локальными переменными нового процесса.
Синтаксис вызова полностью аналогичен команде do:
do label^rtn(expr1,expr2,...)
job label^rtn(expr1,expr2,...)
Кроме того, команде job можно через двоеточие указать дополнительные опции запуска процесса и таймаут ожидания запуска. В случае если
таймаут указан, то команда записывает в системную переменную $test
значение 1 при успехе запуска дочернего процесса или 0 при неуспехе.
Команда job возвращает управление сразу как только выполнен запуск дочернего процесса либо стало известно, что такое действие невозможно по каким-либо причинам. Команда job не ожидает завершения
выполнения дочернего процесса.
Состав и назначение дополнительных опций команды job определяются реализацией и версией MUMPS системы. Традиционно в них специфицируются, например, передача дополнительных локальных переменных целиком в виде дерева, передача конкурентного сокета, указание
какой объем памяти необходимо использовать, в какой базе данных начать новый процесс, и другие параметры. В случае использования опций
команды job необходимо проверить в документации на используемую
MUMPS систему их состав и точный синтаксис.
Общий формат команды job специфицируется так:
job label^routine(params,...):(options,...):timeout
Также, как и для команды do, может быть опущено имя рутины, в
таком случае для старта нового процесса используется текущая рутина.
Традиционно, различные реализации MUMPS систем поддерживают
специальные расширенные системные переменные чтобы получить информацию о номере запущенного дочернего процесса в родительском
процессе и о номере родительского процесса в дочернем процессе. Например, это могут быть системные переменные $zparent и $zchild.
После запуска дочерний процесс выполняется параллельно и не связанно с родительским, и любой из них может завершить работу независимо друг от друга.
Команда LOCK (L) занимает или освобождает блокировку. Сама блокировка имеет имя совпадающее с именем локальной или глобальной

1.1. КОМАНДЫ 53
переменной. При этом существование и значение этих локальных или
глобальных имен для команды lock не имеют значения. Доступ к этим
переменным ничуть не препятствуется.
По своему назначению блокировка - это механизм синхронизации
двух или более процессов в рамках одного сервера MUMPS системы.
Если процесс может получить блокировку, то он получает и продолжает
выполнение. Если не может, то выполнение процесса приостанавливается до обнаружения состояния когда получить блокировку становится
возможным.
Блокировки, установленные процессом, имеют время жизни либо до
ее снятия самим процессом-владельцем, либо до окончания процесса.
Многие современные реализации MUMPS систем имеют возможности
принудительно снять блокировки, установленные в другом процессе.
Этот функционал уже находится за пределами стандарта и выполняется
средствами, зависимыми от реализации.
Команда VIEW (V), как и системная функция $view(), введена специально для вынесения в нее всех возможностей, специфических для
реализации MUMPS системы, например, просмотр значений операционного окружения, значения внутренних структур памяти, прямого управления сбросом буферов и многого другого.
Что интересно, сама команда VIEW стандартом предусмотрена, но
назначение и точный синтаксис оставлен на усмотрение реализации. При
портировании программ, разработанных на MUMPS, обычно именно использование команды view, функции $view и расширенных системных
переменных начинающихся на $Z, является предметом внимания для
поиска эквивалентной замены по функционалу.
1.1.6 Постусловия
Постусловия - это условия выполнения или использования, записанные
после команды или аргумента команды, к которым они применяются. В
других языках аналогичная конструкция не встречается и может вызвать
первое время непонимание. В действительности это некоторый более
короткий аналог команды if, но локального действия.
Синтаксически постусловие отделяется двоеточием и является произвольным вычисляемым выражением. При выполнении программы исполняющая системы вычисляет указанное в постусловии выражение. После
чего приводит его к числу и сравнивает с нулем. Если результат получится эквивалентом числового нуля, то постусловие считается ложным,
если результат - числовой не ноль, то постусловие считается истинным.

54 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
Постусловие команды применяется к команде. Если команде указано несколько аргументов, то постусловие распространяется на все эти
аргументы. Общий синтаксис:
cmd:postcond arg1,arg2,....
Некоторые команды, например, команды GOTO и DO с аргументами
допускают указание постусловия для аргумента. В этом случае постусловие указывается через двоеточие для аргумента. Общий синтаксис
постусловия для аргумента:
cmd arg1:postcond1,arg2:postcond2,...
В некотором смысле постусловие это укороченный аналог команды if
но с применением не ко всей последующей строке а только к указанной
команде или аргументу. В отличие от команды if, которая изменяет значение системной переменной $test, постусловие ни в какой форме его не
изменяет, если конечно самостоятельно не содержит соответствующих
побочных эффектов.
Если постусловие применено к команде, то при его невыполнении
команда не выполняется, но управление все равно передается следующей
команде.
Если постусловие применено к команде с несколькими аргументами,
то оно применяется к всем указанным аргументам. Например, если при
выполнении кода
write:a*b 123,!,456,! write 789,!
условие a * b вычислилось как 0, то команда
write 123,!,456,!
не выполняется полностью, но команда
write 789,!
все равно выполняется.
Постусловие для команд не может быть указано для условных команд IF, ELSE и FOR. В самом деле, положим что в языке разрешено
применять постусловие к командам IF, ELSE, FOR. В этом случае мы
должны в зависимости от значения постусловия применить команду к аргументу. И, если постусловие не выполнилось, то перейти к следующей
команде. В этом случае мы при ложном постусловии все равно выполняем команды, расположенные после команды IF, и один раз выполняем

1.2. ОПЕРАТОРЫ 55
команды расположенные в теле цикла, после команды FOR, несмотря
на собственные правила выполнения цикла, описанные в команде FOR.
Таким образом, разрешение постусловий для условных команд приводит
к недоразумениям.
Хотя постусловное выражение записывается после ключевого слова
команды, но вычисляется и проверяется перед выполнением или невыполнением команды.
Даже в случае, если постусловное выражение не выполняется (результат вычисления равен нулю), тем не менее, выражение вычисляется,
и вычисление может иметь побочные эффекты. На это разработчик обязательно должен обращать внимание.
Постусловие для аргумента указывает применять ли постусловие к
этому аргументу если команда выполняется. Не все команды поддерживают постусловия для аргумента. В частности, команды do и goto
поддерживают постусловия на аргументы.
Если постусловие аргумента не указано, то команда применяется к
нему, иначе, сначала вычисляется постусловие аргумента, проверяется
как число на равенство нулю, и в зависимости от результата команда
применяется к этому аргументу, либо применяется к следующему, если
он есть. При этом, если есть постусловие как на аргумент команды,
так и на команду, то сначала вычисляется и проверяется постусловие
на команду, а затем, если оно выполняется, вычисляются и проверяются
постусловия на аргументы. Например:
do:pc label1:pc1,label2:pc2
Здесь, если выражение pc вычисляется как 0, то все аргументы и
постусловия аргументов игнорируются, и управление переходит к следующей команде. Иначе, далее вычисляется и проверяется постусловие
pc1, и если выполняется, то вызывается подпрограмма с метки label1.
После обработки первого аргумента управление переходит ко второму,
вычисляется и проверяется постусловие pc2. Если оно выполняется, то
вызывается подпрограмма с метки label2.
В случае команды goto управление безусловно передается первому
из аргументов, для которого выполнилось постусловие, и дальнейшие
проверки не выполняются.
1.2 Операторы
Операторами называются действия над значениями, в результате которых получается также значение.

56 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
Операторы используются для укороченной записи специальных часто
используемых функций, и используют специальные символы для облегчения чтения и записи действий. Например, для записи сложения можно
использовать функцию, принимающую два аргумента, и имеющую, например, имя sum или summa или add, или иное, или обозначить одним
символом плюс:
a+b
Конечно, вариант с записью такого действия в виде отдельно определенного оператора намного читабельнее.
В языке MUMPS используются операторы двух видов - унарные (префиксные), применяемые к одному аргументу, и бинарные (инфиксные),
применяемые к двум аргументам.
Унарный оператор в префиксной форме применяется к аргументу следующим за ним. Примеры унарных операторов языка MUMPS:
+varname
-varname
’logical
Бинарные операторы в инфиксной форме применяются к двум аргументам, и располагаются между ними. Примеры бинарных операторов
языка MUMPS:
a+b
a*b
Часть бинарных операторов может состоять из одного символа, часть
из двух. В случае если оператор обозначен двумя символами, для него
дается отдельная трактовка, например два символа используется для
оператора отрицания логического оператора:
a’=b
a’>b
a’<b
a’]b
Определение оператора отрицания оператора задается как последовательное применение сначала оригинального оператора, затем к результату применяется оператор логического отрицания. В частности, эквивалентны замены:

1.2. ОПЕРАТОРЫ 57
a’=b -> ’(a=b)
a’>b -> ’(a>b)
a’<b -> ’(a<b)
a’]b -> ’(a]b)
При этом, некоторые современные реализации MUMPS систем, например MiniM и Cach´e, дополнительно поддерживают нестандартные
расширенные операторы из двух символов. В частности, операторы сравнения и ленивой логики
a>=b
a<=b
a||b
a&&b
Применение расширенных нестандартных операторов, конечно, должно входить в соглашения, принятые при разработке - можно ли их применять или нет, поскольку при портировании кода на другую MUMPS
систему они могут как поддерживаться, так и не поддерживаться.
Самым важным в применении операторов языка MUMPS для программистов, работавших с другими языками, является правило отсутствия приоритетов операторов. Все вычисления выполняются слева направо, как они написаны, и изменение порядка необходимо задавать
явно, указав круглыми скобками очередность вычисления выражений.
Так, если есть выражение
a+b*c
то интерпретатор MUMPS выполняет сначала сложение, затем умножение. Если программисту необходимо, чтобы сначала было выполнено
умножение, а затем сложение, это нужно описать явно:
a+(b*c)
Для начинающих разработчиков на MUMPS этот факт некоторое
время может быть источником проблем. В частности, при портировании кода вычисления выражений написанных на языке, использующем
приоритеты операций, или при модификации выражения, записанного
без скобок, или при модификации выражения, использующем порядок
вычисления слева направо.
Так, если было условие
a=b

58 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
и к нему необходимо добавить логическое ИЛИ с условием
c=d
то недостаточно дописать
a=b!c=d
Такое выражение будет соответствовать не ожидаемому
(a=b)!(c=d)
а совсем другому. Если записать его же с указанием порядка скобками,
то оно будет вычисляться так:
((a=b)!c)=d
Так что получится что значение d будет сравниваться с результатом
вычисления
(a=b)!c
Что интересно, автору доводилось видеть именно такую некорректную замену, причем этот код работал не проявляя ошибки больше полугода, потому что значения переменных перед вычислением принимали
такие значения, что результат, вычисленный неправильно, подходил под
правильный ответ.
Кроме операторов, вычисляющих выражение, в языке MUMPS также присутствует входящий в стандарт оператор отрицания кода шаблона,
сам по себе не вычисляющий выражение, а формирующий правило сопоставления шаблону:
USER>w "a"?1N
0
USER>w "a"?1’N
1
Здесь первый шаблон задает правило "один символ цифра", а второй отрицает тип символа и задает правило "один символ не цифра". С
оператором отрицания типа символа в шаблоне у разработчиков могут
возникнуть затруднения при его использовании, поскольку этот оператор довольно сложен в выполнении и не все реализации MUMPS его
поддерживают.
В дополнение к стандартным операторам системы MiniM и Cach´e
поддерживают операторную запись битовых операций и порядка их выполнения для битовых строк в аргументе функции $BITLOGIC:

1.2. ОПЕРАТОРЫ 59
& (И, бинарный)
| (ИЛИ, бинарный)
~ (НЕ, унарный)
Аргументами оператора могут быть любые значения, если они могут быть вычислены. Это могут быть константы, значения локальных,
системных, или глобальных переменных, результат возврата системных
и пользовательских функций, результаты других операторов. Если интерпретатор встречает использование оператора, то его аргументы синтаксически рассматриваются именно в этом контексте. В частности, для
указания что необходимо вызвать подпрограмму с возвращаемым значением, необходимо перед меткой указать символы $$, иначе литерал
метки интерпретатор будет оценивать как имя переменной или как число, если имя метки состоит из цифр.
В отличие от других языков, где есть предварительная декларация
типов, в языке MUMPS все литералы и имена рассматриваются как
синтаксические конструкции по контексту операции. В частности, различные элементы языка могут иметь совпадающие имена, и интерпретатор оценивает тип элемента не по его имени, а по синтаксическому
способу его использования:
1. name - локальная переменная
2. name(a,b,...) - индексированная локальная переменная
3. ˆname - глобальная переменная
4. ˆname(a,b,...) - индексированная глобальная переменная
5. $name - системная переменная
6. $name(a,...) - системная функция
7. $$name - пользовательская переменная в текущей рутине
8. $$name(a,...) - пользовательская функция в текущей рутине
9. $$nameˆrname - пользовательская переменная в рутине rname
10. $$nameˆrname(a,...) - пользовательская функция в рутине rname
Операторы языка по своему действию могут быть сгруппированы по
различным критериям, наиболее часто используется критерий группирования по типу действия - арифметические (численные), строковые (литеральные), логические (булевские).

60 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
Формально, такое деление условно и не строгое, поскольку строковые
и арифметические операторы могут быть использованы для вычисления
значения используемого как логическое условие, а логические операторы
могут быть использованы для вычисления строкового значения ("1" или
"0").
Арифметические операторы выполняют действия над операндами рассматривая их как числа и выполняют числовые операции. Множество
операторов языка покрывает традиционный для языков программирования набор операций. К таким операторам в языке MUMPS относятся:
1. Унарный плюс (+), применяется к аргументу справа от оператора,
приводит аргумент к числовому значению.
2. Унарный минус (-), применяется к аргументу справа от оператора,
приводит аргумент к числовому значению и меняет знак на противоположный.
3. Сложение (+), возвращает арифметическую сумму операндов.
4. Вычитание (-), возвращает арифметическую разность левого и правого операндов.
5. Умножение (*), возвращает произведение операндов.
6. Деление (/), возвращает отношение левого и правого операндов.
7. Целочисленное деление (\), возвращает целую часть отношения
левого и правого операндов.
8. Возведение в степень (**), возвращает результат возведения левого
операнда в степень равную второму операнду.
9. Деление по модулю (#), возвращает остаток от деления нацело
первого операнда на второй операнд.
10. Больше (>), возвращает булевское значение числового сравнения
операндов, проверяет что левый операнд арифметически больше
второго.
11. Меньше (<), возвращает булевское значение числового сравнения
операндов, проверяет что левый операнд арифметически меньше
второго.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
