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 |
Функция, используемая для реализации этого оператора (должна иметь свойство |
lefttype |
Тип данных левого операнда оператора, если он есть. Этот параметр опускается для лево-унарного оператора |
righttype |
Тип данных правого операнда оператора, если он есть. Этот параметр опускается для право-унарного оператора |
com_op |
Необязательное выражение |
neg_op |
Необязательное выражение |
res_proc |
Необязательное выражение
Это помогает оптимизатору, давая ему представление о том, сколько строк будет отфильтровано условиями
|
join_proc |
Необязательное выражение
Это помогает оптимизатору, позволяя ему определить, какая из нескольких возможных последовательностей соединений потребует наименьшей работы. Обычно для многих собственных операторов можно просто использовать одну из следующих стандартных системных функций-оценщиков соединений:
|
HASHES |
Необязательное выражение В большинстве случаев поддерживать хеширование практично только для операторов, которые принимают один и тот же тип данных с обеих сторон. Однако вы можете спроектировать совместимые хеш-функции для двух или более типов данных, то есть функции, которые будут генерировать одинаковые хеш-коды для "равных" значений, даже если значения представлены по-разному. Чтобы быть помеченным как Хеш-соединяемый оператор должен иметь коммутатор (самого себя, если типы операндов совпадают, или связанный оператор равенства, если они различаются), который присутствует в том же семействе операторов. Иначе при использовании оператора могут возникать ошибки планировщика. Для лучшей оптимизации семейство хеш-операторов, поддерживающее несколько типов данных, должно предоставлять операторы равенства для каждой комбинации типов данных. ПРИМЕЧАНИЕ
Функция, лежащая в основе хеш-соединяемого оператора, должна быть помечена как |
MERGES |
Выражение Соединение слиянием основано на идее сортировки левой и правой таблицы по порядку с последующим параллельным сканированием.
Это означает, что оба типа данных должны быть полностью упорядочиваемыми, а оператор соединения должен быть таким, который может успешно сработать только для пар значений, находящихся в эквивалентных позициях в порядке сортировки.
На практике это означает, что оператор соединения должен вести себя как оператор равенства.
Однако вы можете выполнять соединение слиянием для двух различных типов данных, если они логически совместимы.
Например, оператор равенства Чтобы быть помеченным как ПРИМЕЧАНИЕ
|
Примечания
Все функции, используемые для реализации оператора, должны быть определены как 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 не предусматривает пользовательские операторы.