35.2. Типовая система Tantor BE#
35.2. Типовая система Tantor BE #
Tantor BE типы данных могут быть разделены на базовые типы, контейнерные типы, домены и псевдо-типы.
35.2.1. Базовые типы #
Базовые типы - это те, такие как integer
, которые реализованы на уровне языка SQL
(обычно на низкоуровневом языке, таком как C). Они обычно
соответствуют тому, что часто называют абстрактными типами данных.
Tantor BE может работать только с такими
типами через функции, предоставленные пользователем, и понимает
поведение таких типов только в той степени, в которой его описывает
пользователь.
Встроенные базовые типы описаны в Глава 8.
Перечисляемые (enum) типы могут рассматриваться как подкатегория базовых типов. Основное отличие заключается в том, что они могут быть созданы с использованием только команд SQL, без какого-либо низкоуровневого программирования. См. Раздел 8.7 для получения дополнительной информации.
35.2.2. Типы контейнеров #
Tantor BE имеет три вида типов “контейнеров”, которые являются типами, содержащими несколько значений других типов. Это массивы, составные типы и диапазоны.
Массивы могут содержать несколько значений одного и того же типа. Для каждого базового типа, составного типа, диапазонного типа и типа домена автоматически создается тип массива. Однако массивов массивов не существует. С точки зрения системы типов, многомерные массивы идентичны одномерным массивам. Дополнительную информацию см. в разделе Раздел 8.15.
Композитные типы, или типы строк, создаются каждый раз, когда пользователь создает таблицу. Также возможно использование CREATE TYPE для определения “независимого” композитного типа без связанной таблицы. Композитный тип представляет собой просто список типов с соответствующими именами полей. Значение композитного типа представляет собой строку или запись значений полей. Дополнительную информацию см. в разделе Раздел 8.16.
Тип диапазона может содержать два значения одного типа, которые являются нижней и верхней границами диапазона. Типы диапазонов создаются пользователем, хотя существуют и несколько встроенных. Дополнительную информацию см. в разделе Раздел 8.17.
35.2.3. Домены #
Домен основан на определенном базовом типе и во многих случаях может быть взаимозаменяем с его базовым типом. Однако домен может иметь ограничения, которые ограничивают его допустимые значения подмножеством того, что позволяет базовый тип. Домены создаются с использованием команды SQL CREATE DOMAIN. Дополнительную информацию см. в разделе Раздел 8.18.
35.2.4. Псевдо-типы #
Есть несколько “псевдо-типов” для специальных целей. Псевдо-типы не могут быть использованы в качестве столбцов таблиц или компонентов контейнерных типов, но они могут быть использованы для объявления аргументов и типов результатов функций. Это предоставляет механизм внутри системы типов для идентификации специальных классов функций. Таблица 8.27 перечисляет существующие псевдо-типы.
35.2.5. Полиморфные типы #
Некоторые псевдо-типы особого интереса - это полиморфные типы, которые используются для объявления полиморфных функций. Эта мощная функция позволяет одному определению функции работать с различными типами данных, с конкретными типами данных, определяемыми фактически переданными типами данных в конкретном вызове. Полиморфные типы показаны в Таблица 35.1. Некоторые примеры их использования приведены в Раздел 35.5.11.
Таблица 35.1. Полиморфные типы
Имя | Семейство | Описание |
---|---|---|
anyelement | Simple | IУказывает, что функция принимает любой тип данных |
anyarray | Simple | Указывает, что функция принимает любой тип данных массива |
anynonarray | Simple | Указывает, что функция принимает любой не-массивный тип данных |
anyenum | Simple | Указывает, что функция принимает любой перечислимый тип данных (см. Раздел 8.7) |
anyrange | Simple | Указывает, что функция принимает любой тип данных диапазона (см. Раздел 8.17) |
anymultirange | Simple | Указывает, что функция принимает любой тип данных мультидиапазона (см. Раздел 8.17) |
anycompatible | Common | Указывает, что функция принимает любой тип данных, с автоматическим преобразованием нескольких аргументов в общий тип данных |
anycompatiblearray | Common | Указывает, что функция принимает любой тип данных массива, с автоматическим преобразованием нескольких аргументов в общий тип данных |
anycompatiblenonarray | Common | Указывает, что функция принимает любой немассивный тип данных, с автоматическим преобразованием нескольких аргументов в общий тип данных |
anycompatiblerange | Common | Указывает, что функция принимает любой тип данных диапазона, с автоматическим преобразованием нескольких аргументов в общий тип данных |
anycompatiblemultirange | Common | Указывает, что функция принимает любой тип данных мультидиапазона, с автоматическим преобразованием нескольких аргументов в общий тип данных |
Полиморфные аргументы и результаты связаны друг с другом и разрешаются в конкретные типы данных при разборе запроса, вызывающего полиморфную функцию. Когда есть более одного полиморфного аргумента, фактические типы данных входных значений должны соответствовать, как описано ниже. Если тип результата функции является полиморфным или у нее есть выходные параметры полиморфных типов, типы этих результатов выводятся из фактических типов полиморфных входов, как описано ниже.
Для семейства полиморфных типов “simple” правила сопоставления и вывода работают следующим образом:
Каждая позиция (аргумент или возвращаемое значение), объявленная как anyelement
, может иметь любой конкретный фактический тип данных, но в каждом вызове они должны быть одного и того же фактического типа. Каждая позиция, объявленная как anyarray
, может иметь любой тип массива, но также они должны быть одного типа. И аналогично, позиции, объявленные как anyrange
, должны быть одного и того же типа диапазона. То же самое относится и к anymultirange
.
Кроме того, если объявлены позиции с типом anyarray
и другие объявлены с типом anyelement
, фактический тип массива в позициях anyarray
должен быть массивом, элементы которого имеют тот же тип, что и в позициях anyelement
. anynonarray
обрабатывается точно так же, как и anyelement
, но добавляет дополнительное ограничение, что фактический тип не должен быть типом массива. anyenum
обрабатывается точно так же, как и anyelement
, но добавляет дополнительное ограничение, что фактический тип должен быть типом перечисления.
Аналогично, если объявлены позиции anyrange
и другие объявлены anyelement
или anyarray
, фактический тип диапазона в позициях anyrange
должен быть диапазоном, чей подтип является тем же типом, который появляется в позициях anyelement
и таким же, как тип элемента позиций anyarray
.
Если объявлены позиции anymultirange
, их фактический тип мультидиапазона должен содержать диапазоны, соответствующие параметрам, объявленным anyrange
, и базовые элементы, соответствующие параметрам, объявленным anyelement
и anyarray
.
Таким образом, когда более одной позиции аргумента объявляется с полиморфным типом, чистый эффект заключается в том, что разрешены только определенные комбинации фактических типов аргументов. Например, функция, объявленная как equal(anyelement, anyelement)
, примет любые два входных значения, при условии, что они имеют один и тот же тип данных.
Когда возвращаемое значение функции объявлено как полиморфный тип, должно быть хотя бы одно полиморфное положение аргумента, и фактический тип данных, предоставленный для полиморфных аргументов, определяет фактический тип результата для этого вызова. Например, если бы не было механизма индексации массива, можно было бы определить функцию, которая реализует индексацию как subscript(anyarray, integer) returns anyelement
. Это объявление ограничивает фактический первый аргумент типом массива и позволяет парсеру вывести правильный тип результата из типа фактического первого аргумента. Другой пример - функция, объявленная как f(anyarray) returns anyenum
, будет принимать только массивы типов перечислений.
В большинстве случаев парсер может определить фактический тип данных для полиморфного результата на основе аргументов, которые имеют разные полиморфные типы в одной семье; например, тип anyarray
может быть выведен из типа anyelement
и наоборот. Исключение составляет полиморфный результат типа anyrange
, который требует аргумента типа anyrange
; его нельзя вывести из аргументов типа anyarray
или anyelement
. Это связано с тем, что может существовать несколько типов диапазонов с одним и тем же подтипом.
Обратите внимание, что anynonarray
и anyenum
не представляют
отдельные типовые переменные; они являются тем же типом, что и
anyelement
, только с дополнительным ограничением. Например,
объявление функции как f(anyelement, anyenum)
эквивалентно объявлению f(anyenum, anyenum)
:
оба фактических аргумента должны быть одного и того же типа перечисления.
Для семейства полиморфных типов “common” правила сопоставления и вывода работают примерно так же, как и для семейства “simple”, с одним основным отличием: фактические типы аргументов не обязательно должны быть идентичными, достаточно, чтобы они могли быть неявно приведены к одному общему типу. Общий тип выбирается в соответствии с теми же правилами, что и для UNION
и связанных конструкций (см. Раздел 10.5). При выборе общего типа учитываются фактические типы входных данных anycompatible
и anycompatiblenonarray
, типы элементов массива входных данных anycompatiblearray
, подтипы диапазона входных данных anycompatiblerange
и подтипы мультидиапазона входных данных anycompatiblemultirange
. Если присутствует anycompatiblenonarray
, то общий тип должен быть не массивным типом. После определения общего типа аргументы в позициях anycompatible
и anycompatiblenonarray
автоматически приводятся к этому типу, а аргументы в позициях anycompatiblearray
автоматически приводятся к типу массива для этого типа.
Поскольку нет способа выбрать тип диапазона, зная только его подтип, использование типов anycompatiblerange
и/или anycompatiblemultirange
требует, чтобы все аргументы, объявленные с этим типом, имели один и тот же фактический тип диапазона и/или множественного диапазона, и чтобы подтип этого типа согласовывался с выбранным общим типом, так что приведение значений диапазона не требуется. Как и в случае с типами anyrange
и anymultirange
, использование типов anycompatiblerange
и anymultirange
в качестве типа результата функции требует наличия аргумента anycompatiblerange
или anycompatiblemultirange
.
Обратите внимание, что типа anycompatibleenum
не существует. Такой тип был бы не очень полезным, поскольку обычно нет неявных преобразований к типам перечислений, что означает, что не будет способа определить общий тип для различных входных значений перечислений.
“Простые (simple)” и “общие (common)” полиморфные семейства представляют два независимых набора типовых переменных. Рассмотрим, например
CREATE FUNCTION myfunc(a anyelement, b anyelement, c anycompatible, d anycompatible) RETURNS anycompatible AS ...
В фактическом вызове этой функции первые два входа должны иметь точно такой же тип. Последние два входа должны быть приводимыми к общему типу, но этот тип не обязательно должен иметь что-то общее с типом первых двух входов. Результат будет иметь общий тип последних двух входов.
Вариативная функция (принимающая переменное количество аргументов, как в Раздел 35.5.6) может быть полиморфной: это достигается путем объявления ее последнего параметра как VARIADIC
anyarray
или VARIADIC
anycompatiblearray
. Для целей сопоставления аргументов и определения фактического типа результата такая функция ведет себя так же, как если бы вы написали соответствующее количество параметров anynonarray
или anycompatiblenonarray
.