PostgreSQL-UDF用户自定义函数-扩展插件
零、前置条件
ggc postgresql
一、创建 .c 和 .sql 文件
创建.c文件
进入PG源码的contib/
目录下面,这个目录下面都是用于PG进行功能扩展的插件。 创建我们的插件(UDF同义词:插件;扩展;用户自定义函数)目录demo/
。 在我们的插件目录下创建.c
和.sql
文件,后续第二步中还会创建用于编译和链接的Makefile
文件和.control
文件。
[ root@localhost ~]
[ root@localhost contrib]
[ root@localhost contrib]
[ root@localhost demo]
# include "postgres.h"
# include "fmgr.h"
# ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
# endif
PG_FUNCTION_INFO_V1 ( my_sum) ;
Datum my_sum ( PG_FUNCTION_ARGS) ;
Datum my_sum ( PG_FUNCTION_ARGS) {
int32 a = PG_GETARG_INT32 ( 0 ) ;
int32 b = PG_GETARG_INT32 ( 1 ) ;
int32 sum = a + b;
PG_RETURN_INT32 ( sum) ;
}
创建.sql文件
.sql
文件中主要是写入创建FUNCTION
和TYPE
的SQL语句。vim
新建一个以插件名+插件版本号命名的.sql
文件(这里demo
是插件名,--1.0
是版本号)。
[ root@localhost demo]
CREATE FUNCTION my_sum( INTEGER , INTEGER )
RETURNS INTEGER
AS '$libdir/demo'
LANGUAGE C STRICT;
注意:SQL语句中的函数名要和上面.c
中定义的函数保持一致。 其中$libdir
这个变量是PG安装位置下的静态库文件的默认存储路径,可以用[root@localhost ~]# pg_config --pkglibdir
这一命令查看具体的路径,可以不用管,后面直接接与插件名一致的目录即可,这里接的是demo
。 如果.c
文件中定义了多个函数,.sql
文件中的AS
后面需要指明是demo.c
中的哪一个函数,即:
CREATE FUNCTION …
… …
AS '$libdir/demo' , 'my_sum'
… …
二、创建 .control 和 Makefile 文件
创建 .control 文件
在PostgreSQL中,后缀为.control
的文件是一个扩展的控制文件。它用于管理和描述特定扩展的元数据和配置信息。 控制文件通常与扩展相关联,并存储了有关扩展的重要信息,例如扩展的名称、版本、所需依赖项等。这些文件还可以包含其他配置选项,以更好地定义和管理扩展的行为。 通过使用.control
文件,PostgreSQL能够根据需要加载和卸载扩展,并确保正确配置和使用扩展。这些文件对于扩展的安装、更新和卸载过程都起着重要作用。 总结:.control
文件是PostgreSQL中扩展的元数据文件,用于管理和配置扩展的属性和行为。
[ root@localhost demo]
comment = 'test demo'
default_version = '1.0'
module_pathname = '$libdir/demo'
relocatable = true
comment
配置项:用于提供关于扩展的注释或描述性文本。它允许开发人员向用户提供有关扩展功能、用途或其他相关信息的说明。这些注释可以帮助用户更好地理解和使用扩展.relocatable
配置项:用于指定扩展是否可重定位。如果设置为true
,则表示扩展可以在不重新编译数据库的情况下移动到不同的安装位置。这对于在多个数据库实例之间共享和部署扩展非常有用。默认情况下,该配置项的值是false
。注意:default_version
要与最新版本的.sql
文件名中的版本号保持一致。
创建 Makefile 文件
Makefile
文件本质上是shell命令的集合,用于一系列源代码文件的自动化编译,用make指令执行一个Makefile
文件,可以根据文件中的编译规则对一系列源代码文件进行不同的编译。这里贴一个Linux下编译链接相关文件的流程说明(根据自己的理解总结的图,有错误敬请指出): 回到正题,Makefile
文件由变量 们和编译规则 构成:
定义变量的基本格式是变量名 = 变量值
,使用变量的基本格式和shell一致$(变量名)
。 对某个源码文件的编译规则编写的语法基本格式如下:
目标文件1:依赖文件1
(Tab键)规则1(依赖文件1怎么生成目标文件1的,也就是用依赖文件生成目标文件的方法)
目标文件2:依赖文件2
(Tab键)规则2(依赖文件2怎么生成目标文件2的)
依赖文件对应上图.c
、.cpp
等源码文件,目标文件对应上图中.o
文件。 规则对应编译命令gcc [编译选项] (编译对象)
实例:
demo.o:demo.c
gcc -c demo.c
MODULES = demo
EXTENSION = demo
DATA = demo--1.0.sql
PGFILEDESC = "demo - various functions that return tables"
OBJS = demo.o
CC = gcc
REGRESS = tablefunc
LDFLAGES_SL += $( filter -lm, $( LIBS) )
ifdef NO_PGXS
subdir = contrib/extensions
top_builddir = .. /..
include $( top_builddir) /src/Makefile.global
include $( top_srcdir) /contrib/contrib-global.mk
else
PG_CONFIG = pg_config
PGXS := $( shell $( PG_CONFIG) --pgxs )
include $( PGXS)
endif
PG源码地址/src/Makefile.global
文件截图如下:
三、编译 & 链接
在demo目录下执行make
和make install
[ root@localhost demo]
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 -g -O0 -fPIC -I. -I./ -I/opt/pgsql-15.3/include/server -I/opt/pgsql-15.3/include/internal -D_GNU_SOURCE -c -o demo.o demo.c -MMD -MP -MF .deps/demo.Po
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 -g -O0 -fPIC demo.o -L/opt/pgsql-15.3/lib -Wl,--as-needed -Wl,-rpath,'/opt/pgsql-15.3/lib' ,--enable-new-dtags -shared -o demo.so
[ root@localhost demo]
demo.c demo.control demo.o demo.so Makefile
[ root@localhost demo]
/usr/bin/mkdir -p '/opt/pgsql-15.3/share/extension'
/usr/bin/mkdir -p '/opt/pgsql-15.3/share/extension'
/usr/bin/mkdir -p '/opt/pgsql-15.3/lib'
/usr/bin/install -c -m 644 .//demo.control '/opt/pgsql-15.3/share/extension/'
/usr/bin/install -c -m 644 .//demo--1.0.sql '/opt/pgsql-15.3/share/extension/'
/usr/bin/install -c -m 755 demo.so '/opt/pgsql-15.3/lib/'
[ root@localhost demo]
demo--1.0.sql plpgsql.control postgres_fdw.control
demo.control postgres_fdw--1.0--1.1.sql
plpgsql--1.0.sql postgres_fdw--1.0.sql
四、psql(或者其他PG backend)中创建扩展
posgres=
CREATE EXTENSION
posgres=
posgres=
my_sum
3
( 1 row )