Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
MUMPS СУБД. Практика применения и опыт программирования.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
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 хранит битовые строки в компрессированном по необхо­димости формате.