↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

不受支持的版本: 7.3 / 7.2
历史版本PostgreSQL 7.3 已于 2007 年 11 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本手册首页。

14.5. 创建操作符和支持例程 #

现在我们已经了解了这些概念,下面就是承诺的创建新操作符类的示例。首先,我们需要一组操作符。定义操作符的过程已在第 11 章中讨论过。对于 B-树上的 complex_abs_ops 操作符类,我们需要的操作符是:

  • 绝对值小于(策略 1)
  • 绝对值小于等于(策略 2)
  • 绝对值等于(策略 3)
  • 绝对值大于等于(策略 4)
  • 绝对值大于(策略 5)

假设实现这些函数的代码存储在文件 PGROOT/src/tutorial/complex.c 中, 并且我们已把它编译成 PGROOT/src/tutorial/complex.so。 C 代码的一部分如下所示:

#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 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。