Три манифеста баз данных ретроспектива и перспективы

       

Скалярные типы


Термин тип

охватывает и скалярные и не скалярные типы. Между скалярными и не скалярными типами имеется принципиальное различие. Скалярные типы вне зависимости от уровня сложности их реальных представлений – не содержат компонентов, видимых для пользователя.115 Напротив, не скалярные типы  содержат видимые для пользователя компоненты; в частности, типы кортежей и отношений не являются скалярными и содержат наборы видимых для пользователя атрибутов.

 

Значения некоторого скалярного типа обобщенно называются скалярными значениями (для краткости, скалярами). Аналогично, переменные, значения которых ограничиваются скалярами, обобщенно называются скалярными переменными. Реальное представление  таких значений и переменных может быть сколь угодно сложным.

Скалярные типы могут определяться пользователями либо быть системно-определенными (“встроенными”). Требуется, чтобы поддерживался хотя бы один встроенный скалярный тип – тип истинностного значения. Для определенности предполагается, что для этого типа поддерживаются операции NOT , AND и OR и литералы TRUE и FALSE . Для удобства считается, что поддерживаются также встроенные скалярные типы INTEGER , RATIONAL (Д&Д предпочитают использовать этот термин вместо REAL ) и CHAR с соответствующими операциями и литералами.

Вот несколько примеров определений пользовательских скалярных типов (используется синтаксис Tutorial D , который в данном случае не требует пояснений).

TYPE S# POSSREP { CHAR } ;

TYPE QTY POSSREP { INTEGER CONSTRAINT QTY > 0 } ;

Здесь у типа S # имеется только одно объявленное возможное представление (“POSSREP ”), обладающее именем S # по умолчанию.116У этого возможного  представления имеется ровно один компонент, имя которого по умолчанию совпадает с именем возможного представления, т.е. опять S # . Поскольку этот компонент определяется как принадлежащий типу CHAR , и не указано какое-либо дополнительное ограничение для типа S # , множество допустимых значений этого типа является множеством всех значений, которые можно представить в виде символьных строк.
Тип QTY определяется аналогичным образом, но для него указано дополнительное ограничение –  значения этого типа должны быть положительными.

Вот несколько более сложных примеров определения скалярных типов:

TYPE LENGHT POSSREP { L RATIONAL } ;



TYPE POINT
     POSSREP POINT { X LENGHT, Y LENGHT
                     CONSTRAINT … } ;
     POSSREP POLAR { R LENGHT, THETA ANGLE
                     CONSTRAINT … } ;

TYPE POLYGON
     POSSREP { VERTICES
               RELATION { V# INTEGER, VERTEX POINT
               CONSTRAINT … } ;

Определение типаLENGTH аналогично ранее приведенным определениям типов за исключением того, что единственному компоненту возможного представления этого типа задано явное имя L . ТипPOINT (“точка”) отличается от предыдущих примеров тем, что у него есть два различных объявленных возможных представления: первое –POINT (у этого возможного представления то же имя, что и у типа), с компонентами (Декартовыми координатами) X и Y , и второе – POLAR с компонентами (полярными координатами)R и THETA . Только в тех случаях, когда заданный тип имеет два или более объявленных возможных представлений, необходимо давать таким возможным представлениям явные имена. ТипELLIPSE (“эллипс”) отличается от предыдущих примеров тем, что его объявленное возможное представление основано не на встроенных, а на определенных пользователем типахLENGTH и POINT . Наконец, типPOLYGON (“многоугольник”) отличается от предыдущих примеров тем, что единственный компонент его объявленного возможного представления VERTICES принимает значения-отношения. То есть многоугольник представлялся бы отношением, содержащим по одному кортежу для каждой вершины этого многоугольника; этот кортеж содержал бы номер вершины (значение типаINTEGER ) вместе с самой соответствующей вершиной (значение типа POINT ).

Следует подчеркнуть, что операция определения типа реально не создает соответствующего множества значений. Концептуально, это множество значений уже существует и всегда будет существовать.


Все, что делает операция “определения типа”, заключается в введении имени, посредством которого можно ссылаться на это множество значений. Из RM -предписания 2 следует, что любое значение всегда относится к одному и только одному типу (если не поддерживается наследование). Побочным (но важным) следствием является то, что пересечение множеств значений любых двух различных типов всегда пусто (опять же при отсутствии наследования).

Скалярная операция – это операция, возвращающая скалярное значение или обновляющая скалярную переменную. 117  Как и скалярные типы, скалярные операции могут определяться либо пользователями, либо системой (“встраиваться”). Встроенные операции определяются только в связи со встроенными типами. Предполагается, что для встроенных скалярных типов BOOLEAN , INTEGER , RATIONAL и CHAR поддерживается естественный для этих типов набор операций, причем имена некоторых операций перегружены. Определяемые пользователями операции можно определять как для встроенных типов, так и для определяемых пользователями.

Факт существования операции с заданным именем не препятствует возможности перегрузки – то есть определения другой операции с тем же именем, но с другими объявленными типами параметров и (возможно) результатов, и следовательно, по крайней мере, частично отличной семантикой. Можно было бы даже не только перегрузить, но и переопределить существующую операцию посредством определения другой операции с тем же именем и теми же объявленными типами параметров и результатов, но с другой семантикой. По очевидным соображениям, мы рекомендуем, чтобы это средство использовалось со всеми возможными предосторожностями.  

Вот пример определяемой пользователем скалярной операции, работающей со встроенным типом: 

OPERATOR ABS ( N RATIONAL ) RETURNS RATIONAL ;
   RETURN CASE
             WHEN N ³ 0.0 THEN +N
             WHEN N < 0.0 THEN –N
          END CASE ;

END OPERATOR ;

Операция ABS определяется с единственным параметром N объявленного типа RATIONAL и возвращает результат того же объявленного типа.


Это операция только чтения, что означает, что ни при каком вызове функция не пытается обновлять свой собственный аргумент.

Вот другой пример определяемой пользователем скалярной операции только чтения, которая работает с некоторыми определяемыми пользователем типами:

OPERATOR DIST ( P1 POINT, P2 POINT ) RETURNS LENGTH ;
   RETURN WITH THE_X ( P1 ) AS X1 ,
            THE_X ( P2 ) AS X2 ,
            THE_Y ( P1 ) AS Y1 ,
            THE_Y ( P2 ) AS Y2 ,
            SORT ( ( X1 - X2 ) ** 2 + ( Y1 - Y2 ) ** 2 ) ) ;

END OPERATOR ;

Эта операция, DIST (“расстояние”) определяется с двумя параметров P 1 и P 2 объявленного типа POINT , и возвращает результат объявленного типа LENGTH . Операции THE _ X и THE _ Y используются для получения координат X и Y двух рассматриваемых точек, затем эти координаты используются для получения требуемого расстояния. WITH позволяет ввести сокращения для некоторых выражений.

Для определенности принимается, что аргументы вызовов операций задаются в  позиционной нотации, т.е. в данном вызове i -й аргумент в списке аргументов  соответствует i -му параметру в списке параметров определения операции.

Вот пример операции обновления:

OPERATOR REFLECT ( P POINT ) UPDATES P ;
   BEGIN ;
      THE_X ( P ) := THE_X ( P ) ;
      THE_Y ( P ) := THE_Y ( P ) ;
      RETURN ;

END OPERATOR ;

Операция REFLECT фактически перемещает точку с декартовыми координатами (x ,y ) в центрально-симметричную точку (- x ,- y ). Операция определяется с одним параметром P объявленного типа POINT и при вызове должным образом обновляет аргумент, соответствующий этому параметру. Как в предыдущем примере, операции THE _ X и THE _ Y используются для “чтения” координат X и Y заданной точки; псевдопеременныеTHE _ X и THE _ Y используются для обновления этих координат. Вызов REFLECT не возвращает результата; такой вызов не имеет значения и не является скалярным выражением. Поэтому вызов должен выполняться посредством явного оператора CALL (или некоторого его логического эквивалента).


Содержание раздела