pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
现在我们已经了解了这些概念,下面就是承诺的创建新操作符类的示例。首先,我们需要一组操作符。定义操作符的过程已在第 11 章中讨论过。对于 B-树上的 complex_abs_ops 操作符类,我们需要的操作符是:
假设实现这些函数的代码存储在文件 中, 并且我们已把它编译成 PGROOT/src/tutorial/complex.c。 C 代码的一部分如下所示:PGROOT/src/tutorial/complex.so
#define Mag(c) ((c)->x*(c)->x + (c)->y*(c)->y)
bool
complex_abs_eq(Complex *a, Complex *b)
{
double amag = Mag(a), bmag = Mag(b);
return (amag==bmag);
}
(注意,我们在此文本中只展示相等操作符。其他四个操作符非常类似。 细节请参阅 complex.c 或 complex.source。)
我们像下面这样让 PostgreSQL 知道该函数:
CREATE FUNCTION complex_abs_eq(complex, complex) RETURNS boolean
AS 'PGROOT/src/tutorial/complex'
LANGUAGE C;
这里有几件重要的事情:
首先,注意这里正在为 complex 定义小于、小于等于、等于、 大于等于和大于操作符。我们只能有一个名为(例如)= 并且两个操作数都取 complex 类型的操作符。在本例中我们没有其他用于 complex 的 = 操作符,但如果我们在构造一种实用的数据类型, 我们可能希望 = 是复数的普通相等操作。在那种情况下,我们就需要为 complex_abs_eq 使用其他某个操作符名。
其次,尽管 PostgreSQL 能处理名称相同但输入数据类型 不同的操作符,C 却只能处理给定名称的一个全局例程。因此,我们不应该把 C 函数 简单命名成 abs_eq 之类。通常,在 C 函数名中包含数据类型 名称是个好习惯,这样就不会与其他数据类型的函数发生冲突。
第三,我们本可以把该函数的 PostgreSQL 名称取为 abs_eq,并依靠 PostgreSQL 通过输入数据类型把它与任何其他同名的 PostgreSQL 函数区分开。为了让示例保持简单,这里我们让 C 层和 PostgreSQL 层的函数使用相同的名称。
最后,注意这些操作符函数返回布尔值。实际上,所有被定义为索引访问方法 策略的操作符都必须返回 boolean 类型,因为要与索引 配合使用,它们必须出现在 WHERE 子句的顶层。 (另一方面,支持函数返回的是特定访问方法所期望的类型——对 B-树的 比较函数来说,就是一个有符号整数。)
现在我们准备好定义操作符了:
CREATE OPERATOR = (
leftarg = complex, rightarg = complex,
procedure = complex_abs_eq,
restrict = eqsel, join = eqjoinsel
);
这里的重要内容是过程名(即上面定义的 C 函数)以及限制和连接选择性函数。 你应当直接使用示例中所用的选择性函数(见 complex.source)。 注意,小于、等于和大于情形有不同的此类函数。必须提供这些函数, 否则优化器将无法有效地使用该索引。
下一步是注册 B-树所需的比较“支持例程”。实现它的 C 代码位于包含上述 操作符过程的同一文件中:
CREATE FUNCTION complex_abs_cmp(complex, complex)
RETURNS integer
AS 'PGROOT/src/tutorial/complex'
LANGUAGE C;
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。