🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # <span style="font-size:15px">**扩展开发基本步骤** </span> * 在源码目录的`contrib/`目录下创建与扩展名同名的文件夹,在该文件夹内存放开发好的扩展源码文件,包含MakeFile文件、.sql文件、.control控制文件等 * 在该目录下,执行`make`命令,进行编译 * 将编译生成的so文件和sql文件迁移至安装目录的lib和extension下 * 将so文件和sql文件修改权限和用户组 * 最后再在数据库中添加扩展:`create extension 扩展名;` # <span style="font-size:15px">**扩展开发使用的语言** </span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PostgreSQL 支持使用`PL/pgSQL`语言或者原生的C语言开发扩展。`PL/pgSQL`开发相对简单,但性能上较原生的C语言要差。只需要通过指定sql文件的`CREATE FUNCTION`的`LANGUAGE`参数即可。 # <span style="font-size:15px">**实例一:使用SQL语言实现自定义扩展** </span> 1、在源码目录的`contrib/`目录下创建与扩展名同名的文件夹,在该文件夹内,创建`demo--1.0.sql`文件,定义add函数,实现数值相加,其中`LANGUAGE`参数设置为`SQL` ``` -- 如果脚本是由 psql 而不是 CREATE EXTENSION 执行,则报错 -- \echo开始的行,会被扩展机制认为是注释行,如果脚本文件被送给psql而不是由CREATE EXTENSION载入,这种机制通常被用来抛出错误 \echo Use "CREATE EXTENSION" to load this file. \quit CREATE FUNCTION add(integer, integer) RETURNS integer AS 'select $1 + $2;' LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT; ``` 2、创建`demo.control`文件 ``` comment = create add function' # 添加扩展注释 default_version = '1.0' # 指定默认扩展版本 relocatable = false # 设置扩展是否可重定向 ``` 3、创建`Makefile`文件 ``` EXTENSION = demo DATA = demo--1.0.sql PG_CONFIG = pg_config PGXS := $(shell $(PG_CONFIG) --pgxs) include $(PGXS) ``` 4、`make && make install` ``` [postgres@izwz91quxhnlkan8kjak5hz demo]$ l demo--1.0.sql demo.control Makefile [postgres@izwz91quxhnlkan8kjak5hz demo]$ make && make install make: 对“all”无需做任何事。 /usr/bin/mkdir -p '/www/server/postgresql/share/extension' /usr/bin/mkdir -p '/www/server/postgresql/share/extension' /usr/bin/install -c -m 644 .//demo.control '/www/server/postgresql/share/extension/' /usr/bin/install -c -m 644 .//demo--1.0.sql '/www/server/postgresql/share/extension/' ``` 5、`create extension demo` ``` [postgres@izwz91quxhnlkan8kjak5hz demo]$ psql Password: psql (13.0) Type "help" for help. postgres=# create extension demo; CREATE EXTENSION ``` 6、测试验证 ``` // 查询语句中直接调用扩展的函数,自定义扩展函数正常生效 postgres=# SELECT id,name,sale,num,add(sale,num) from test WHERE id =2; id | name | sale | num | add ----+-------+------+-----+----- 2 | z4Vuo | 3 | 3 | 6 (1 row) ``` 7、为demo扩展新增multi函数(乘法算法),并将扩展版本更新为1.1 当前demo扩展安装的版本为1.0,可通过pg_extension查看 ``` postgres=# select * from pg_extension where extname='demo'; oid | extname | extowner | extnamespace | extrelocatable | extversion | extconfig | extcondition -------+---------+----------+--------------+----------------+------------+-----------+-------------- 16628 | demo | 10 | 2200 | t | 1.0 | | (1 row) ``` 在demo扩展目录下新增demo--1.0--1.1.sql升级脚本,并更改Makefile的DATA 参数:增加demo--1.0--1.1.sql ``` [postgres@izwz91quxhnlkan8kjak5hz demo]$ ls demo--1.0--1.1.sql demo--1.0.sql demo.control Makefile [postgres@izwz91quxhnlkan8kjak5hz demo]$ cat demo--1.0--1.1.sql -- 如果脚本是由 psql 而不是 CREATE EXTENSION 执行,则报错 -- \echo开始的行,会被扩展机制认为是注释行,如果脚本文件被送给psql而不是由CREATE EXTENSION载入,这种机制通常被用来抛出错误 \echo Use "CREATE EXTENSION" to load this file. \quit CREATE FUNCTION multi(integer, integer) RETURNS integer AS 'select $1 * $2;' LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT; [postgres@izwz91quxhnlkan8kjak5hz demo]$ cat Makefile EXTENSION = demo DATA = demo--1.0.sql demo--1.0--1.1.sql PG_CONFIG = pg_config PGXS := $(shell $(PG_CONFIG) --pgxs) include $(PGXS) ``` 执行`make install`并执行`ALTER EXTENSION`命令将demo扩展版本更新到1.1 ``` [postgres@izwz91quxhnlkan8kjak5hz demo]$ make install /usr/bin/mkdir -p '/www/server/postgresql/share/extension' /usr/bin/mkdir -p '/www/server/postgresql/share/extension' /usr/bin/install -c -m 644 .//demo.control '/www/server/postgresql/share/extension/' /usr/bin/install -c -m 644 .//demo--1.0.sql .//demo--1.0--1.1.sql '/www/server/postgresql/share/extension/' [postgres@izwz91quxhnlkan8kjak5hz ~]$ psql Password: psql (13.0) Type "help" for help. postgres=# ALTER EXTENSION demo update to '1.1'; ALTER EXTENSION postgres=# SELECT * from pg_extension where extname='demo'; oid | extname | extowner | extnamespace | extrelocatable | extversion | extconfig | extcondition -------+---------+----------+--------------+----------------+------------+-----------+-------------- 16628 | demo | 10 | 2200 | t | 1.1 | | (1 row) ``` > 如执行 ALTER EXTENSION 发现以下报错。需检查Makefile的DATA参数是否有写新的脚本文件 > postgres=# ALTER EXTENSION demo update to '1.1'; > ERROR: extension "demo" has no update path from version "1.0" to version "1.1" > 此报错说明该扩展没有升级路径,可通过此命令查看: > ``` > postgres=# SELECT * FROM pg_extension_update_paths('demo'); > source | target | path > --------+--------+------ > (0 rows) > ``` Makefile和sql文件填写正确后,在make install之后,该扩展就会自动更新其升级路径 ``` postgres=# SELECT * FROM pg_extension_update_paths('demo'); source | target | path --------+--------+---------- 1.0 | 1.1 | 1.0--1.1 1.1 | 1.0 | (2 rows) ``` 8、升级后的版本功能测试:新增了multi函数(乘法算法),且功能正常,扩展版本也成功更新为1.1 ``` postgres=# SELECT id,name,sale,num,add(sale,num),multi(sale,num) from test WHERE id =2; id | name | sale | num | add | multi ----+-------+------+-----+-----+------- 2 | z4Vuo | 3 | 3 | 6 | 9 (1 row) ``` # <span style="font-size:15px">**实例二:使用c语言实现自定义扩展** </span> 1、创建add_test扩展的相关文件 ``` [postgres@izwz91quxhnlkan8kjak5hz add_test]$ pwd /postgresql/postgresql-13.0/contrib/add_test [postgres@izwz91quxhnlkan8kjak5hz add_test]$ ls add_test--1.0.sql add_test.c add_test.control Makefile ``` 2、add_test--1.0.sql :声明扩展的函数、该函数的字符串常量以及使用的语言 ``` [postgres@izwz91quxhnlkan8kjak5hz add_test]$ cat add_test--1.0.sql \echo Use "create EXTENSION add_test" to load this file. quit CREATE FUNCTION add(integer, integer) RETURNS integer AS '$libdir/add_test' LANGUAGE C STRICT IMMUTABLE; ``` 3、add_test.c:编写c脚本,实现扩展的自定义函数逻辑 ``` #include "postgres.h" //包含 PostgreSQL 基础的接口。这是开发 PostgreSQL 扩展必需包含的头文件 #include "fmgr.h" // 包含了PG_GETARG_XX和PG_RETURN_XX等获取参数和返回结果的重要的宏,是必需的 #ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; // 从 PostgreSQL 8.2版本后就必须的宏,必须写在#include "fmgr.h"之后 #endif PG_FUNCTION_INFO_V1(add); // PG_FUNCTION_INFO_V1宏声明了我们所定义的函数为 Version-1 约定的函数,需要在定义方法之前先进行声明 Datum add(PG_FUNCTION_ARGS); Datum add(PG_FUNCTION_ARGS) // Datum 等同于void,表示函数返回任意类型的数据 { int sum,a,b; a = PG_GETARG_INT32(0); // 获取函数的第一个参数的值,并且将其转换为 int 类型 b = PG_GETARG_INT32(1); sum = a + b; PG_RETURN_INT32(sum); // 将结果转换为 int 类型并返回,也有其他类型的返回值:float、json } ``` 4、add_test.control:编写控制文件,定义默认版本号以及设置是否可重定向 ``` [postgres@izwz91quxhnlkan8kjak5hz add_test]$ cat add_test.control # demo extension comment = 'custom add function' default_version = '1.0' relocatable = true ``` 5、Makefile ``` [postgres@izwz91quxhnlkan8kjak5hz add_test]$ cat Makefile MODULE_big = add_test OBJS = add_test.o EXTENSION = add_test DATA = add_test--1.0.sql PG_CONFIG = pg_config PGXS := $(shell $(PG_CONFIG) --pgxs) include $(PGXS) ``` 6、make install ``` [postgres@izwz91quxhnlkan8kjak5hz add_test]$ 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/www/server/postgresql/include/server -I/www/server/postgresql/include/internal -D_GNU_SOURCE -c -o add_test.o add_test.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 add_test.so add_test.o -L/www/server/postgresql/lib -Wl,--as-needed -Wl,-rpath,'/www/server/postgresql/lib',--enable-new-dtags /usr/bin/mkdir -p '/www/server/postgresql/lib' /usr/bin/mkdir -p '/www/server/postgresql/share/extension' /usr/bin/mkdir -p '/www/server/postgresql/share/extension' /usr/bin/install -c -m 755 add_test.so '/www/server/postgresql/lib/add_test.so' /usr/bin/install -c -m 644 .//add_test.control '/www/server/postgresql/share/extension/' /usr/bin/install -c -m 644 .//add_test--1.0.sql '/www/server/postgresql/share/extension/' ``` 7、添加扩展并测试 ``` postgres=# create extension add_test; CREATE EXTENSION postgres=# select id,name,age,sale,num,add(sale,num) from test limit 1; id | name | age | sale | num | add ----+-------+-----+------+-----+----- 2 | z4Vuo | 4 | 3 | 3 | 6 ```