一.創建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/