PostgreSQL extension扩展模块解析
PostgreSQL extension扩展模块解析
extension是什么
extension是PostgreSQL的扩展模块,用于扩展PostgreSQL本身所欠缺的功能。
为什么创建extension
1. 受众人群较少
2. 快速实现所需功能
3. 代码质量未经严格审核测试
从哪里获得extension
PostgreSQL源码的contrib目录下
pgxn:https://pgxn.org/
github:很多项目获取
extension缺陷
- 代码质量与PostgreSQL相比稍有欠缺
- 版本更新不及时,存在版本适配问题
- 维护者较少
- 没有严格的测试
extension编写指南
extension编译模式
模式由Makefile的关键字进行配置
- 单文件模式
MODULES -
多文件模式
MODULE_big,对象文件使用OBJS -
可执行模式
PROGRAM
extension编译关键字
-
EXTENSION
extension的名字 -
MODULEDIR
extension模块的名字,默认安装到share/extension下 -
DATA
安装到share/$MODULEDIR下的文件 -
DATA_built
安装到share/$MODULEDIR下的文件,会先构建MODULEDIR目录 -
DATA_TSEARCH
安装到share/tsearch_data下的文件 -
DOCS
安装到doc/$MODULEDIR下的文件 -
HEADERS
安装到include/server/$MODULEDIR/$MODULE_big下的头文件 -
HEADERS_built
同HEADERS,需要先构建目录 -
HEADERS_$MODULE
-
HEADERS_built_$MODULE
安装到include/server/$MODULEDIR/$MODULE下的头文件 -
SCRIPTS
-
SCRIPTS_built
安装到bin下的脚本文件,非二进制需要编译的文件 -
REGRESS
回归测试用例列表 -
REGRESS_OPTS
传递给pg_regress的参数 -
ISOLATION
传递给隔离测试的用例列表 -
ISOLATION_OPTS
传递给pg_isolation_regress的参数 -
NO_INSTALLCHECK
不用定义installcheck的目标 -
EXTRA_CLEAN
make clean清理的文件 -
PG_CPPFLAGS
传递给CPPFLAGS的参数 -
PG_CFLAGS
传递给CFLAGS的参数 -
PG_CXXFLAGS
传递给CXXFLAGS的参数 -
PG_LDFLAGS
传递给LDFLAGS的参数 -
PG_LIBS
PROGRAM 的库连接 -
SHLIB_LINK
MODULE_big的库连接 -
PG_CONFIG
pg_config的路径
extension 控制文件
-
directory
SQL脚本文件目录,绝对路径或相对于SHAREDIR目录,默认为extension目录 -
default_version
extension默认安装的版本 -
comment
注释 -
encoding
SQL脚本文件使用的字符集编码。默认数据库编码 -
module_pathname
参数的值将替换脚本文件中的MODULE_PATHNAME -
requires
此扩展所依赖的扩展名列表requires = ‘foo, bar’。必须先安装这些扩展,然后才能安装此扩展。 -
superuser
如果此参数是true(默认值),则只有超级用户可以创建扩展或将其更新为新版本 -
relocatable
重定位到不同的模式中,默认false -
schema
所建对象的模式
extension配置表
通常,如果表是extension的一部分,则表的定义及其内容都不会被pg_dump出来。但是这种行为对于一些做配置的表是不合理的。
- pg_dump 备份方法
SELECT pg_catalog.pg_extension_config_dump(‘table or seq’, ‘where query‘)
表的定义和数据都会被dump出来。此函数仅在create extension时的脚本文件中使用。
extension版本更新安装
版本更新安装采用最短路径的方式。如下文件存在时,安装2.0会直接使用cloud–2.0.sql
cloud–2.0.sql
cloud–1.0.sql
cloud–1.0–2.0.sql
- 版本有向图
版本中的数字没有任何意义,只是在建图的时候有用
版本组成:
1. extname–ver1.sql
2. extname–ver1–tover2.sql
建图:
ver1图(可安装),建立可达tover2的图
tover2图(不可安装)
建立路径:
从可安装图开始查找,依次找到目标版本
extension内部实现原理
钩子函数
钩子函数是PostgreSQL预留的接口,通过重新编写的钩子函数可以改变postgresql的默认功能,
钩子函数通常以hook最为结尾,PostgreSQL预留了非常丰富的接口。
示例:
ExecutorStart_hook
ExecutorRun_hook
ExecutorFinish_hook
ExecutorEnd_hook
自定义接口
通过PostgreSQL提供的扩展SQL实现
示例:
CREATE TYPE
CREATE FUNC
CREATE TEXT SEARCH PARSER
C函数
使用C语言可以获得PostgreSQL的头文件,结构体,变量等,可以获取数据库内部的信息,实现非常复杂的功能
示例:
CREATE FUNCTION zhprs_end(internal)
RETURNS void
AS ‘MODULE_PATHNAME’
LANGUAGE C STRICT;
extension组成
extension 通常由如下3个文件组成
- 控制文件
参考:extension 控制文件 -
脚本文件(sql)
参考: 自定义接口 -
动态库
参考:C函数
动态库控制文件的加载有4种情况
1. 不使用任何PostgreSQL的hook
2. 服务器启动时需要加载hook的库,配置到shared_preload_libraries
3. 与服务器建立连接时加载hook的库,配置到session_preload_libraries,只允许超级用户修改
4. 与服务器建立连接时加载hook的库,配置到local_preload_libraries,只能加载libdir/plugins下的库,普通用户可以修改
extension语法
- 创建
CREATE EXTENSION [ IF NOT EXISTS ] extension_name
[ WITH ] [ SCHEMA schema_name ]
[ VERSION version ]
[ FROM old_version ]
[ CASCADE ]
CASCADE:
递归安装依赖的extension
VERSION:
指定安装的版本,默认为control版本
FROM:
从哪个版本开始安装
SCHEMA:
安装到哪个模式下
创建extension时会在pg_extension建立pg_depend关系
- 更新
ALTER EXTENSION name UPDATE [ TO new_version ]
ALTER EXTENSION name SET SCHEMA new_schema
ALTER EXTENSION name ADD member_object
ALTER EXTENSION name DROP member_object
member_object:TABLE/FUNCTION/TYPE等
- 删除
DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
CASCADE:
递归删除依赖
删除extension时会根据pg_depend的关系递归删除extension建立的对象
demo
总结
extension模块的实现并不复杂,但是非常强大实用,其中版本升级这个有向图做的非常好。
[CitusDB中国]站主,PostgreSQL粉丝,现从事Citus研发工作
愿Citus在中国发展的越来越好