PostgreSQL是使用C语言进行开发的,一般情况下,大部分的脚本语言会比C语言脚本允许的更慢,另外PostgreSQL的某些功能只能依靠C语言来进行开发,下面介绍一下如何使用C语言在pg进行编程。
我们这里编写一个简单的函数,用来实现两个参数的和的计算。
首先我们需要先编写C源文件,代码如下:
#include "postgres.h"
#include "fmgr.h"
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(add_ab);
Datum
add_ab(PG_FUNCTION_ARGS)
{
int32 arg_a = PG_GETARG_INT32(0);
int32 arg_b = PG_GETARG_INT32(1);
PG_RETURN_INT32(arg_a + arg_b);
}
简单对上面的函数中的内容进行一些介绍:
- #include“ postgres.h”:包括与Postgres接口所需的大多数基本内容。此行需要包含在每个声明Postgres函数的C文件中。
- #include“ fmgr.h”:包含需要使用PG_GETARG_XXX和PG_RETURN_XXX宏。
- PG_MODULE_MAGIC:为了确保动态载入对象文件不会被载入到一个不兼容的服务器, PostgreSQL会检查该文件是否包含一个
带有合适内容的“magic block”。 - Datum:是每个C语言Postgres函数的返回类型,可以是任何数据类型。
- add_ab(PG_FUNCTION_ARGS):add_ab是函数名,PG_FUNCTION_ARGS表示参数可以为任意值,即使函数没有参数也必须加上。
- PG_GETARG_INT32(0):用来为参数获取值。
- PG_RETURN_INT32:用来返回函数值。
接下来我们需要编译.c的源文件。这里可以通过Makefile文件来实现,同时我们可以直接利用PostgreSQL扩展程序构建基础(简称PGXS)来实现。
Makefile:
MODULES = add_func
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
MODULES:要从源文件构建的具有相同词干的共享库对象的列表(不要在这个列表中包括库后缀)。
剩下的三行是是PostgreSQL 构建扩展相关的命令,保留就可以。
编写完这两个文件我们就可以使用make命令来编译了。
pg12@oracle-> make
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/home/pg12/pgsql12.4/include/server -I/home/pg12/pgsql12.4/include/internal -D_GNU_SOURCE -c -o add_func.o add_func.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 add_func.o -L/home/pg12/pgsql12.4/lib -Wl,--as-needed -Wl,-rpath,'/home/pg12/pgsql12.4/lib',--enable-new-dtags -shared -o add_func.so
pg12@oracle-> make install
/bin/mkdir -p '/home/pg12/pgsql12.4/lib'
/bin/install -c -m 755 add_func.so '/home/pg12/pgsql12.4/lib/'
编译完之后我们就可以去数据库中直接创建这个函数了:
bill@bill=>create function add(int,int)
bill-# returns int
bill-# as '/home/pg12/pgsql12.4/lib/add_func','add_ab'
bill-# language C strict;
CREATE FUNCTION
使用测试:
bill@bill=>select add(1,2);
add
-----
3
(1 row)
至此一个简单的构建C函数的例子便完成了,但是上面的代码中有一个很大的缺点:移植性不行。因为我们换个环境可能又要根据不同的目录(如上的’/home/pg12/pgsql12.4/lib’)来编写不同的CREATE FUNCTION的命令了。因此我们可以在上面的基础上做一些简单的优化。
我们要编写一个名为add_func.sql.in 的文件,其内容如下:
add_func.sql.in:
create function add(int,int)
returns int
as 'MODULE_PATHNAME','add_ab'
language C strict;
接着在Makefile中加入DATA_built = add_func.sql:
MODULES = add_func
DATA_built = add_func.sql
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
接下来我们再运行make命令编译时,add_func.sql.in会被编译到add_func.sql文件中,而其中的MODULE_PATHNAME会被真实的路径替换,
pg12@oracle-> make
sed 's,MODULE_PATHNAME,$libdir/add_func,g' add_func.sql.in >add_func.sql
查看下add_func.sql文件:
create function add(int,int)
returns int
as '$libdir/add_func','add_ab'
language C strict;
那么我们加下来只需要直接执行该文件即可:
bill@bill=>\i ./add_func.sql
CREATE FUNCTION
总结:
在PostgreSQL中编写一个简单的C函数大致过程为:
1、在modulename.c中写C代码。
2、在modulename.sql.in中为CREATE FUNCTION写SQL代码。
3、写一个Makefile 函数。
4、运行make,编译一个C程序并生成modulename.sql
5、运行make install,安装已生成的程序。
6、在psql命令行中执行 \i /
/modulename.sql,运行生成的modulename.sql文件。