CREATE OPERATOR

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)个字符的序列: + - * / < > = ~ ! @ # % ^ & | ` ?

名称的选择有一些限制:

  • --/*不能出现在运算符名称的任何位置,因为它们将被用作注释的开头。
  • 多字符运算符名称不能以+-结尾,除非该名称也包含以下至少一个字符: ~ ! @ # % ^ & | ` ?

例如,@-是允许的运算符名称,但*-不是。 此限制使Greenplum数据库可以解析与SQL兼容的命令,而无需在标记之间使用空格。

不建议将=>用作运算符。在将来的版本中可能完全不允许使用它。

运算符!=在输入时映射为<>,因此这两个名称始终相等。

必须至少定义LEFTARGRIGHTARG之一。 对于二元运算符,必须同时定义两者。 对于右一元运算符,仅应定义LEFTARG,而对于左一元运算符,仅应定义RIGHTARG

funcname过程必须事先使用CREATE FUNCTION定义, 必须是IMMUTABLE,并且必须定义为接受所指示类型的正确数量的参数(一个或两个)。

其他子句指定可选的运算符优化子句。 适当时应提供这些子句,以加快使用运算符的查询的速度。 但是,如果提供它们,则必须确保它们是正确的。 错误地使用优化子句可能导致服务器进程崩溃,错误的输出或其他意外结果。 如果您不确定优化子句,则可以始终忽略该子句。

为了能够创建运算符,您必须对参数类型和返回类型具有USAGE特权,并且对基础函数具有EXECUTE特权。 如果指定了换向或负运算符,则您必须拥有这些运算符。

参数

name
要定义的运算符的名称(可以由模式指定)。 如果同一模式中的两个运算符对不同的数据类型进行运算,则它们可以具有相同的名称。
funcname
用于实现此运算符的函数(必须为IMMUTABLE函数)。
lefttype
运算符的左操作数的数据类型(如果有)。 左一元运算符将忽略此选项。
righttype
运算符的右操作数的数据类型(如果有)。 右一元运算符将忽略此选项。
com_op
可选的COMMUTATOR子句命名一个运算符,该运算符是要定义的运算符的交换器。 我们说如果对于所有可能的输入值x,y,(x A y)等于(y B x),则算符A是算符B的交换子。 请注意,B也是A的交换子。 例如,特定数据类型的运算符<>通常是彼此的交换子,而运算符 + 通常是与自身交换的。 但是运算符-通常不与任何东西互换。 可交换运算符的左操作数类型与其交换器的右操作数类型相同,反之亦然。 因此,只需在COMMUTATOR子句中提供交换器运算符的名称即可。
neg_op
可选的NEGATOR子句命名一个运算符,该运算符是要定义的运算符的否定符。 我们说如果两个操作符都返回布尔结果,并且对于所有可能的输入x,y,(x A y)等于NOT(x B y),则运算符A是运算符B的否定符。 请注意,B也是A的否定符。例如,<>=是大多数数据类型的否定符对。 运算符的否定符必须具有与要定义的运算符相同的左右操作数类型,因此,在NEGATOR子句中仅需要指定运算符名称。
res_proc
可选的RESTRICT为运算符命名了一个限制选择性估计函数。 请注意,这是一个函数名称,而不是运算符名称。 RESTRICT子句仅对返回布尔值的二元运算符有意义。 限制选择性估计器背后的想法是猜测表中哪几部分行将满足以下形式的WHERE子句条件:
column OP constant
用于当前运算符和特定的常量值。 这有助于优化器了解具有这种形式的WHERE子句将消除多少行。
You can usually just use one of the following system standard estimator functions for many of your own operators:

eqsel 为 =

neqsel 为 <>

scalarltsel 为 < 或 <=

scalargtsel 为 > 或 >=

join_proc
可选的JOIN子句为运算符命名联接选择性估计函数。 请注意,这是一个函数名称,而不是运算符名称。 JOIN子句仅对返回布尔值的二元运算符有意义。 连接选择性估计器背后的想法是猜测一对表中的哪几部分行将满足以下WHERE子句条件
table1.column1 OP table2.column2
对于当前的运算符。通过让优化器找出几个可能的连接序列中哪一个可能花费最少的工作,可以帮助优化器。
通常,您可以对许多自己的运算符使用以下系统标准联接选择性估计器函数之一:

eqjoinsel 为 =

neqjoinsel 为 <>

scalarltjoinsel 为 < 或 <=

scalargtjoinsel 为 > 或 >=

areajoinsel 为基于2D区域的比较

positionjoinsel 为基于2D位置的比较

contjoinsel 为基于2D包含的比较

HASHES
可选的HASHES子句告诉系统允许使用哈希联接方法进行基于此运算符的联接。 HASHES仅对返回布尔值的二元运算符有意义。 哈希联接运算符只能对哈希到同一哈希代码的一对左右值返回true。 如果将两个值放在不同的哈希存储桶中,则联接将永远不会比较它们, 隐式地假设联接运算符的结果必须为false。 因此,为不表示相等性的运算符指定HASHES永远没有意义。
在大多数情况下,仅在两侧采用相同数据类型的运算符支持散列。 但是,您可以为两个或多个数据类型设计兼容的哈希函数, 即使这些值的表示方式不同,这些函数也会为“相等”值生成相同的哈希码。
要标记为HASHES,联接运算符必须出现在哈希索引运算符类中。 如果不存在此类运算符类,则尝试在哈希联接中使用运算符将在运行时失败。 系统需要运算符类为运算符的输入数据类型查找特定于数据类型的哈希函数。 在创建运算符类之前,还必须提供合适的哈希函数。 在准备散列函数时,请格外小心,因为存在与机器相关的方法,散列函数可能无法正确运行。 例如,在满足IEEE浮点标准的计算机上,负零和正零是不同的值(不同的位模式),但被定义为相等。 如果浮点值可以包含负零,则将其定义为生成与正零相同的哈希值。
可哈希连接的运算符必须具有出现在同一运算符族中的换向符 (如果两个操作数数据类型相同,则为自身,或者如果两个运算符数据类型不同,则为相关的相等运算符)。 否则,使用运算符时可能会发生优化器错误。 为了更好的优化,支持多种数据类型的哈希运算符族应为数据类型的每种组合提供相等运算符。
Note: 哈希可连接运算符的基础函数必须标记为不可变或稳定的;标记为volatile的运算符将不会使用。 如果可哈希连接的运算符具有标记为严格的基础函数,则该函数也必须是完整的, 对于任何两个非空输入都返回true或false,并且不返回null。
MERGES
MERGES子句(如果存在)告诉系统允许使用merge-join方法基于该运算符进行联接。 MERGES仅对返回布尔值的二元运算符有意义,并且在实践中, 该运算符必须表示某些数据类型或一对数据类型的相等性。
合并联接基于的想法是将左表和右表排序,然后并行扫描它们。 这意味着这两种数据类型都必须能够完全排序, 并且联接运算符必须是仅对按排序顺序位于相等位置的值对成功的运算符。 实际上,这意味着联接运算符必须表现得像相等运算符。 但是,您可以合并联接两种不同的数据类型,只要它们在逻辑上是兼容的。 例如,smallint-versus-integer等价运算符是可合并连接的。 仅需要将两种数据类型都放入逻辑兼容序列的排序运算符。
要标记为MERGES,联接运算符必须显示为btree索引运算符族的相等成员。 创建运算符时不会强制执行此操作,因为引用运算符族直到稍后才存在。 但是,除非可以找到匹配的运算符族,否则该运算符实际上不会用于合并联接。 因此,MERGE标记可作为对优化器的建议,以寻找匹配的运算符族。
可合并连接的运算符必须具有出现在同一运算符族中的换向器。 如果两个操作数数据类型相同,则其为数据本身; 如果数据类型不同,则为相关的相等运算符。 如果没有合适的换向器,则在使用运算符时会发生优化器错误。 同样,尽管不是严格要求,但是支持多种数据类型的btree运算符族应该能够为数据类型的每种组合提供相等运算符; 这样可以实现更好的优化。
Note: SORT1SORT2LTCMPGTCMP以前用于指定与可合并连接运算符关联的排序运算符的名称。 现在,通过查看B树运算符族可以找到有关关联运算符的信息。 指定这些运算符中的任何一个都将被忽略,除非它将隐式地将MERGES设置为true。

注解

用于实现运算符的任何函数都必须定义为IMMUTABLE

CREATE OPERATOR中不能指定运算符的词法优先级,因为解析器的优先级行为是固定的。 有关优先级的详细信息,请参见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是一个Greenplum数据语言的扩展。 SQL标准不提供用户定义的运算符。