×
Мы обрабатываем cookies, чтобы сделать наш сайт удобнее и персонализированнее для вас. Подробнее: политика использования «cookies» и «политики конфиденциальности».

Для самостоятельной настройки ознакомьтесь с инструкцией

Дополнительные настройки cookies в браузерах

Файлы cookie автоматически загружаются в ваш браузер при посещении веб-сайта. У вас есть возможность управлять этими файлами. Если Вы не согласны с использованием файлов cookies, запретите их сохранение на своём устройстве, удалите уже имеющиеся файлы cookies через настройки браузера или прекратите использование сайта.

При отключении обработки cookie наш сайт продолжит функционировать, однако будут использоваться исключительно необходимые технические файлы, без которых работа ресурса невозможна.

Инструкция по отключению cookies
Принять
Настроить
Отклонить

ДОКУМЕНТАЦИЯ

Выберите версию, форк и язык для СУБД Digital Q.DataBase, чтобы прочитать или скачать всю документацию.
Техподдержка
Документация
Диасофт
Авторские права © 2016–2025 ООО "Диасофт Экосистема"
Скачать всю документацию:

2.7.2. Операторы

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

Разрешение типов данных в операторах

  1. Выберите рассматриваемые операторы из pg_operator системного каталога. Если было использовано имя оператора без указания схемы (обычный случай), рассматриваются операторы с соответствующим именем и количеством аргументов, которые видимы в текущем пути поиска (см. Раздел 2.2.10.3). Если было указано имя оператора с квалификатором схемы, рассматриваются только операторы в указанной схеме.

    1. Если в пути поиска обнаруживается несколько операторов с идентичными типами аргументов, рассматривается только тот, который встречается в пути первым. Операторы с различными типами аргументов рассматриваются на равных условиях независимо от их позиции в пути поиска.

  2. Проверьте наличие оператора, принимающего именно такие типы входных аргументов. Если такой оператор существует (в наборе рассматриваемых операторов может быть только одно точное совпадение), используйте его. Отсутствие точного совпадения создает угрозу безопасности при вызове через полное имя [9] (что нетипично), любой оператор, найденный в схеме, позволяющей недоверенным пользователям создавать объекты. В таких ситуациях следует выполнить приведение типов аргументов, чтобы добиться точного соответствия.

    1. Если один аргумент вызова бинарного оператора имеет unknown тип данных, тогда для этой проверки предполагается, что он имеет тот же тип данных, что и второй аргумент. Вызовы, в которых участвуют два unknown входных значения, или префиксный оператор с unknown входным значением, на данном этапе никогда не найдут соответствия.

    2. Если один аргумент вызова бинарного оператора имеет unknown тип данных, а другой — доменный тип, далее следует проверить, существует ли оператор, принимающий именно базовый тип данных домена с обеих сторон; если это так, используйте его.

  3. Поиск наилучшего соответствия.

    1. Исключите операторы-кандидаты, для которых типы входных данных не совпадают и не могут быть преобразованы (с помощью неявного приведения типов) для обеспечения соответствия. unknown предполагается, что литералы могут быть приведены к любому типу данных для этой цели. Если остался только один кандидат, используйте его; в противном случае перейдите к следующему шагу.

    2. Если какой-либо входной аргумент относится к типу данных домена, он рассматривается как имеющий базовый тип данных домена на всех последующих этапах. Это гарантирует, что домены ведут себя так же, как их базовые типы данных, для целей разрешения неоднозначности операторов.

    3. Просмотрите всех кандидатов и оставьте тех, у которых наблюдается наибольшее количество точных совпадений по типам данных входных аргументов. Оставьте всех кандидатов, если ни у одного из них нет точных совпадений. Если остался только один кандидат, используйте его; в противном случае перейдите к следующему шагу.

    4. Просмотрите всех кандидатов и оставьте тех, которые принимают предпочтительные типы данных (из категории входного типа данных) в наибольшем количестве позиций, где требуется приведение типов. Сохраните всех кандидатов, если ни один из них не принимает предпочтительные типы данных. Если остался только один кандидат, используйте его; в противном случае перейдите к следующему шагу.

    5. Если какие-либо входные аргументы являются unknown, проверьте категории типов данных, принимаемые в данных позициях аргументов оставшимися кандидатами. Для каждой позиции выберите string категорию, если какой-либо кандидат принимает эту категорию. (Такое смещение в сторону строковых типов уместно, поскольку литерал неизвестного типа выглядит как строка.) В противном случае, если все оставшиеся кандидаты принимают одну и ту же категорию типов данных, выберите эту категорию; в противном случае работа завершится ошибкой, так как правильный выбор невозможно сделать без дополнительных уточняющих данных. Теперь исключите кандидатов, которые не принимают выбранную категорию типов данных. Более того, если какой-либо кандидат принимает предпочтительный тип данных в этой категории, исключите кандидатов, принимающих непредпочтительные типы для данного аргумента. Сохраните всех кандидатов, если после этих проверок не осталось ни одного. Если остался только один кандидат, используйте его; в противном случае перейдите к следующему шагу.

    6. Если присутствуют как unknown , так и аргументы известного типа, и при этом все аргументы известного типа имеют один и тот же тип данных, следует предположить, что unknown аргументы также имеют этот тип, и проверить, какие кандидаты могут принять этот тип в unknown-позиции аргументов. Если данную проверку проходит ровно один кандидат, используйте его. В противном случае работа завершится ошибкой.

Ниже приведено несколько примеров.

Пример 2.7.1. Разрешение типов для оператора извлечения квадратного корня

Существует только один оператор извлечения квадратного корня (префиксный |/) определен в стандартном каталоге и принимает аргумент типа данных double precision. Сканер назначает начальный тип данных integer для аргумента в данном выражении запроса:

SELECT |/ 40 AS "square root of 40";
 square root of 40
-------------------
 6.324555320336759
(1 row)

Таким образом, парсер выполняет приведение типов для операнда, и запрос становится эквивалентен:

SELECT |/ CAST(40 AS double precision) AS "square root of 40";


Пример 2.7.2. Разрешение типов для оператора конкатенации строк

Строковый синтаксис используется как для работы со строковыми типами данных, так и для работы со сложными типами расширений. Строковые литералы с неуказанным типом сопоставляются с наиболее подходящими операторами-кандидатами.

Пример с одним аргументом неизвестного типа:

SELECT text 'abc' || 'def' AS "text and unknown";

 text and unknown
------------------
 abcdef
(1 row)

В данном случае парсер проверяет, существует ли оператор, принимающий text для обоих аргументов. Так как он существует, предполагается, что второй аргумент должен быть интерпретирован как тип данных text.

Ниже приведен пример конкатенации двух значений неопределенных типов:

SELECT 'abc' || 'def' AS "unspecified";

 unspecified
-------------
 abcdef
(1 row)

В данном случае нет исходной подсказки о том, какой тип данных использовать, так как в запросе типы не указаны. Поэтому парсер ищет все подходящие операторы и находит кандидатов, принимающих входные данные как строковой категории, так и категории битовых строк. Так как строковая категория является предпочтительной, выбирается именно она, а затем предпочтительный тип данных для строк, text, используется в качестве конкретного типа для разрешения литералов неизвестного типа.


Пример 2.7.3. Разрешение типов для операторов модуля и отрицания

Компонент Digital Q.DataBase каталог операторов содержит несколько записей для префиксного оператора @, все из которых реализуют операции вычисления модуля для различных числовых типов данных. Одна из этих записей предназначена для типа данных float8, который является предпочтительным типом в числовой категории. Следовательно, Digital Q.DataBase будет использовать эту запись при наличии unknown входные данные:

SELECT @ '-4.5' AS "abs";
 abs
-----
 4.5
(1 row)

В данном случае система неявно разрешила литерал неизвестного типа как тип данных float8 перед применением выбранного оператора. Мы можем убедиться в том, что float8 использовался именно этот, а не какой-либо другой тип данных:

SELECT @ '-4.5e500' AS "abs";

ERROR:  "-4.5e500" is out of range for type double precision

С другой стороны, префиксный оператор ~ (побитовое отрицание) определен только для целочисленных типов данных, но не для float8. Следовательно, если мы рассмотрим аналогичный случай с ~, то получим:

SELECT ~ '20' AS "negation";

ERROR:  operator is not unique: ~ "unknown"
HINT:  Could not choose a best candidate operator. Возможно, вам потребуется добавить явный оператор CAST.

Это происходит потому, что система не может выбрать один из нескольких возможных ~ следует отдавать предпочтение операторам. Эту ситуацию можно разрешить с помощью явного приведения типов:

SELECT ~ CAST('20' AS int8) AS "negation";

 negation
----------
      -21
(1 row)


Пример 2.7.4. Определение типов для оператора включения массива

Вот еще один пример разрешения типов для оператора с одним известным и одним неизвестным аргументом:

SELECT array[1,2] <@ '{1,2,3}' as "is subset";

 is subset
-----------
 t
(1 row)

Компонент Digital Q.DataBase каталог операторов содержит несколько записей для инфиксного оператора <@, но только две из них могут принимать массив integer с левой стороны: это операторы включения массива (anyarray <@ anyarray) и включения в диапазон (anyelement <@ anyrange). Поскольку ни один из этих полиморфных псевдотипов (см. Раздел 2.5.21) не является предпочтительным, парсер не может разрешить неоднозначность на этом основании. Тем не менее Шаг 3.f позволяет ему предположить, что литерал неизвестного типа имеет тот же тип данных, что и второй аргумент, а именно массив integer. Теперь только один из двух операторов может соответствовать условию, поэтому выбирается оператор включения массивов. (Если бы был выбран механизм включения диапазонов, возникла бы ошибка, так как строка не имеет корректного формата для литерала диапазона.)


Пример 2.7.5. Пользовательский оператор для типа-домена

Пользователи иногда пытаются объявить операторы, применяемые только к типу-домену. Это возможно, но далеко не так полезно, как может показаться, поскольку правила разрешения операторов разработаны для выбора операторов, применяемых к базовому типу данных домена. В качестве примера рассмотрим

CREATE DOMAIN mytext AS text CHECK(...);
CREATE FUNCTION mytext_eq_text (mytext, text) RETURNS boolean AS ...;
CREATE OPERATOR = (procedure=mytext_eq_text, leftarg=mytext, rightarg=text);
CREATE TABLE mytable (val mytext);

SELECT * FROM mytable WHERE val = 'foo';

Данный запрос не будет использовать пользовательский оператор. Парсер сначала проверит, существует ли mytext = mytext оператор (Шаг 2.a), которого не существует; тогда будет рассмотрен базовый тип данных домена text, и проверено, существует ли text = text оператор (Шаг 2.b), который существует; таким образом, литерал типа unknownбудет определен как text и будет использован text = text оператор. Единственный способ задействовать пользовательский оператор — явно выполнить приведение типов литерала:

SELECT * FROM mytable WHERE val = text 'foo';

чтобы mytext = text оператор был найден сразу согласно правилу точного соответствия. Если применяются правила поиска наилучшего соответствия, они отдают меньший приоритет операторам для типов-доменов. Если бы это было не так, подобные операторы создавали бы слишком много ошибок из-за двусмысленности, поскольку правила приведения типов всегда рассматривают домен как приводимый к своему базовому типу данных или из него, и оператор домена считался бы применимым во всех тех же случаях, что и одноименный оператор для базового типа данных.




[9] Данная проблема не возникает при использовании имен, не квалифицированных схемой, поскольку путь поиска, содержащий схемы, в которых недоверенным пользователям разрешено создавать объекты, не представляет собой безопасный шаблон использования схем.

Наверх
свяжитесь
с нами
контакты
Для прямой связи с нами вы можете использовать контакты ниже, либо оставить заявку через форму обратной связи, и мы обязательно свяжемся с вами

*поля обязательные к заполнению