Добавил:
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 - рутины
- •Планирование файлов
- •Память и сборка мусора

Введение
Много лет назад, в середине прошлого века, когда компьютеры были
большими и очень большими, методы работы с ними опирались на машинно - ориентированные способы и языки. Прикладным специалистам
было необходимо такое средство, чтобы можно было описывать собственные задачи и способы обработки информации, полностью абстрагируясь
от особенностей строения самих компьютеров.
Специалисты в области медицины, работавшие в Центральной больнице штата Массачусетс, коллектив разработчиков лаборатории вычислительной математики, определили основные требования к новому языку, чтобы его можно было легко применять в прикладных задачах. Так
возник язык, в который были вложены множество практически востребованных технологий и методов организации вычислений. В новый язык
были введены комплексно такие методы обработки информации, как работа со строками переменной длины, древовидные переменные, хранение данных в базе данных, одновременная параллельная работа заданий,
встроенный механизм ввода - вывода, работа с терминальными устройствами и устройствами самых различных типов, интерпретирующая среда исполнения, возможность писать компактно и обозримо на экране
размером 25*80, бестиповые данные, и многое другое.
Язык получил название MUMPS, как сокращение от названия разработки, Massachusetts General Hospital’s Utility Multiprogramming System.
В дальнейшем, чтобы называть язык программирования не названием
определенной системы, название в стиле самого языка стали сокращать
до первой буквы - M. В настоящее время названия M и MUMPS используются как синонимы для обозначения M - технологии в целом и
языка в частности.
Разработка языка MUMPS была выполнена в 1967-м году. Это был
период 60-х годов, годов бурного роста технологий, создания компьютеров, освоения космоса и новых видов техники, бурных событий в политике, привыкание Америки жить без расовой сегрегации, а СССР без
Сталина, периода Карибского кризиса и войны во Вьетнаме, освоения
11

12 ОГЛАВЛЕНИЕ
Арктики и строительства промышленных гигантов, открытий в физике
элементарных частиц, феномена группы Битлз и хиппи, полетов на Луну
и развитие телевидения. Умы молодых людей были наполнены идеями и
верой в то, что все их задумки, выглядевшие фантастикой, могут быть
выполнены, и они с открытым сердцем стремились создавать новое и совершенно шикарное по своим возможностям. Им ничто не мешало, над
ними не нависал дамоклов меч маркетинга, и язык MUMPS был создан.
Разработка оказалась настолько практичной и востребованной, что
была применена в самых различных медицинских учреждениях, а затем и в коммерческих, банковских. Разработка была подхвачена множеством групп разработчиков, появились самые различные реализации
языка MUMPS, и молодые пытливые умы вливали в него самые разнообразные идеи. Возникла задача стандартизации языка и этим занялся
комитет Mumps Development Committee, позднее был принят стандарт
на язык MUMPS, выходивший со временем в более поздних редакциях.
Выход единого стандарта на язык заложил основу его распространения и применения тем, что стандарт был весьма жестким и требовательным, и соответствие реализации языка этому стандарту означало практически беспроблемный перенос программ, разработанных на MUMPS,
между самыми различными компьютерами.
Со временем разработки MUMPS и M - технологии проникли и в
СССР, технические и прикладные специалисты высоко оценили его возможности и различные группы разработчиков стали также применять его
и в СССР. Появились также собственные реализации языка MUMPS,
переводы технической документации.
В существенной степени развитие и применение M - технологий оставалось и поныне остается инициативой самих разработчиков, как системных, так и прикладных. Это живой язык, и в различных реализациях
языка и сейчас производятся усовершенствования и введение различных
перспективных технологий.
В этой книге освещаются вопросы самого языка, возможности среды выполнения, вопросы стандартизации, совместимости и переносимости, различные программистские трюки и головоломки. Примеры кода,
примеры интерактивного исполнения команд приведены моноширинным
шрифтом. Те вставки, которые содержат промпт, являются примерами
интерактивной работы с MUMPS системой, остальные являются фрагментами подпрограмм.
В книге упоминаются несколько современных реализаций MUMPS
систем - это Cach´e, GT.M, MiniM, MUMPSV1. Это названия продуктов
с технической поддержкой, но книга может быть отнесена как практическое руководство также и к остальным системам.

Глава 1
Среда исполнения
1.1 Команды
По совокупности различного рода классификаций MUMPS системы относятся к процедурным, строчно - ориентированным, командно - ориентированным интерпретаторам позднего связывания.
По сути, все, что делает MUMPS система, есть исполнение заданной ей команды. В отличие от языков алгольной группы (C, Pascal),
где единицей исполнения является вычисление выражения и необходимо отдельно указывать единицы исполнения не являющиеся вычислением выражения (условные операторы или операторы циклов, передачи
управления), в MUMPS системе единицей исполнения всегда является
выполнение команды.
В языке MUMPS различается даже очевидное для других языков
действие присваивания, и требуется явно указать что именно с присваиванием необходимо сделать - присвоить только одно значение или всю
переменную вместе с содержащимся в ней поддеревом.
По своей структуре команда указывает, что нужно сделать, и в аргументе указывается к чему эту команду надо применить. В отдельных
случаях команды допускают применение дополнительных опций, детализирующих характер применения действия.
Команда задается ключевым словом, и это ключевое слово не является зарезервированным и может быть использовано в совершенно любом
регистре. Например, несколько различных написаний одной и той же
команды:
write
WRITE
Write
13

14 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
wRiTe
WRite
Одна из первых же неожиданностей для начинающих состоит в том,
что все что есть в языке MUMPS традиционно имеет две формы написания - полную и сокращенную, или аббревиатуру-синоним. В основном,
за очень редким исключением, команды сократимы до первой буквы.
Например, вместо команд
set
merge
halt
for
write
можно писать то же самое в сокращенной форме:
s
m
h
f
w
Учитывая, что в давно написанных прикладных системах принято
было использовать буквы верхнего регистра, и сокращение применяется
также к именам функций, код на языке MUMPS для новичка может
выглядеть результатом генератора случайных символов. Не нужно пугаться, уже примерно через неделю-другую после первого знакомства
с MUMPS системой новички начинают писать точно также и считают
MUMPS - стиль очевидным.
Другой неожиданностью для начинающих является то, что ключевые
слова для команд не являются зарезервированными в языке MUMPS,
и могут быть использованы в качестве имен локальных переменных.
Например, такой код:
kill lock
означает удаление локальной переменной lock, а код
lock kill
означает блокирование локальной переменной kill.
Большинство команд имеет так называемую безаргументную форму.
Если после имени команды не указан аргумент, то система исполняет
эту команду в безаргументной форме. Безаргументная форма по своему

1.1. КОМАНДЫ 15
назначению и пониманию относится ко всему контексту исполняемого
системой процесса. Например, безаргументная форма команды kill удаляет вообще все локальные переменные до которых сможет добраться.
Чтобы отличить безаргументную форму от аргументной, используется правило - если после имени команды стоит ровно один пробел и
далее следует аргумент или синтаксическая конструкция подходящая по
смыслу под допустимый аргумент, то это аргументная форма команды.
Все остальные варианты, например отсутствие символов в строке после
команды, два или более пробелов, воспринимается MUMPS системой
как безаргументная форма. Например, если есть конструкция удаления
локальной переменной
kill lock
то, стоит сделать не один а два пробела
kill lock
то это уже будет две команды, одна - удаление всех локальных переменных, вторая - снятие всех блокировок.
При этом, есть команды, для которых неприменима безаргументная
форма, например команды set или merge, есть команды для которых не
применима аргументная форма, например команды else или halt, и есть
команды которые являются различными командами в зависимости от
того, указан аргумент или нет (h - команды).
H - команды это две команды, halt и hang. Первая прекращает выполнение процесса, вторая - приостанавливает выполнение на указанное число секунд. Обе имеют допустимую форму сокращения до первой
буквы (h), но если аргумент указан то система считает эту команду
командой hang, а если нет - то командой halt.
Все команды языка MUMPS могут быть сгруппированы во вполне
традиционные для языков программирования группы команд:
1. Команды присваивания
2. Условные команды
3. Команды передачи управления
4. Команды ввода-вывода
5. Служебные команды

16 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
При этом, в силу полного отсутствия типизации переменных в языке
MUMPS отсутствуют команды декларирования переменных или описания их типа.
Синтаксически языки MUMPS и ранние версии языка BASIC организованы во многом аналогично - оба основаны на командах, оба являются
строчно - ориентированными, оба содержат встроенные команды вводавывода.
Традиционно, разработчики на языке MUMPS, работая над одним
проектом, принимают набор стилистических соглашений для написания
кода, или стандарты кодирования, и в различных командах могут быть
приняты различные соглашения. При этом разные группы свободно понимают стили друг друга.
Автор заметил, что большинство проектов разработанных много лет
назад, используют в основном соглашения о верхнем регистре команд,
функций и имен переменных, а проекты разработанные недавно, уже чаще применяют нижний регистр. В языках семейства C/C++ ключевые
слова являются регистрозависимыми и большинство идентификаторов
по инерции используется в нижнем регистре. В языках, допускающих
регистронезависимые ключевые слова и идентификаторы, чаще можно встретить смешивание регистров для большей читабельности кода.
В языке MUMPS по самому его духу не принято никак препятствовать разработчикам либо навязывать какой-либо стиль, поэтому можно
встретить самые различные соглашения о кодировании, при этом у разработчиков работающих в разных стилях, практически не встречается
неприятия иных стилей.
При чтении кода разработчики по инерции читают сначала имя команды, затем в зависимости от того указана аргументная форма или
безаргументная, читают аргумент команды, и так далее. В одной строке можно указывать подряд несколько команд, и они будут выполняться последовательно в порядке написания, слева направо. Исключение условные команды и команды передачи управления.
Команде могут быть указаны не один аргумент, а несколько, перечисленные через запятую. В этом случае команда применяется последовательно к каждому из указанных аргументов. Например, команда
присваивания
s a=123,b=456,c=789
последовательно выполняет 3 присваивания.
Вот, например, небольшая последовательность команд, имитирующая
с некоторым приближением командный шелл MUMPS системы:

1.1. КОМАНДЫ 17
f r !,"mumps>",l,! q:l="" x l
Здесь сначала идет команда f (for), в безаргументной форме, что означает вечный цикл. Затем идет команда r (read), чтение из текущего
устройства ввода-вывода с выводом сначала перевода строки (!), затем
строки приглашения, затем чтения строки в локальную переменную l и
затем снова вывода в текущее устройство перевода строки. Затем идет
команда q (quit) с постусловием но в безаргументной форме (два пробела после постусловия), прерывающая выполнение цикла если значение
переменной l получилось равным пустой строке, и далее идет команда x
(xecute), выполняющая строку l как последовательность команд.
С одной стороны, пример для новичка совершенно нечитабелен и может выглядеть шпионской шифровкой, но для человека знакомого с языком MUMPS эта короткая строка читается именно как большой абзац с
более чем осмысленным содержанием.
Та же самая строка, но в развернутом и приукрашенном виде может
выглядеть, например, так:
For Do Quit:LineToExec=""
. Write !,"MUMPS>"
. Read LineToExec
. Write !
. If LineToExec="" Quit
. Xecute LineToExec
При написании кода в более традиционном, развернутом стиле, новый
вариант увеличивается в объеме в разы и более-менее осмысленный код
по отправке, например, сообщения по SMTP, занимающий пару экранов,
может превратиться в необъятного размера монстра.
Автор считает, что есть повод задуматься о компактности и обозримости кода, если необходимо работать с действительно сложными и
ответственными системами. Например, с такими как медицинская система WorldVista. Ее исходный текст на языке MUMPS занимает примерно
94 мегабайт. Думается, если бы ее писали на языке, требующем большей "разговорчивости", то она не могла бы быть написана до сих пор,
в то время как применение MUMPS позволило ей быть написанной,
отлаженной и работающей не одно десятилетие.
С другой стороны, свобода выбора, предоставляемая языком MUMPS,
ничуть не препятствует также и написанию практически нечитабельного кода. Например, код написанный в стиле минимизации команд и демонстрирующей на экране падающие зеленые буквы в стиле заставки
фильма "Матрица":

18 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
matrix
matrix ; k d ^matrix w
w *27,"[32;40m",*27,"[?25l",#
n ch,i f r *ch:0.15 q:ch’=-1 d
. w *27,"[H",*27,"[1L"
. f i=1:1:80 w $s(i#4:" ",$r(8):$c($a("A")+$r(26)),1:" ")
w *27,"[0m",#,*27,"[?25h" q
для непосвященного может выглядеть также таинственно как и сам
фильм.
Иногда можно встретить шутку, что текст правильной (или вернее сказать идеальной) программы на MUMPS должен занимать ровно
80x25 символов.
1.1.1 Команды присваивания
Команды присваивания изменяют значение переменной. В качестве нового значения могут быть использованы
1. Результат вычисления выражения
2. Копия другой переменной с ее поддеревом
3. Присваивание неопределенного значения
Нужно отметить, что, в отличие от систем баз данных, различающих
операции insert и update в зависимости от того, существуют изменяемые
данные или нет, в языке MUMPS операции манипулирования данными
определены не на начало операции, а на окончание операции. Например,
для присваивания значения не требуется существование или несуществование переменной, она будет или перезаписана или создана, но в
любом случае будет иметь указанное значение по окончании операции.
Точно также для удаления переменной не требуется ее существование
или несуществование, по окончании операции удаления переменной не
будет существовать.
Для присваивания значения выражения используется команда set
set varname=expr
Для присваивания команда set сначала вычисляет все значения индексов указанные для переменной varname, затем вычисляет значение
expr, затем присваивает.

1.1. КОМАНДЫ 19
Одной из необычных особенностей языка MUMPS является то, что
для команды set могут быть использованы левосторонние функции. Обычная функция используется для вычисления выражения по некоторому
правилу и для возврата результата. В левосторонних функциях указывается что и как сделать с какой-либо частью значения переменной.
Например, функция $extract возвращает подстроку значения:
USER>s str="abcdefgh"
USER>w $e(str,2,4)
bcd
При этом функция описывает позиции, с которыми проиводится операция. Точно также функция $extract может быть использована для указания позиций для присваивания, и при этом команда set присвоит не
все значение целиком, а перезапишет лишь указанные позиции в строке:
USER>s str="abcdefgh"
USER>w $e(str,2,4)
bcd
USER>s $e(str,2,4)="FFFFFF"
USER>w str
aFFFFFFefgh
К таким левосторонним функциям в языке MUMPS относятся функции $extract, $piece, и в зависимости от реализации, $list, $bit и $qs.
Левосторонние функции могут быть применены лишь к локальным
или глобальным переменным. Применить их к системным, даже если
системная переменная допускает присваивание, нельзя.
Для левосторонних функций, выполняющих замещение в определенном формате, вводится в каждом случае специальное соглашение о дополнении строки, если значение содержит недостаточное число байт.
В частности, функция $extract дополняет пробелами, функция $piece
дополняет фрагментами из пустых строк, функция $bit дополняет нулевыми битами, функция $list дополняет неопределенными элементами
списка, а функция $qs дополняет индексами из пустых строк.
USER>s str="12"
USER>s $e(str,7)=777
USER>w

20 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
str="12 777"
USER>s str="1,2,3"
USER>s $p(str,",",7)=777
USER>w
str="1,2,3,,,,777"
USER>s str=$na(a(1,2,3))
USER>s $qs(str,7)=777
USER>w
str="a(1,2,3,"","","",777)"
Поведение дополнений максимально приближено к трактовке недостающих элементов как значений по умолчанию с точки зрения каждой
из этих функций.
Команда set имеет дополнительный синтаксис применения действия
присваивания к указанному списку переменных. В этом случае значение
выражения вычисляется однократно, но присваивается каждой из перечисленных в списке переменной или левосторонней функции. Общий
синтаксис:
set (assign1,assign2,...)=expr
Например, присваивание пустых строк сразу трем переменным:
set (a,b,c)=""
Использование левосторонних функций в зависимости от задачи может как существенно снизить читабельность кода, так и наоборот, существенно увеличить его. Сравните, например, просто присваивание:
s $p(rec,4,"~")=$h
w $p(rec,4,"~")
и простановку значения текущей даты в поле записи:
s nDATE=4
s DELIM="~"
...
s $p(rec,nDATE,DELIM)=$H
w $p(rec,nDATE,DELIM)
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
