通过使用 PostgreSQL 的 C 函数接口,我们可以编写用 C 语言实现的函数,并将其集成到数据库中。这些函数可以在 SQL 查询中像其他内置函数一样被调用,从而扩展 PostgreSQL 的功能。
C 函数在某些情况下可以提供比 SQL 函数更高的执行效率,因为它们可以直接访问底层系统资源并进行更高级的优化。通过使用 C 函数,我们可以在函数内部实现复杂的算法和逻辑,利用 C 语言的功能和库来提高执行效率。
1.准备
1.1 开发文档
-- 查询数据库版本 SELECT "version"() -- PostgreSQL 12.12 (Debian 12.12-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
根据数据库的版本查看文档:
英文:PostgreSQL: Documentation: 12: 37.10. C-Language Functions
中文:37.10. C 语言函数 (postgres.cn)
1.2 工具安装
# 避免报错1 functionNameFile.c:1:10: fatal error: postgres.h: No such file or directory 1 | #include "postgres.h" | ^~~~~~~~~~~~ compilation terminated. # 根据版本进行安装【必备】安装的 postgresql12-devel.x86_64 的版本要跟数据库保持一致 yum install postgresql12-devel.x86_64 # 问题 Error: Package: postgresql12-devel-12.15-1PGDG.rhel7.x86_64 (pgdg12) Requires: llvm-toolset-7-clang >= 4.0.1 # 解决 yum install centos-release-scl-rh # 再次进行安装
2.开始
2.1 编写C语言函数
要严格按照文档的说明进行编写,创建一个新的文件,例如 func.c
,并添加以下内容:
#include "postgres.h" #include "fmgr.h" PG_MODULE_MAGIC; PG_FUNCTION_INFO_V1(add_one); Datum add_one(PG_FUNCTION_ARGS) { int32 arg = PG_GETARG_INT32(0); PG_RETURN_INT32(arg + 1); }
#include "postgres.h"
:这是一个预处理指令,用于包含 PostgreSQL 的核心头文件,以便在代码中使用 PostgreSQL 的数据类型、宏和函数。#include "fmgr.h"
:这是一个预处理指令,用于包含 PostgreSQL 函数管理器的头文件,提供了函数定义和声明所需的宏。PG_MODULE_MAGIC
:这是一个宏,它用于标识模块的版本和兼容性信息。PG_FUNCTION_INFO_V1(add_one)
:这是一个宏,用于声明函数的元数据。在这里,它将函数名add_one
与函数版本号V1
关联起来。这样 PostgreSQL 就能够正确地识别和处理这个函数。Datum add_one(PG_FUNCTION_ARGS)
:这是函数的定义,使用Datum
作为返回值类型。PG_FUNCTION_ARGS
是一个宏,它展开为一个结构体,包含了函数的参数和返回值信息。int32 arg = PG_GETARG_INT32(0)
:这是获取函数参数的值。PG_GETARG_INT32(0)
宏用于从参数列表中获取第一个参数,并将其转换为int32
类型。这里将获取到的参数值存储在int32
类型的变量arg
中。PG_RETURN_INT32(arg + 1)
:这是函数的返回语句。它使用PG_RETURN_INT32
宏将arg + 1
的结果作为函数的返回值。在这里,函数将输入的整数参数加一后返回。
这段代码的功能很简单:将输入的整数参数加一并作为函数的返回值。
2.2 编译和链接动态载入的函数
Linux环境,其他环境小伙伴儿们自行查看啊:
# 创建PIC的编译器标志是-fpic。创建一个共享库的编译器标志是-shared。 cc -fPIC -c name.c cc -shared -o name.so name.o
实例使用 C 编译器将源代码编译为共享库,例如 func.so
:
# 实例 cc -fPIC -I`pg_config --includedir-server` -c funcs.c cc -shared -o funcs.so funcs.o -I`pg_config --includedir-server` -lm # pg_config --includedir-server 的地址 [root@tcloud ~]# pg_config --includedir-server /usr/pgsql-12/include/server
- 将共享库文件复制到 PostgreSQL 的共享库目录中:
cp funcs.so `pg_config --libdir`/. # pg_config --libdir 的地址 [root@tcloud ~]# pg_config --libdir /usr/pgsql-12/lib
- 在 PostgreSQL 中创建函数的定义:
CREATE FUNCTION add_one ( INTEGER ) RETURNS INTEGER AS '/usr/pgsql-12/lib/func', 'add_one' LANGUAGE C STRICT;
现在,已经可以在 SQL 查询中使用 add_one
函数了,例如:
SELECT add_one(11);
注意:在实际应用中,可能需要进行更多的参数校验和错误处理,并支持更复杂的数组类型和维度。