PostgresSql操作符重载

运算符是一个保留字或字符主要用于PostgreSQL的语句的WHERE子句中执行操作,如比较和算术运算。

运算符用于指定一个PostgreSQL表中的条件,并在一份声明中多个条件作为连词。

  • 算术运算符
  • 比较操作符
  • 逻辑运算符
  • 位运算符



操作命令

创建操作符
1
2
3
4
5
6
7
8
9
10
Command:     CREATE OPERATOR
Description: define a new operator
Syntax:
CREATE OPERATOR name (
PROCEDURE = function_name
[, LEFTARG = left_type ] [, RIGHTARG = right_type ]
[, COMMUTATOR = com_op ] [, NEGATOR = neg_op ]
[, RESTRICT = res_proc ] [, JOIN = join_proc ]
[, HASHES ] [, MERGES ]
)
删除操作符
1
2
3
4
Command:     DROP OPERATOR
Description: remove an operator
Syntax:
DROP OPERATOR [ IF EXISTS ] name ( { left_type | NONE } , { right_type | NONE } ) [, ...] [ CASCADE | RESTRICT ]
查看系统操作符视图 pg_operator
1
select * from pg_operator;

思考如何重载操作符?

操作符可以被重载,也就是说相同的操作符名称可以用于具有不同操作数数量和类型的操作符。在创建相应处理操作符之前必须先创建底层函数。

其执行的操作:

  1. create function
  2. create operation
方法一: internal 扩展 (需要重新initdb)

实际,重新再pg_operator.h重载操作符 类似于 create function .... LANUAGE internal 方式。

需要将执行函数静态编译到Postgres 需要修改 pg_proc.h , 然后在 pg_operator.h 进行引用

不然将会报错。 提示 FATAL: 42883: there is no built-in function named "xxxxxx"

  • pg_opertor.h
  • pg_proc.h
  • 执行函数 此处执行函数可以 sql 语句编写,也可以在 xxx.c 文件实现

过程如下:

方法二: c 扩展(不需要重新initdb)

实际执行方式为create function ..... LANUAGE C , 在xxx.so共享库中查找执行函数。

  • 插件编写并进行加载-实现psql内建函数与c源码函数关联

  • pg中关联操作符与指定psql函数

    1
    2
    3
    4
    5
    6
    7
    CREATE OPERATOR name (
    PROCEDURE = function_name
    [, LEFTARG = left_type ] [, RIGHTARG = right_type ]
    [, COMMUTATOR = com_op ] [, NEGATOR = neg_op ]
    [, RESTRICT = res_proc ] [, JOIN = join_proc ]
    [, HASHES ] [, MERGES ]
    )
    • name

    • PROCEDURE

      • 用来实现这个操作符的psql函数
    • LEFTARG

      • 这个操作符的左操作数(如果有)的数据类型。忽略这个选项 可以表示一个左一元操作符。
    • RIGHTARG

      • 这个操作符的右操作数(如果有)的数据类型。忽略这个选项 可以表示一个右一元操作符。
    • COMMUTATOR

      • 这个操作符的交换子。 意味着左右操作数类型与此类型相反,指定其操作符。
    • NEGATOR

      • 这个操作符的求反器。 例如: = 操作符的 求反器为 !=
    • RESTRICT

      • 用于这个操作符的限制选择度估计函数。
    • JOIN

      • 用于这个操作符的连接选择度估算函数。
    • HASHES

      • 表示这个操作符可以支持哈希连接。
    • MERGES

      • 表示这个操作符可以支持归并连接。
  • 图示

    未添加

    1
    2
    3
    4
    CREATE OPERATOR pg_catalog.= (
    leftarg = numeric, rightarg = text, procedure = numeric_eq_varchar,
    commutator = OPERATOR(=) -- 添加左右参数交换操作函数
    );

    添加

    此示例为添加其左右交换因子;

示例:

1
2
3
4
5
6
7
8
9
CREATE FUNCTION complex_abs_lt(complex, complex) RETURNS bool
AS 'filename', 'complex_abs_lt'
LANGUAGE C IMMUTABLE STRICT;

CREATE OPERATOR < (
leftarg = complex, rightarg = complex, procedure = complex_abs_lt,
commutator = > , negator = >= ,
restrict = scalarltsel, join = scalarltjoinsel
);

源代码定义解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
"cat src/include/catalog/pg_operator.h"

CATALOG(pg_operator,2617)
{
NameData oprname; /* name of operator */
Oid oprnamespace; /* OID of namespace containing this oper */
Oid oprowner; /* operator owner */
char oprkind; /* 'l', 'r', or 'b' */
bool oprcanmerge; /* can be used in merge join? */
bool oprcanhash; /* can be used in hash join? */
Oid oprleft; /* left arg type, or 0 if 'l' oprkind */
Oid oprright; /* right arg type, or 0 if 'r' oprkind */
Oid oprresult; /* result datatype */
Oid oprcom; /* OID of commutator oper, or 0 if none */
Oid oprnegate; /* OID of negator oper, or 0 if none */
regproc oprcode; /* OID of underlying function */
regproc oprrest; /* OID of restriction estimator, or 0 */
regproc oprjoin; /* OID of join estimator, or 0 */
} FormData_pg_operator;

参考

Postgresql 9.5 Create Operator参考

欣赏此文? 求鼓励,求支持!