一.创建sql文件
这里建议大家从sql开始入手,一方面这里的逻辑比较清晰,也易于理解;另一方面sql文件只需要引用c函数就能写进数据库中。
CREATE OR REPLACE FUNCTION rv_sum(INTEGER,INTEGER) RETURNS INTEGER AS '$libdir/demo' LANGUAGE 'c' IMMUTABLE STRICT;
本例使用的是直接引用文件的方法,在这个方法中,要创建的sql函数名称必须与c文件中的函数名称一致。
如果c文件中有多个函数,可以通过以下方式声明:
… AS '$libdir/demo',’rv_sum’ …
当然,对于一些大型项目,这里的“$libdir/”为方便维护,可以替换成需要的变量写在sql.in里面(就像PostGIS那样)。
二.创建c函数
#include "postgres.h" #include "fmgr.h" #ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; #endif PG_FUNCTION_INFO_V1(rv_sum); Datum rv_sum(PG_FUNCTION_ARGS); Datum rv_sum(PG_FUNCTION_ARGS) { int sum,a,b; a = PG_GETARG_INT32(0); b = PG_GETARG_INT32(1); sum = a + b; PG_RETURN_INT32(sum); }
在PG中使用c函数进行扩展遵循简单的“三步走”原则:
1. PG_MODULE_MAGIC
在创建扩展时,为了确保不会错误加载共享库文件,PostgreSQL 会检查那个文件的"magic block",来让服务器检查明显的不兼容性。
注意,如果扩展中包含多个c文件,PG_MODULE_MAGIC不需要重复定义。
#ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; #endif
2.声明函数
PG中需要使用PG_FUNCTION_INFO_V1()来声明函数名称,例如:
PG_FUNCTION_INFO_V1(rv_sum);
3.include头文件fmgr.h
本例在第一次测试时没有加fmgr.h,在创建扩展时会报could not load library: undefined symbol的错误。
三.编辑Makefile
MODULE_big = demo IBASE_VERSION = 1.0 OBJS = demo.o EXTENSION = demo DATA = demo--1.0.sql SHLIB_LINK += $(filter -lm,$(LIBS)) USE_PGXS = 1 ifdef USE_PGXS PG_CONFIG = /opt/PostgreSQL/bin/pg_config PGXS := $(shell $(PG_CONFIG) --pgxs) include $(PGXS) else subdir = contrib/demo top_builddir = ../.. include $(top_builddir)/src/Makefile.global include $(top_srcdir)/contrib/contrib-global.mk endif
这里主要涉及两个变量:PG_CONFIG和PGXS,本例为简单起见直接设置了绝对路径,请读者注意。
四.编辑control文件
.control主要用于扩展的版本控制,主要版本号要与sql文件的版本号相同。
# demo extension comment = 'test' default_version = '1.0' relocatable = true
五.测试
[root@msharvest 11-RV_Media]# make && make install gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -I. -I./ -I/opt/PostgreSQL/include/postgresql/server -I/opt/PostgreSQL/include/postgresql/internal -D_GNU_SOURCE -c -o demo.o demo.c gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -shared -o demo.so demo.o -L/opt/PostgreSQL/lib -Wl,--as-needed -Wl,-rpath,'/opt/PostgreSQL/lib',--enable-new-dtags -lm /usr/bin/mkdir -p '/opt/PostgreSQL/lib/postgresql' /usr/bin/mkdir -p '/opt/PostgreSQL/share/postgresql/extension' /usr/bin/mkdir -p '/opt/PostgreSQL/share/postgresql/extension' /usr/bin/install -c -m 755 demo.so '/opt/PostgreSQL/lib/postgresql/demo.so' /usr/bin/install -c -m 644 .//demo.control '/opt/PostgreSQL/share/postgresql/extension/' /usr/bin/install -c -m 644 .//demo--1.0.sql '/opt/PostgreSQL/share/postgresql/extension/'
进入PG,创建扩展
postgres=# CREATE EXTENSION demo; CREATE EXTENSION
六.参考资料
PostgreSQL 扩展开发基础教程:
http://joshuais.me/postgresql-extension-develop/