Привет, Я DocuDroid!
Оценка ИИ поиска
Спасибо за оценку нашего ИИ поиска!
Мы будем признательны, если вы поделитесь своими впечатлениями, чтобы мы могли улучшить наш ИИ поиск для вас и других читателей.
GitHub

CREATE OPERATOR

Определяет новый оператор.

Синтаксис

CREATE OPERATOR <name> (
       PROCEDURE = <funcname>
       [, LEFTARG = <lefttype>] [, RIGHTARG = <righttype>]
       [, COMMUTATOR = <com_op>] [, NEGATOR = <neg_op>]
       [, RESTRICT = <res_proc>] [, JOIN = <join_proc>]
       [, HASHES] [, MERGES] )

Описание

CREATE OPERATOR определяет новый оператор. Пользователь, определивший оператор, становится его владельцем.

Имя оператора представляет собой последовательность символов из набора + - * / < > = ~ ! @ # % ^ & | ` ?, длина которой — не больше значения константы NAMEDATALEN минус 1, то есть по умолчанию — не больше 63.

Существует несколько ограничений на выбор имени:

  • Сочетания символов -- и /* не могут использоваться в имени оператора, так как будут восприниматься как начало комментария.

  • Многосимвольное имя оператора не может оканчиваться на + или -, если только имя также не содержит хотя бы один из следующих символов: ~ ! @ # % ^ & | ` ?.

Например, @- — допустимое имя оператора, а *- — нет. Это ограничение позволяет Greengage DB разбирать SQL-совместимые команды, не требуя пробелов между токенами.

Использование => в качестве имени оператора считается устаревшим.

Оператор != при вводе маппится на <>, поэтому эти два имени всегда эквивалентны.

Должен быть определен как минимум один из параметров LEFTARG и RIGHTARG. Для бинарных операторов должны быть определены оба. Для правых унарных операторов следует определять только LEFTARG, а для левых унарных операторов — только RIGHTARG.

Процедура funcname должна быть предварительно определена с помощью CREATE FUNCTION, должна быть IMMUTABLE и должна быть определена так, чтобы принимать корректное число аргументов (один или два) указанных типов.

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

Чтобы создать оператор, требуется иметь привилегию USAGE для типов аргументов и типа результата, а также привилегию EXECUTE для базовой функции. Если указан оператор-коммутатор или оператор-негатор, требуется владеть этими операторами.

Параметры

Параметр Описание

name

Имя определяемого оператора (при необходимости со схемой). Два оператора в одной и той же схеме могут иметь одно и то же имя, если они работают с разными типами данных

funcname

Функция, используемая для реализации этого оператора (должна иметь свойство IMMUTABLE)

lefttype

Тип данных левого операнда оператора, если он есть. Этот параметр опускается для лево-унарного оператора

righttype

Тип данных правого операнда оператора, если он есть. Этот параметр опускается для право-унарного оператора

com_op

Необязательное выражение COMMUTATOR задает имя оператора, который является коммутатором определяемого оператора. Говорят, что оператор A является коммутатором оператора B, если (x A y) равно (y B x) для всех возможных входных значений x, y. Обратите внимание, что B также является коммутатором A. Например, операторы < и > для конкретного типа данных обычно являются коммутаторами друг друга, а оператор + обычно коммутативен сам с собой. Но оператор - обычно не коммутативен ни с чем. Тип левого операнда коммутируемого оператора совпадает с типом правого операнда его коммутатора, и наоборот. Поэтому в выражении COMMUTATOR достаточно указать только имя оператора-коммутатора

neg_op

Необязательное выражение NEGATOR задает имя оператора, который является обратным оператором определяемого оператора. Говорят, что оператор A является обратным оператором оператора B, если оба возвращают логический результат и (x A y) равно NOT (x B y) для всех возможных входных значений x, y. Обратите внимание, что B также является обратным оператором A. Например, < и >= являются парой обратных операторов для большинства типов данных. Обратный оператор должен иметь те же типы левого и/или правого операндов, что и определяемый оператор, поэтому в выражении NEGATOR достаточно указать только имя оператора

res_proc

Необязательное выражение RESTRICT задает функцию оценки селективности ограничения для оператора. Обратите внимание, что это имя функции, а не имя оператора. Выражения RESTRICT имеют смысл только для бинарных операторов, возвращающих boolean. Идея оценщика селективности ограничения состоит в том, чтобы угадать, какая доля строк таблицы удовлетворит условию в выражении WHERE вида:

column OP constant

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

  • eqsel для =.

  • neqsel для <>.

  • scalarltsel для < или <=.

  • scalargtsel для > или >=.

join_proc

Необязательное выражение JOIN задает функцию оценки селективности соединения для оператора. Обратите внимание, что это имя функции, а не имя оператора. Выражения JOIN имеют смысл только для бинарных операторов, возвращающих boolean. Идея функции-оценщика селективности соединения состоит в том, чтобы угадать, какая доля строк в паре таблиц удовлетворит условию в выражении WHERE вида:

table1.column1 OP table2.column2

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

  • eqjoinsel для =.

  • neqjoinsel для <>.

  • scalarltjoinsel для < или <=.

  • scalargtjoinsel для > или >=.

  • areajoinsel для двумерных сравнений на основе площади.

  • positionjoinsel для двумерных сравнений на основе позиции.

  • contjoinsel для двумерных сравнений на основе включения

HASHES

Необязательное выражение HASHES сообщает системе, что допустимо использовать метод хеш-соединения (hash join) для соединения на основе этого оператора. HASHES имеет смысл только для бинарного оператора, возвращающего boolean. Оператор хеш-соединения может возвращать true только для пар левых и правых значений, которые хешируются в один и тот же хеш-код. Если два значения попадают в разные хеш-бакеты, соединение никогда не будет их сравнивать, неявно предполагая, что результат оператора соединения должен быть false. Поэтому никогда не имеет смысла указывать HASHES для операторов, которые не представляют равенство.

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

Чтобы быть помеченным как HASHES, оператор соединения должен присутствовать в классе операторов хеш-индекса. Попытки использовать оператор в хеш-соединении завершатся ошибкой во время выполнения, если такого класса операторов не существует. Системе нужен класс операторов, чтобы найти зависящую от типа данных хеш-функцию для входного типа данных оператора. Также необходимо предоставить подходящую хеш-функцию до того, как сможете создать класс операторов. Будьте внимательны при подготовке хеш-функции, так как существуют машинно-зависимые способы, при которых она может работать некорректно. Например, на машинах, соответствующих стандарту IEEE для чисел с плавающей точкой, отрицательный ноль и положительный ноль — разные значения (разные битовые шаблоны), но определены как равные при сравнении. Если значение типа float может содержать отрицательный ноль, определите хеширование так, чтобы оно генерировало тот же хеш, что и для положительного ноля.

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

ПРИМЕЧАНИЕ

Функция, лежащая в основе хеш-соединяемого оператора, должна быть помечена как immutable или stable. Оператор, помеченный как volatile, использоваться не будет. Если у хеш-соединяемого оператора базовая функция помечена как strict, функция также должна быть полной, возвращая true или false, а не null, для любых двух ненулевых входных значений.

MERGES

Выражение MERGES, если присутствует, сообщает системе, что допустимо использовать метод соединения слиянием (merge join) для соединения на основе этого оператора. MERGES имеет смысл только для бинарного оператора, возвращающего boolean, и на практике оператор должен представлять равенство для некоторого типа данных или пары типов данных.

Соединение слиянием основано на идее сортировки левой и правой таблицы по порядку с последующим параллельным сканированием. Это означает, что оба типа данных должны быть полностью упорядочиваемыми, а оператор соединения должен быть таким, который может успешно сработать только для пар значений, находящихся в эквивалентных позициях в порядке сортировки. На практике это означает, что оператор соединения должен вести себя как оператор равенства. Однако вы можете выполнять соединение слиянием для двух различных типов данных, если они логически совместимы. Например, оператор равенства smallint-versus-integer поддерживает соединение слиянием. Необходимы лишь те операторы сравнения, которые обеспечивают для обоих типов данных логически согласованный порядок.

Чтобы быть помеченным как MERGES, оператор соединения должен присутствовать как член равенства в семействе операторов B-tree. Это условие не проверяется при создании оператора, поскольку ссылаемое семейство операторов на тот момент еще не существует. Однако оператор фактически не будет использоваться для соединения слиянием, если не удастся найти подходящее семейство операторов. Таким образом, флаг MERGE действует как подсказка планировщику искать соответствующее семейство операторов. Оператор, поддерживающий соединение слиянием, должен иметь коммутатор, который присутствует в том же семействе операторов. Это будет он сам, если типы операндов совпадают, или связанный оператор равенства, если типы данных различаются. Без подходящего коммутатора при использовании оператора могут возникать ошибки планировщика. Также, хотя это и не строго обязательно, семейство операторов B-tree, поддерживающее несколько типов данных, должно уметь предоставлять операторы равенства для каждой комбинации типов данных, так как это дает лучшую оптимизацию.

ПРИМЕЧАНИЕ

SORT1, SORT2, LTCMP и GTCMP ранее использовались для задания имен сортировочных операторов, связанных с merge-joinable оператором. Информация о связанных операторах теперь определяется по семействам операторов B-tree. Указание любого из этих операторов будет проигнорировано, за исключением того, что оно неявно установит MERGES в true.

Примечания

Все функции, используемые для реализации оператора, должны быть определены как IMMUTABLE.

Нельзя указать лексический приоритет оператора в CREATE OPERATOR, поскольку правила приоритета в парсере жестко заданы. Подробности о приоритетах см. статью Operator Precedence в документации PostgreSQL.

Используйте DROP OPERATOR, чтобы удалить пользовательские операторы из базы данных. Используйте ALTER OPERATOR, чтобы изменить операторы в базе данных.

Примеры

Ниже приведен пример создания оператора для сложения двух комплексных чисел при условии, что уже создано определение типа complex. Сначала определите функцию, которая выполняет операцию, затем определите сам оператор:

CREATE FUNCTION complex_add(complex, complex)
    RETURNS complex
AS
'filename',
'complex_add'
    LANGUAGE C IMMUTABLE
               STRICT;

CREATE OPERATOR + (
    leftarg = complex,
    rightarg = complex,
    procedure = complex_add,
    commutator = +
    );

Чтобы использовать этот оператор в запросе, выполните:

SELECT (a + b) AS c FROM test_complex;

Совместимость

CREATE OPERATOR — расширение языка Greengage DB. Стандарт SQL не предусматривает пользовательские операторы.

См. также