40.14. Пользовательские операторы
Любой оператор представляет собой «синтаксический сахар» для вызова нижележащей функции, выполняющей реальную работу; поэтому прежде чем вы сможете создать оператор, необходимо создать нижележащую функцию. Однако оператор — не исключительно синтаксический сахар, так как он несёт и дополнительную информацию, помогающую планировщику запросов оптимизировать запросы с этим оператором. Рассмотрению этой дополнительной информации будет посвящён следующий раздел.
Postgres Pro поддерживает префиксные и инфиксные операторы. Операторы могут быть перегружены; то есть одно имя оператора могут иметь различные операторы с разным количеством и типами операндов. Когда выполняется запрос, система определяет, какой оператор вызвать, по количеству и типам предоставленных операндов.
В следующем примере создаётся оператор сложения двух комплексных чисел. Предполагается, что мы уже создали определение типа complex
(см. Раздел 40.13). Сначала нам нужна функция, собственно выполняющая операцию, а затем мы сможем определить оператор:
CREATE FUNCTION complex_add(complex, complex)
RETURNS complex
AS 'имя_файла
', 'complex_add'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR + (
leftarg = complex,
rightarg = complex,
function = complex_add,
commutator = +
);
Теперь мы можем выполнить такой запрос:
SELECT (a + b) AS c FROM test_complex; c ----------------- (5.2,6.05) (133.42,144.95)
Мы продемонстрировали создание бинарного оператора. Чтобы создать префиксный оператор, просто опустите leftarg
. Обязательными в CREATE OPERATOR
являются только предложение function
и объявления аргументов. Предложение commutator
, добавленное в данном примере, представляет необязательную подсказку для оптимизатора запросов. Подробнее о commutator
и других подсказках для оптимизатора рассказывается в следующем разделе.
40.14. User-Defined Operators
Every operator is “syntactic sugar” for a call to an underlying function that does the real work; so you must first create the underlying function before you can create the operator. However, an operator is not merely syntactic sugar, because it carries additional information that helps the query planner optimize queries that use the operator. The next section will be devoted to explaining that additional information.
Postgres Pro supports prefix and infix operators. Operators can be overloaded; that is, the same operator name can be used for different operators that have different numbers and types of operands. When a query is executed, the system determines the operator to call from the number and types of the provided operands.
Here is an example of creating an operator for adding two complex numbers. We assume we've already created the definition of type complex
(see Section 40.13). First we need a function that does the work, then we can define the operator:
CREATE FUNCTION complex_add(complex, complex)
RETURNS complex
AS 'filename
', 'complex_add'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR + (
leftarg = complex,
rightarg = complex,
function = complex_add,
commutator = +
);
Now we could execute a query like this:
SELECT (a + b) AS c FROM test_complex; c ----------------- (5.2,6.05) (133.42,144.95)
We've shown how to create a binary operator here. To create a prefix operator, just omit the leftarg
. The function
clause and the argument clauses are the only required items in CREATE OPERATOR
. The commutator
clause shown in the example is an optional hint to the query optimizer. Further details about commutator
and other optimizer hints appear in the next section.