本节以实现Oracle中的add_months函数为例介绍如何通过改造内核实现自定义系统函数.
一、基础知识
在实现之前有必要先行介绍一些基础知识,包括Oid/函数注册等.
Oid
Oid即Object identifier,对象标识符,在PostgreSQL中,每个对象都一个Oid,系统表对象之间以Oid进行关联.
函数作为PostgreSQL中的一种对象,每个函数都存在Oid,通过查询pg_proc可获得相关信息:
postgres=# select oid,proname from pg_proc order by oid;
oid | proname
-------+----------------------------------------------
31 | byteaout
33 | charout
34 | namein
35 | nameout
38 | int2in
39 | int2out
40 | int2vectorin
41 | int2vectorout
42 | int4in
43 | int4out
44 | regprocin
45 | regprocout
46 | textin
47 | textout
48 | tidin
49 | tidout
50 | xidin
51 | xidout
52 | cidin
53 | cidout
54 | oidvectorin
55 | oidvectorout
56 | boollt
57 | boolgt
60 | booleq
--More--
函数注册
假设我们已经实现了一个自定义系统函数,比如add_months,PostgreSQL如何才能感知该函数的存在?答案是通过函数注册实现.
PostgreSQL在编译的时候,会用perl脚本根据预置的记录,生成src/backend/catalog/postgres.bki文件,该文件在initdb时被解析成一条条的SQL,插入到系统表中.因此自定义的系统函数,需要在通过initdb新建的数据库实例中才能被”感知”.
二、实现步骤
有了上面的基础知识,接下来我们step by step的实现add_months自定义函数.
1.获取函数Oid
PostgreSQL提供了unused_oids工具用于快速检索未使用的Oid,该文件位于src/include/catalog目录下
find -name unused_oids
./src/include/catalog/unused_oids
[root@localhost pg11]# ./src/include/catalog/unused_oids
2 - 9
3423 - 3436
3996
3998
4001 - 4013
4142 - 4199
4217 - 4565
4572 - 4999
5017 - 5027
5029 - 5999
6015 - 6099
6103
6105
6107 - 6109
6116
6122 - 9999
我们选择了Oid = 5100
2.注册函数
在文件pg_proc.dat中添加add_months函数
#src/include/catalog/pg_proc.dat
...
{ oid => '5100', descr => 'oracle-like add_months function',
proname => 'add_months', provariadic => '0',
proisstrict => 'f', prorettype => 'date', proargtypes => 'date int4',
prosrc &#