本节简单介绍了如何实现扩展函数.
主要内容翻译自 PostgreSQL: Simple C extension Development for a Novice User (and Performance Advantages)

一、实现步骤

假设我们已在CentOs7.x上使用源码安装了PG,当前用户为PG实例的owner(pg12),已配置好环境变量,可以运行pg_config命令


[pg12@localhost demo_plus]$ whoami
pg12
[pg12@localhost ~]$ cat .bashrc
# .bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then. /etc/bashrc
fi
# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=
# User specific aliases and functions
export PATH=/appdb/xdb/pg12beta1/bin:$PATH
export PGDATA=/data/pgsql/pg12db1
[pg12@localhost ~]$ pg_config --pgxs
/appdb/xdb/pg12beta1/lib/postgresql/pgxs/src/makefiles/pgxs.mk

创建源码目录


[pg12@localhost source]$ mkdir -p extension/demo_plus
[pg12@localhost source]$ cd extension/demo_plus/

使用C作为extension的实现语言,参照PG extension Makefile文件格式编写Makefile文件


[pg12@localhost demo_plus]$ cat Makefile
MODULES = demo_plus
EXTENSION = demo_plus
DATA = demo_plus--0.0.1.sql
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)

MODULES:扩展模块,待Build的Module
EXTENSION:扩展名称,可与Modules不同
DATA:安装脚本
0.0.1:版本

下面创建extension control文件


[pg12@localhost demo_plus]$ cat demo_plus.control
comment = 'Simple number add function'
default_version = '0.0.1'
relocatable = true
module_pathname = '$libdir/demo_plus'

comment:注释
default_version:默认版本
relocatable:是否重新加载
module_pathname:所在路径

接下来是实现文件demo_plus.c


[pg12@localhost demo_plus]$ cat demo_plus.c
#include "postgres.h"
#include "fmgr.h"
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(demo_plus);
Datum
demo_plus(PG_FUNCTION_ARGS)
{
int32 arg1 = PG_GETARG_INT32(0);
int32 arg2 = PG_GETARG_INT32(1);
PG_RETURN_INT32(arg1 + arg2);
}

逻辑很简单,输入两个数,返回两个数相加的结果.make编译


[pg12@localhost demo_plus]$ ls -l
total 12
-rw-rw-r--. 1 pg12 pg12 220 Aug  8 11:21 demo_plus.c
-rw-rw-r--. 1 pg12 pg12 123 Aug  8 11:18 demo_plus.control
-rw-rw-r--. 1 pg12 pg12 146 Aug  8 11:18 Makefile
[pg12@localhost demo_plus]$ make
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 -DOPTIMIZER_DEBUG -g3 -gdwarf-2 -fPIC -I. -I./ -I/appdb/xdb/pg12beta1/include/postgresql/server -I/appdb/xdb/pg12beta1/include/postgresql/internal  -D_GNU_SOURCE -I/usr/include/libxml2   -c -o demo_plus.o demo_plus.c -MMD -MP -MF .deps/demo_plus.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 -DOPTIMIZER_DEBUG -g3 -gdwarf-2 -fPIC demo_plus.o -L/appdb/xdb/pg12beta1/lib   -Wl,--as-needed -Wl,-rpath,'/appdb/xdb/pg12beta1/lib',--enable-new-dtags  -shared -o demo_plus.so

最后一步,创建sql文件用于生成函数


[pg12@localhost demo_plus]$ cat demo_plus-0.0.1.sql
CREATE OR REPLACE FUNCTION
demofunc1(int,int) RETURNS int AS 'MODULE_PATHNAME','demo_plus'
LANGUAGE C STRICT;
[pg12@localhost demo_plus]$

执行make install安装


[pg12@localhost demo_plus]$ sudo make install
make -C ../../src/backend generated-headers
make[1]: Entering directory `/data/source/postgresql-12beta1/src/backend'
make -C catalog distprep generated-header-symlinks
make[2]: Entering directory `/data/source/postgresql-12beta1/src/backend/catalog'
make[2]: Nothing to be done for `distprep'.
make[2]: Nothing to be done for `generated-header-symlinks'.
make[2]: Leaving directory `/data/source/postgresql-12beta1/src/backend/catalog'
make -C utils distprep generated-header-symlinks
make[2]: Entering directory `/data/source/postgresql-12beta1/src/backend/utils'
make[2]: Nothing to be done for `distprep'.
make[2]: Nothing to be done for `generated-header-symlinks'.
make[2]: Leaving directory `/data/source/postgresql-12beta1/src/backend/utils'
make[1]: Leaving directory `/data/source/postgresql-12beta1/src/backend'
/usr/bin/mkdir -p '/appdb/xdb/pg12beta1/share/postgresql/extension'
/usr/bin/mkdir -p '/appdb/xdb/pg12beta1/share/postgresql/extension'
/usr/bin/mkdir -p '/appdb/xdb/pg12beta1/lib/postgresql'
/usr/bin/install -c -m 644 ./demo_plus.control '/appdb/xdb/pg12beta1/share/postgresql/extension/'
/usr/bin/install -c -m 644 ./demo_plus--0.0.1.sql  '/appdb/xdb/pg12beta1/share/postgresql/extension/'
/usr/bin/install -c -m 755  demo_plus.so '/appdb/xdb/pg12beta1/lib/postgresql/'

创建extension,执行函数


testdb=# create extension demo_plus;
CREATE EXTENSION

PL/pgSQL vs C Extension
C Extension的性能接近于原生内置函数(+),而PL/pgSQL的执行时间则是原生的2倍+


CREATE FUNCTION plpgsql_demo_plus(a integer, b integer)RETURNS integer
as $$
BEGINreturn a+b;
END;
$$ LANGUAGE plpgsql;
[xdb@localhost ~]$ time psql -c "select plpgsql_demo_plus(floor(random() * (100-1+1) + 1)::int,x) from generate_series(1,1000000) as x" -p 5433 -d testdb > out.txt
real    0m3.753s
user    0m0.924s
sys    0m0.658s
[xdb@localhost ~]$ time psql -c "select demo_plus(floor(random() * (100-1+1) + 1)::int,x) from generate_series(1,1000000) as x" -p 5433 -d testdb > out.txt
real    0m1.685s
user    0m1.005s
sys    0m0.093s
[xdb@localhost ~]$ time psql -c "select floor(random() * (100-1+1) + 1)::int+x from generate_series(1,1000000) as x" -p 5433 -d testdb > out.txt
real    0m1.666s
user    0m0.992s
sys    0m0.067s

二、配置文件说明

Makefile
MODULES
list of shared-library objects to be built from source files with same stem (do not include library suffixes in this list)
MODULE big
a shared library to build from multiple source files (list object files in OBJS)
PROGRAM
an executable program to build (list object files in OBJS)
EXTENSION
extension name(s); for each name you must provide an extension.control file, which will be installed into prefix/share/extension
MODULEDIR
subdirectory of prefix/share into which DATA and DOCS files should be installed (if not set, default is extension if EXTENSION is set, or contrib if not)
DATA
random files to install into prefix/share/$MODULEDIR
DATA_built
random files to install into prefix/share/$MODULEDIR, which need to be built first
DATA_TSEARCH
random files to install under prefix/share/tsearch_data
DOCS
random files to install under prefix/doc/$MODULEDIR
HEADERS
HEADERS_built
Files to (optionally build and) install under prefix/include/server/$MODULEDIR/$MODULE_big.
Unlike DATA_built, files in HEADERS_built are not removed by the clean target; if you want them removed, also add them to EXTRA_CLEAN or add your own rules to do it.
HEADERS$MODULE
HEADERS built $MODULE
Files to install (after building if specified) under prefix/include/server/$MODULEDIR/$MODULE, where $MODULE must be a module name used in MODULES or MODULE big.
Unlike DATA_built, files in HEADERS_built$MODULE are not removed by the clean target; if you want them removed, also add them to EXTRA CLEAN or add your own rules to do it.
It is legal to use both variables for the same module, or any combination, unless you have two module names in the MODULES list that differ only by the presence of a prefix built, which would cause ambiguity. In that (hopefully unlikely) case, you should use only the HEADERS built $MODULE variables.
SCRIPTS
script files (not binaries) to install into prefix/bin
SCRIPTS_built
script files (not binaries) to install into prefix/bin, which need to be built first
REGRESS
list of regression test cases (without suffix), see below
REGRESS_OPTS
additional switches to pass to pg_regress
ISOLATION
list of isolation test cases, see below for more details
ISOLATION_OPTS
additional switches to pass to pg_isolation_regress
TAP_TESTS
switch defining if TAP tests need to be run, see below
NO_INSTALLCHECK
don’t define an installcheck target, useful e.g. if tests require special configuration, or don’t use pg_regress
EXTRA_CLEAN
extra files to remove in make clean
PG_CPPFLAGS
will be prepended to CPPFLAGS
PG_CFLAGS
will be appended to CFLAGS
PG_CXXFLAGS
will be appended to CXXFLAGS
PG_LDFLAGS
will be prepended to LDFLAGS
PG_LIBS
will be added to PROGRAM link line
SHLIB_LINK
will be added to MODULE_big link line
PG_CONFIG
path to pg_config program for the PostgreSQL installation to build against (typically just pg_config to use the first one in your PATH)

control file
A control file can set the following parameters:
directory (string)
The directory containing the extension’s SQL script file(s). Unless an absolute path is given, the name is relative to the installation’s SHAREDIR directory. The default behavior is equivalent to specifying directory = ‘extension’.
default_version (string)
The default version of the extension (the one that will be installed if no version is specified in CREATE EXTENSION). Although this can be omitted, that will result in CREATE EXTENSION failing if no VERSION option appears, so you generally don’t want to do that.
comment (string)
A comment (any string) about the extension. The comment is applied when initially creating an extension, but not during extension updates (since that might override user-added comments). Alternatively, the extension’s comment can be set by writing a COMMENT command in the script file.
encoding (string)
The character set encoding used by the script file(s). This should be specified if the script files contain any non-ASCII characters. Otherwise the files will be assumed to be in the database encoding.
module_pathname (string)
The value of this parameter will be substituted for each occurrence of MODULE_PATHNAME in the script file(s). If it is not set, no substitution is made. Typically, this is set to $libdir/shared_library_name and then MODULE_PATHNAME is used in CREATE FUNCTION commands for C-language functions, so that the script files do not need to hard-wire the name of the shared library.
requires (string)
A list of names of extensions that this extension depends on, for example requires = ‘foo, bar’. Those extensions must be installed before this one can be installed.
superuser (boolean)
If this parameter is true (which is the default), only superusers can create the extension or update it to a new version. If it is set to false, just the privileges required to execute the commands in the installation or update script are required.
relocatable (boolean)
An extension is relocatable if it is possible to move its contained objects into a different schema after initial creation of the extension. The default is false, i.e. the extension is not relocatable. See Section 37.17.3 for more information.
schema (string)
This parameter can only be set for non-relocatable extensions. It forces the extension to be loaded into exactly the named schema and not any other. The schema parameter is consulted only when initially creating an extension, not during extension updates. See Section 37.17.3 for more information.

三、参考资料

PostgreSQL: Simple C extension Development for a Novice User (and Performance Advantages)
Packaging Related Objects into an Extension
Extension Building Infrastructure

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/6906/viewspace-2653047/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/6906/viewspace-2653047/

PostgreSQL 源码解读(216)- 实现简单的扩展函数相关推荐

  1. PostgreSQL 源码解读(147)- Storage Manager#3(fsm_search函数)

    本节简单介绍了PostgreSQL在执行插入过程中与存储相关的函数RecordAndGetPageWithFreeSpace->fsm_search,该函数搜索FSM,找到有足够空闲空间(min ...

  2. PostgreSQL 源码解读(203)- 查询#116(类型转换实现)

    本节简单介绍了PostgreSQL中的类型转换的具体实现. 解析表达式,涉及不同数据类型时: 1.如有相应类型的Operator定义(pg_operator),则尝试进行类型转换,否则报错; 2.如有 ...

  3. PostgreSQL 源码解读(155)- 后台进程#7(walsender#3)

    本节继续介绍PostgreSQL的后台进程walsender,重点介绍的是调用栈中的函数WalSndLoop->WaitLatchOrSocket->WaitEventSetWait-&g ...

  4. PostgreSQL 源码解读(153)- 后台进程#5(walsender#1)

    本节简单介绍了PostgreSQL的后台进程walsender,该进程实质上是streaming replication环境中master节点上普通的backend进程,在standby节点启动时,s ...

  5. PostgreSQL 源码解读(31)- 查询语句#16(查询优化-表达式预处理#1)

    本节简单介绍了PG查询优化对表达式预处理中连接Var(RTE中的Var,其中RTE_KIND=RTE_JOIN)溯源的过程.处理逻辑在主函数subquery_planner中通过调用flatten_j ...

  6. PostgreSQL 源码解读(35)- 查询语句#20(查询优化-简化Having和Grou...

    本节简单介绍了PG查询优化中对Having和Group By子句的简化处理. 一.基本概念 简化Having语句 把Having中的约束条件,如满足可以提升到Where条件中的,则移动到Where子句 ...

  7. PostgreSQL 源码解读(160)- 查询#80(如何实现表达式解析)

    本节介绍了PostgreSQL如何解析查询语句中的表达式列并计算得出该列的值.表达式列是指除关系定义中的系统列/定义列之外的其他投影列.比如: testdb=# create table t_expr ...

  8. PostgreSQL 源码解读(32)- 查询语句#17(查询优化-表达式预处理#2)

    本节简单介绍了PG查询优化表达式预处理中常量的简化过程.表达式预处理主要的函数主要有preprocess_expression和preprocess_qual_conditions(调用preproc ...

  9. PostgreSQL 源码解读(156)- 后台进程#8(walsender#4)

    上节介绍了PostgreSQL的后台进程walsender中的函数WalSndLoop->WaitLatchOrSocket->WaitEventSetWait->WaitEvent ...

  10. PostgreSQL 源码解读(154)- 后台进程#6(walsender#2)

    本节继续介绍PostgreSQL的后台进程walsender,重点介绍的是调用栈中的exec_replication_command和StartReplication函数. 调用栈如下: (gdb) ...

最新文章

  1. Python实用笔记 (2)list和tuple
  2. Python pip 国内镜像大全及使用办法
  3. vue 给取data值_web前端教程分享Vue相关面试题
  4. 12.MYSQL高级(二)
  5. 南京理工大学计算机学院教师信息网,南京理工大学教师信息
  6. 使用Python快速获取公众号文章定制电子书(一)
  7. P2P之UDP穿透NAT的原理与实现
  8. thinkphp在IIS7.5+环境下部署出现的URL重写问题解决方法
  9. c语言程序设计报告链表,c语言程序设计报告链表实现学生信息管理.docx
  10. 学好python浪漫表白,表白代码
  11. 恶作剧批处理(bat)代码解析
  12. 易语言-VB keypress事件中键盘上每个键的KeyAscii值
  13. 油烟浓度在线监测仪在浙江省某市餐饮油烟监测治理项目中的应用
  14. 珍惜生命之水,节约从我做起
  15. RK3399 GMAC驱动失败,打印如下log,DMA engine initialization failed 原因
  16. MuMu模拟器开发者文档
  17. Kaldi简介【开源语音识别工具】
  18. MyBatis----回顾mybatis自定义和环境搭建+完善自定义Mybatis的注解开发
  19. 北京新生儿医保办理流程【非京籍】
  20. 【输入法】搜狗输入法中英文切换

热门文章

  1. 自动化 计算机方向非核心期刊,自动化控制方向好中的核心期刊
  2. 《第二行代码》学习笔记
  3. 关于数据恢复,记一次修复SD卡 RAW 之后的修复过程
  4. wamp mysql服务无法启动_wamp中mysql无法启动怎么办
  5. 烽火狼烟丨VMware Workspace ONE Access身份验证绕过、本地提权漏洞风险提示
  6. 课堂笔记-多元函数微分
  7. 【支线】基于Aidlux的Arduino小车
  8. 邀请函|SOFA 四周年,开源正当时!
  9. Canvas箭头动画
  10. 九城加设网游防沉迷 3千名玩家声称罢玩魔兽