Добавил:
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.12. ШАБЛОНЫ 141
A Буквы.
C Непечатные символы. Символы с ко-
дами от 0 до 31 и с кодом 127.
E Любой символ.
L Буква в нижнем регистре.
N Цифра.
P Знаки пунктуации и пробел.
U Буква в верхнем регистре.
Коды классов символов могут задаваться как в верхнем, так и в
нижнем регистре.
Формально, это перечень кодов, предусмотренных стандартом языка. При этом реализации MUMPS систем могут поддерживать дополнительные коды классов символов. Для уточнения полного перечня нужно
обратиться к документации на используемую MUMPS систему.
Коды классов символов могут следовать один за другим. В этом случае MUMPS система строит объединенное множество из их множеств.
Например, последовательность
AN
означает множество символов букв и цифр.
Формально говоря, стандарт языка MUMPS предусматривает применение оператора отрицания к коду класса символа для получения множества, не включающего указанный класс, например
1.3’N - от 1 до 3 не цифр
1.3’A - от 1 до 3 не букв
но такой функционал поддерживают в настоящее время не все реализации MUMPS систем. При использовании отрицания класса символов,
таким образом, необходимо проверить в документации на используемую
MUMPS систему, поддерживаются ли они. В случае если не поддерживаются, но шаблон был передан в виде внешних данных и применен
косвенно, то возникнет ошибка на этапе выполнения, а не компиляции.
Примеры шаблонов образованных счетчиком повторов и классами
символов:
2.AN 2 или больше букв или цифр
1A.E 1 буква, после которой любое число любых
символов
.’C любое число печатных символов

142 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
Второй вариант задания символов - это задание последовательности
символов (одного или нескольких) явно в виде строки. Строка должна
быть указана в двойных кавычках, как обычная строковая константа
языка:
1"%"4AN Один символ процента после которого 4
буквы или цифры
1.12AN1"@mail.ru" От 1 до 12 букв или цифр после которых 1
строка "@mail.ru"
Сопоставление явно заданным символам выполняется чувствительно
к регистру.
Альтернативы задаются круглыми скобками с перечислением вариантов через запятую. Сопоставление считается успешным, если система
находит соответствие для подходящего участка строки по меньшей мере
одной из указанных альтернатив. Например:
1.12AN1"@"1(1"mail.ru",1"yandex.ru") От 1 до 12 букв или цифр, косле которых 1 символ "@", после которого 1 повтор из альтернативы из 1 последовательности
"mail.ru" или 1 последовательности "yandex.ru"
Нужно отметить, что в приведенном примере вместо спецификации
числа повторов 1 также могут быть указаны любые числа, в этом случае
проверка по шаблону будет искать повторы заданных строк подряд, одна
за другой.
Альтернативы шаблонов могут быть вложены друг в друга.
Механизм сопоставления строки шаблону был разработан давно, принят в стандарте 1977-го года. В стандарт тогда входило задание классов
символов и строк, в качестве числа повторов можно было указывать
либо число либо точку, означающие что должно быть либо строго указанное число повторов либо любое число повторов. В стандарте 1984-го
года было дополнено возможностью указывать число повторов либо от
и до указанного числа, либо до, либо от указанного числа. В стандарте
1995-го года были приняты альтернативы.
Намного более сложные правила задаются регулярными выражениями. В определенном смысле, что такое регулярные выражения, задает
тон язык PERL, и многие другие системы ориентируются на его возможности и правила спецификации.

1.13. КОСВЕННОСТЬ 143
В системах MUMPS полновесные регулярные выражения могут быть
использованы лишь в виде внешних модулей либо если MUMPS система
поддерживает встроенные системные функции для регулярных выражений, в частности MiniM поддерживает семейство функций $ZPCRE для
проверки по регулярному выражению, для поиска и для замены подстрок. Но все эти возможности, несмотря на поддержку и наличие, не
входят в стандарт переносимости и разработчики должны проверять как
именно регулярные выражения поддерживаются на целевой системе.
Поддержка полноценных регулярных выражений в синтаксисе языка
PERL в той или иной функциональной форме видится существенным
улучшением с точки зрения прикладных программ. В действительности,
многие данные проходят или фильтр по определенным правилам проверки и нормализации, или разбор структуры также по определенным
правилам. Если стандартные шаблоны MUMPS могут лишь выполнить
проверку, то регулярные выражения могут также выполнить поиск с заменой и выделение набора подходящих фрагментов. Вводить регулярные
выражения в язык MUMPS на уровне синтаксиса языка в настоящее время выглядит нецелесообразным, но расширенная функциональная поддержка в стиле многих других языков видится удачной.
1.13 Косвенность
Во многих языках используются синтаксические конструкции, означающие не прямое использование значения, а использование значения как
указания что именно нужно использовать на самом деле, или вместо указанного. В этом случае производится непрямое использование значения
(indirection). В языке MUMPS эта операция также называется косвенностью. В те годы, когда разрабатывался язык MUMPS, было принято
использовать для обозначения косвенности символ "@". Во многих программных средствах он же используется и до сих пор.
Слабым аналогом косвенности является использование указателей
или ссылок, когда код использует не значение самого указателя или
ссылки, а тот объект, но который они указывают. Аналогом косвенности
выражения является функция eval в языке JavaScript, например.
Если при чтении программного кода разработчик видит символ @, то
это означает оператор косвенности. Оператор косвенности применяется
к тому, что стоит непосредственно справа от него. В языке MUMPS оператор косвенности может быть применен к большинству синтаксических
конструкций. Это:

144 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
1. Косвенность имени переменной
2. Косвенность индексов
3. Косвенность метки
4. Косвенность аргумента команды
5. Косвенность шаблона
Исключением являются косвенность оператора, выражения, и косвенность команды. Вместо косвенности собственно команды используется команда XECUTE, задающая выполнение не одной, а нескольких
команд. Вместо косвенности выражения используется косвенность аргумента для тех команд, которые в качестве аргумента используют выражение. Например, это команда QUIT или команда IF.
Вариант косвенного выполнения команды, или задание команды в
виде отдельной строки:
USER>s command="kill"
...
USER>x command_" varname"
Здесь к аргументу varname применяется команда, указанная ранее.
Но полноценной заменой косвенности команды это не является, поскольку используется команда xecute, автоматически создающая новый уровень стека и выполнение, в частности, команды new будет отменено при
возврате из команды xecute.
Вариант косвенности выражения сопряжен с использованием команды quit в аргументной форме и требует отдельной метки в рутине:
eval(expr) q @expr
Такую метку можно использовать для вычисления выражений, заданных косвенно:
w $$eval("2*2"),!
w $$eval("$sy_$zd($h)"),!
Оператор косвенности применяется к выражению после его вычисления и выражение может быть задано с произвольной сложностью. В
случае использования неатомарного выражения, например составленного из операторов, необходимо все выражение заключить в скобки, чтобы

1.13. КОСВЕННОСТЬ 145
указать что оператор применяется к результату вычисления всего выражения полностью, за исключением косвенности индексов. В случае
косвенности индексов индексы добавляются именно как указано.
Стандарт, вообще говоря, допускает применение косвенности произвольного уровня вложенности. Интерпретатор на этапе выполнения
будет раскрывать все встреченные им синтаксические конструкции косвенности пока все выражение не будет раскрыто полностью. Выполнение
этой операции с точки зрения внутренних алгоритмов и архитектуры, а
также требуемых ресурсов компьютера может представлять некоторую
сложность, поэтому при использовании рекурсии в операторе косвенности не все синтаксические конструкции могут быть выполнены.
В частности, система MiniM при использовании рекурсии генерирует
следующую ошибку:
USER>s x="@x"
USER>w @x
<MAXOBJCODE>
система Cach´e генерирует ошибку:
USER>s x="@x" w @x
S x="@x" W @x
<FRAMESTACK>
^
и система M3-Lite генерирует ошибку:
3>s x="@x" w @x
<STKOV>
Кроме того, отдельные реализации могут содержать ограниченные
возможности по рекурсивному раскрытию косвенности, либо по сочетанию видов косвенности, либо по глубине вложенности архитектурно,
либо, как было показано в примерах, косвенно из-за ограниченности выделяемых на операцию раскрытия ресурсов. В частности, приведенные
выше примеры показывают, что было запрошено бесконечное рекурсивное развертывание аргумента команды, определенное через само себя.
В обоих случаях системы натыкаются на израсходование внутренних
пределов выполнения кода, в зависимости от внутренних архитектур и
методов развертывания.

146 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
Оператор косвенности не имеет синтаксических отличий для его различных форм, форма косвенности определяется по контексту. В случае
если трактовка косвенности может быть многозначной, система выбирает
наиболее общий вариант. Например, если указано
write @string
то синтаксически это может соответствовать как косвенности имени для
вычисления значения переменной и вывода этого значения, так и косвенности аргумента команды write.
Но случай косвенности аргумента включает в себя возможный вариант, что в аргументе может быть использовано вычисляемое выражение,
или имя переменной, или перечисление нескольких допустимых аргументов команды, поэтому MUMPS система выбирает наиболее общий
из этих вариантов и трактует данный случай как косвенность аргумента
команды.
1.13.1 Косвенность имени
Косвенность имени означает замену оператора косвенности вместе с его
значением на использование того, что указано в значении. Если выражение было вычислено как строка, содержащая допустимое имя локальной,
глобальной, или структурной системной переменной, то система использует это имя вместо оператора косвенности. Например:
USER>s name="abcdef"
USER>w
name="abcdef"
USER>s @name=123456
USER>w
abcdef=123456
name="abcdef"
USER>
Здесь оператор косвенности применен к переменной name, что для
команды set означает применение операции не к переменной name, а к
значению переменной name. Оператор может быть применен к результату
выражения, вычисленному произвольным образом. В частности:

1.13. КОСВЕННОСТЬ 147
USER>w
USER>f i=1:1:5 s @("aa"_i_"bb")=i*i
USER>w
aa1bb=1
aa2bb=4
aa3bb=9
aa4bb=16
aa5bb=25
i=5
USER>
При конструировании выражения с именем переменной код может
конструировать как неиндексированное имя, как в примере выше, так
и индексированное, если оно построено по синтаксическим правилам
языка MUMPS:
USER>w
USER>f i=1:1:5 s @("aa"_i_"(i)")=i*i
USER>w
aa1(1)=1
aa2(2)=4
aa3(3)=9
aa4(4)=16
aa5(5)=25
i=5
USER>
Конечно, в случае использования строковых индексов разработчик
должен самостоятельно принять меры, чтобы кавычки были удвоены
там, где это необходимо, для получения корректного синтаксического
имени.
1.13.2 Косвенность индексов
Косвенность индексов задается только после косвенности имени и означает дописывание указанных индексов к вычисленному имени переменной. Имя переменной может вычисляться как локальное или глобальное
имя.
Если имя было вычислено как неиндексированное, при применении
косвенности индексов образуется имя с указанными индексами. Если

148 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
было вычислено индексированное имя, то индексы добавляются после
его последнего индекса.
Примеры дополнения неиндексированного имени:
USER>w
USER>s @("abc"_123)@(11,22,33)="value"
USER>w
abc123(11,22,33)="value"
USER>s @"name"="value2"
USER>w
abc123(11,22,33)="value"
name="value2"
Примеры дополнения индексированного имени:
USER>s @("abcd(1,2,3)")@(11,22,33)="value"
USER>s name=$na(local($j,$p))
USER>s @name@(11,22,33)="value2"
USER>w
abcd(1,2,3,11,22,33)="value"
local(2560,"|CON|",11,22,33)="value2"
name="local(2560,"|CON|")"
При развертывании косвенности индексов MUMPS система сначала
вычисляет и выполняет все необходимые подстановки для начального
имени переменной, затем вычисляет значения индексов переданные после оператора косвенности индексов и получает полное имя переменной.
Результаты операций косвенности имен и косвенности индексов могут
быть использованы в любом месте, где допускается применение имени
переменной.
В случае если функция, принимающая имя переменной, не допускает
использование структурной системной переменной, но оно было передано косвенно, MUMPS система генерирует ошибку на этапе выполнения
операции в зависимости от выполняемой функции.
Операции косвенности имен и индексов часто используются разработчиками для передачи строк в качестве аргументов функций, чтобы
функции могли применять обобщенные алгоритмы к произвольным переменным. Во многих случаях разработчики применяют также хранение

1.13. КОСВЕННОСТЬ 149
реальных имен переменных в глобалах с настройками прикладной программы, с тем, чтобы программа оперировала данными в указанных ей
переменных, глобалах. В этом случае администратор может направить
действия программы на необходимое сочетание глобалов.
1.13.3 Косвенность метки
Оператор косвенность метки определяется по контексту, в котором должна быть использована метка. Метки используются для безусловного перехода командой GOTO, для вызова подпрограмм командой DO, для
вызова функций с возвращаемым значением ($$) и как аргумент функции $TEXT. Во всех этих случаях MUMPS система будет подставлять
вместо метки вычисленное значение.
В каком-то смысле слабым аналогом косвенности метки является вы-
зов функции по указателю на функцию в других языках.
Метка состоит из четырех частей - собственно имя метки, величина смещения, имя базы данных где находится рутина и имя рутины.
Синтаксически имя базы данных рутины и номер смещения являются
вычисляемыми значениями, а имена метки и рутины указываются как
есть. Для конструирования полного имени метки и используются различные формы косвенности метки:
1. @expr - в значении expr MUMPS система ожидает полный набор
из 4-х компонент, часть из которых может быть опущена на усмотрение разработчика.
2. @exprˆrouname - в значении expr MUMPS система ожидает комбинирование имени метки и смещения.
3. label+@nameˆrouname - косвенность для смещения не поддерживается, здесь символы @name трактуются как вычисляемое выражение и синтаксически соответствуют косвенности имени. Значение
смещения берется из переменной, имя которой содержится в переменной name (в данном случае).
4. label[+offset]ˆ@expr - в значении expr MUMPS система ожидает
имя рутины с опционально заданной базой данных.
5. label[+offset]ˆ|@name|routine - косвенность для имени базы данных не поддерживается, здесь символы @name трактуются как
вычисляемое выражение и синтаксически соответствуют косвенности имени. Имя базы данных рутины берется из переменной, имя
которой содержится в переменной name (в данном случае).

150 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
Разработчики могут комбинировать косвенность частей метки произвольно, если после развертывания MUMPS система может получить
корректный результат.
Косвенность метки в том виде как она была определена при создании языка MUMPS, позволяет использовать аналог механизма функций
высшего порядка, когда функции могут передать и принять в качестве
параметров другие функции. Передать непосредственно функцию в языке MUMPS нельзя, поскольку отсутствует типизация в любом виде, но
можно передать строку, которую можно использовать в качестве имени
функции. Более того, со строкой можно поступить как с просто данными
и провести необходимые вычисления, например проверить допустимость
вызова, существует ли такая метка, добавить суффикс в зависимости
от контекста работы процесса и многое другое. Например, пусть есть
рутина fun в виде:
fun
w $$g("f",7),!
q
f(x)
q x+3
g(func,x)
q $$@(func)(x)*$$@(func)(x)
Здесь при вызове метки fun производится обращение к функции g,
и ей передаются строки "f" и 7. При этом функция g использует один
параметр для косвенного вызова функции, второй как передаваемый ей
параметр. При выполнении подпрограмма fun выводит в текущее устройство значение 100.
Здесь нужно обратить внимание на использование скобок в записи:
$$@(func)(x)
Такая запись означает взятие имени метки из переменной func. В
случае если скобки для func будут опущены и будет использована запись
$$@func(x)
то это означает взятие имени метки из индексированной переменной
func(x)
Одним из часто используемых применений косвенности метки является выполнение перехода в зависимости от каких-либо условий в сочетании с функцией $SELECT. Функция $SELECT проверяет условия
и возвращает строку с меткой для перехода или для вызова подпрограммы. К ее результату применяется оператор косвенности и результат
используется как метка. Например:
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
