PostgreSQL内核开发——使用SPI创建C函数

323 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天


说明:
服务器编程接口(SPI)给予用户定义C函数编写者在其函数内运行SQL命令的能力。SPI是一组接口函数,它们可以简化对解析器、规划器和执行器的访问。SPI也做一些内存管理。我们可以使用这些SPI来编写C函数来实现运行SQL的功能。

例子:
1、首先,我们在数据库中创建测试表并插入数据

bill=# create table test(id int,info text,crt_time timestamp);
CREATE TABLE
bill=# insert into test select generate_series(1,10),md5(random()::text),clock_timestamp();
INSERT 0 10

2、然后编写C文件
vi myupdate.c
代码如下:

#include "postgres.h"
#include "executor/spi.h"
#include "utils/builtins.h"
#include "fmgr.h"

PG_MODULE_MAGIC;


PG_FUNCTION_INFO_V1(myupdate);

Datum
myupdate(PG_FUNCTION_ARGS)
{
    char command[128];  //将SQL命令存储在大小合适的数组
    int ret;
    int proc;                       //对表数据操作的行数

    /* 将命令赋值到command */
    sprintf(command, "update test set info = 'bill' where id = %d; ", PG_GETARG_INT32(0));

    SPI_connect();             //创建连接
    ret = SPI_exec( command, 0);  //执行操作
    proc = SPI_processed;       //为行数赋值
    SPI_finish();                //中断连接
    return (proc);               //将操作行数作为返回结果
}

其中SPI_connect、SPI_exec等都是PostgreSQL中提供的SPI函数,详细的说明参考:
www.postgresql.org/docs/13/spi…

3、编译
pg11@oracle-> gcc -fpic -I/home/itm_pg/pgsql11.1/include/server -shared -o myupdate.so myupdate.c

4、将so文件复制到lib目录下
pg11@oracle-> cp myupdate.so /home/itm_pg/pgsql11.1/lib

5、加载到数据库服务器中

bill=# load 'myupdate';
LOAD

6、创建函数

bill=# create function myupdate(integer) returns integer as '$libdir/myupdate.so','myupdate' language c strict;                         
CREATE FUNCTION

7、使用测试

bill=# select myupdate(1);
 myupdate 
----------
        1
(1 row)

bill=# select myupdate(2);
 myupdate 
----------
        1
(1 row)
bill=# select * from test where id in(1,2);
 id | info |          crt_time          
----+------+----------------------------
  1 | bill | 2020-06-05 15:32:43.91827
  2 | bill | 2020-06-05 15:32:43.918443
(2 rows)

参考资料:
www.postgresql.org/docs/13/spi…