|
17.6. 创建操作符和支持过程因此,现在我们有了一个访问方式和一个操作符表. 我们还需要一套操作符; 用于定义操作符的过程已经在 Chapter 14 讨论过了. 对这个用于 B-tree 的 complex_abs_ops 操作符表, 我们需要的操作符是:
假设实现这些函数的代码放在文件 PGROOT /tutorial/complex.c 里, 我们已经把它编译成 PGROOT /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;
有几个很重要的问题要在这里出现∶
文件里最终的过程是我们在讨论表 pg_am 里 amsupport 字段时提到过的 "支持过程" . 我们稍后将用到这个东西.目前我们暂时先忽略它. 现在可以定义使用它们的操作符了: CREATE OPERATOR = ( leftarg = complex, rightarg = complex, procedure = complex_abs_eq, restrict = eqsel, join = eqjoinsel ); 里的重要问题是过程名称(就是上面定义的 C 函数) 和这个关系和连接选择性函数. 你应该只使用例子里(参阅 complex.source )的选择性函数.请注意还要有这样的用于小于,等于和大于情况的函数. 你必须提供这些(函数),否则优化器将无法有效地使用该索引. 下一步是为这些操作符向 pg_amop 关系里面增加条目. 要做这些,我们将需要我们刚定义的这些操作符的 OID. 我们将从所有操作符中找出接受两个 complex 的操作符名称, 并把它们选出来: SELECT o.oid AS opoid, o.oprname INTO TEMP TABLE complex_ops_tmp FROM pg_operator o, pg_type t WHERE o.oprleft = t.oid and o.oprright = t.oid and t.typname = 'complex'; opoid | oprname --------+--------- 277963 | + 277970 | < 277971 | <= 277972 | = 277973 | >= 277974 | > (6 rows) (同样,一些你的 OID (对象标识)将可以说肯定是不同的.) 我们感兴趣的操作符是那些 OID(对象标识)在 277970 到 277974 之间的.你得到的值将可能不同, 你应该用你得到的值代替上面的数值. 我们通过一条 select 语句实现这个目的。 现在我们已经准备好为我们的新操作符表插入记录到 pg_amop 里.这些记录必须把正确的 B-tree 策略数与我们使用的每个操作符相关联.插入小于操作符的命令象下面这个样子∶ INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr) SELECT opcl.oid, 1, false, c.opoid FROM pg_opclass opcl, complex_ops_tmp c WHERE opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree') AND opcname = 'complex_abs_ops' AND c.oprname = '<'; 然后添加其他操作符,相应地替换上面第二行的 "1" 和最后一行的 "<"。 注意顺序: "小于" 是 1,"小于或等于" 是 2,"等于" 是 3,"大于或等于" 是 4, 而 "大于" 是 5。 这里没有讨论 amopreqcheck 字段; 对于 B-tree 操作符,它应该总是假. 最后一步是注册我们前面讨论 pg_am 时描述 过的 "支持过程" . 支持过程的 OID (对象标识)存放在表 pg_amproc 里, 用操作符表的 OID (对象标识)和支持过程数目 做关键字. 首先,我们需要在 PostgreSQL 里注册函数(还记得我们把实现这个过程的 C 代码放在了我们实现操作符过程的文件的底部吗?): CREATE FUNCTION complex_abs_cmp(complex, complex) RETURNS integer AS ' PGROOT /src/tutorial/complex' LANGUAGE C; SELECT oid, proname FROM pg_proc WHERE proname = 'complex_abs_cmp'; oid | proname --------+----------------- 277997 | complex_abs_cmp (1 row) (同样,你的 oid (对象标识)的数字将可能不同.) 我们可以用下面方法增加新的记录: INSERT INTO pg_amproc (amopclaid, amprocnum, amproc) SELECT opcl.oid, 1, p.oid FROM pg_opclass opcl, pg_proc p WHERE opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree') AND opcname = 'complex_abs_ops' AND p.proname = 'complex_abs_cmp';
这样我们就完成了!(乌拉.)现在我们可以在一个 complex 列上创建和使用 B-tree 索引了. |