《4-宋少华-PostgreSQL Extension解析V1.0.pdf》由会员分享,可在线阅读,更多相关《4-宋少华-PostgreSQL Extension解析V1.0.pdf(30页珍藏版)》请在三个皮匠报告上搜索。
1、PostgreSQL Extension 解析演讲人 宋少华北京晟数科技&讲师Extension 运行框架Extension 运行的框架Extension 构成解析Extension 构成文件内容解析Extension 创建示例使用 CREATE EXTENSTION 创建扩展Extension 调用 hook 函数在 Extension 中使用 hook 函数CONTENTPART 01Extension 运行框架Extension 运行框架Extension 分布在 PostgreSQL 源码目录下的 contrib 目录。PART 02Extension 模块解析Makefile文件这里
2、仅解释在一个扩展文件中的基本需求变量名称描述#表示一个注释MODULE_big用于从OJBS中的多个源文件构建的共享库名称OBJS编译源码的目标名称EXTENSION用于$EXTENSIONO.control 中的扩展名称DATA安装到$prefix/share/$MODULEDIR目录下的文件PGFILEDESC用于扩展描述PG_CONFIG用于指定pg_config命令PGXS用于得到扩展Makefile文件的位置include编译时使用的的额外的Makefile文件subdir用于定义扩展模块目录的路径top_builddir用于定义扩展模块所在目录的上级上目录C源码文件C源码文件中的必
3、要定义解析名称描述PG_MODULE_MAGICPG的魔法值宏定义(在 fmgr.h 中声明)Datum表示一个无符号的整数变量(在 postgres.h 中定义 typedef uintptr_t Datum)PG_FUNCTION_INFO_V1动态加载宏定义(在 fmgr.h 中声明)PG_FUNCTION_ARGS用来在函数内部使用fcinfo来访问函数参数和元数据信息(在fmgr.h中声明)extern void _PG_init(void);声明一个函数原型,该函数主要是针对PostgreSQL提供的hook函数进行调用control文件control 文件的必要定义解析控制文件在
4、扩展中属于可选部分名称描述comment对当前扩展注释default_version指定当前扩展版本module_pathname当前扩展安装路径relocatable=true是否启用可重定位sql 文件sql 文件在 PostgreSQL 扩展中属于可选部分,只有当源码文件.c 中定义了相关函数,可在该部分编写 sql 语句,以调用创建PostgreSQL 支持的 C 语言函数。PART 03使用 CREATE EXTENSTION 创建扩展编写源码 C 文件#include postgres.h#include fmgr.h/定义魔法值PG_MODULE_MAGIC;/动态加载宏定义声明
5、函数PG_FUNCTION_INFO_V1(n_sum);/使用Datum 结构返回一个整数Datum n_sumn_sum(PG_FUNCTION_ARGS)uint32 first_val=PG_GETARG_UINT32(0 0);uint32 end_val=PG_GETARG_UINT32(1 1);uint32 sum =0 0;sum=(first_val+end_val)*end_val)/2 2;PG_RETURN_UINT32(sum);编写 Makefile 文件#求前 n 项和MODULE_big=n_sumOBJS=$(WIN32RES)n_sum.oEXTENSIO
6、N=n_sumDATA=n_sum-1.01.0.sqlPGFILEDESC=return first value add end valueifdef USE_PGXSPG_CONFIG=pg_configPGXSPGXS:=$(shell$(PG_CONFIG)-pgxs)include$(PGXS)elseelsesubdir=contrib/n_sumtop_builddir=./.include$(top_builddir)/src/Makefile.globalinclude$(top_srcdir)/contrib/contrib-global.mkendif编写控制文件root
7、rockyserver1 n_sum#cat n_sum.controlcomment=n_sumdefault_version=1.01.0module_pathname=$libdir/n_sumrelocatable=true编写 SQL 文件echo create function n_sum()CREATE FUNCTION n_sum(intint,intint)RETURNS intintAS n_sum,n_sumLANGUAGE C STRICT;编译安装并创建扩展PART 04在 Extension 中使用 hook 函数hook 函数介绍hook 函数属于 C 语言中的一
8、种回调函数,类似触发器的一种函数。hook 函数可以进行功能扩展,事件处理,调试程序。以下是一个简单示例:#ifndef HOOK_TEST_H#define HOOK_TEST_H#include#include#include#endif/定义一个事件信息的结构体structstruct EventInfo intint eventId;charchar eventName5050;/hook 函数类型定义,用于处理事件typedeftypedef voidvoid(*EventHook)(structstruct EventInfo*)*);C文件代码#include hook_test
9、.h/全局 hook 函数指针EventHook eventHook=NULL;/调用 hook 函数以处理事件voidvoid processEventprocessEvent(structstruct EventInfo*event)ifif(eventHook)eventHook(event);printf(我被调用了 n n);/注册 hook 函数并设置事件信息的值voidvoid registerEventHookregisterEventHook(structstruct EventInfo*event,EventHook hook)eventHook=hook;/设置事件信息值
10、event-eventId=1010;snprintf(event-eventName,sizeofsizeof(event-eventName),我被触发了);C文件代码/打印事件信息voidvoid printEventInfoprintEventInfo(structstruct EventInfo*event)printf(事件编号:%d n n,event-eventId);printf(事件名称:%s n n,event-eventName);intint mainmain()/创建一个事件结构体structstruct EventInfo myEvent;/注册 hook 函数并
11、设置事件信息的值registerEventHook(&myEvent,printEventInfo);/处理事件processEvent(&myEvent);returnreturn 0 0;回调结果PostgreSQL中的 hook 函数类型变量名称ClientAuthentication_hook_type客户端认证hook(include/libpq/auth.h)ExecutorCheckPerms_hook_type执行器检查访问权限hook(include/executor/executor.h)ExecutorEnd_hook_type执行器结束hook(include/exec
12、utor/executor.h)ExecutorFinish_hook_type执行器完成hook(include/executor/executor.h)ExecutorRun_hook_type执行器运行hook(include/executor/executor.h)ExecutorStart_hook_type执行器启动hook(include/executor/executor.h)ExplainOneQuery_hook_type解释SQL语句 hook()ProcessUtility_hook_type处理 SQL 语句的hook 函数(include/commands/expl
13、ain.h)check_password_hook_type检查用户密码要求 hook(include/commands/user.h)emit_log_hook_type拦截错误消息 hook(include/utils/elog.h)explain_get_index_name_hook_type解释器中获取索引名称的 hook(include/commands/explain.h)PostgreSQL中的 hook 函数类型变量名称fmgr_hook_type函数管理器 hook(include/fmgr.h)get_attavgwidth_hook_type获取表字段平均宽度 hook
14、(include/utils/lsyscache.h)get_relation_info_hook_type获取关系对象信息hook(include/optimizer/plancat.h)get_relation_stats_hook_type获取关系对象统计信息hook(include/utils/selfuncs.h)join_search_hook_type连接搜索 hook(include/executor/executor.h)needs_fmgr_hook_type确认函数是否进行函数管理器hook(include/fmgr.h)object_access_hook_type基于
15、对象oid访问 hook(include/catalog/objectaccess.h)object_access_hook_type_str基于对象名称访问 hook(include/catalog/objectaccess.h)openssl_tls_init_hook_typssl、tls初始化 hook(include/libpq/libpq-be.h)post_parse_analyze_hook_type查询解析分析 hook(include/parser/analyze.h)row_security_policy_hook_type行级安全策略 hook(include/rewr
16、ite/rowsecurity.h)PostgreSQL中的 hook 函数类型变量名称set_join_pathlist_hook_type集合操作添加 join 路径hook(include/optimizer/paths.h)set_rel_pathlist_hook_type关系对象查找路径hook(include/optimizer/paths.h)shmem_request_hook_type共享内存请求 hook(include/miscadmin.h)shmem_startup_hook_type共享内存启动 hook(include/storage/ipc.h)Postgre
17、SQL 中hook 调用示例使用客户端认证 hook 函数实现在日志中记录用户登录信息(c 代码)#include postgres.h#include fmgr.h#include libpq/auth.h#include utils/guc.h/定义魔法值PG_MODULE_MAGIC;/hook 函数声明staticstatic ClientAuthentication_hook_type clientAuthentication_hook=NULL;/初始化函数声明externextern voidvoid_ _PG_initPG_init(voidvoid);PostgreSQL 中
18、hook 调用示例使用客户端认证 hook 函数实现在日志中记录用户登录信息(c 代码)/记录登录信息staticstatic voidvoid clientAuthenticationHookclientAuthenticationHook(Port*port,intint status)ifif(status=STATUS_OK)ereport(LOG,(errmsg(主机 IP 地址:%s,port-remote_host);ereport(LOG,(errmsg(登录用户:%s,port-user_name);ereport(LOG,(errmsg(登录数据库:%s,port-data
19、base_name);ereport(LOG,(errmsg(命令行选项:%s,port-cmdline_options);voidvoid _ _PG_initPG_init(voidvoid)clientAuthentication_hook=ClientAuthentication_hook;ClientAuthentication_hook=clientAuthenticationHookclientAuthenticationHook;PostgreSQL 中hook 调用示例使用客户端认证 hook 函数实现在日志中记录用户登录信息(Makefile文件)#记录用户登录信息MODU
20、LE_big=showhostOBJS=$(WIN32RES)showhost.oEXTENSION=showhostPGFILEDESC=记录登录信息ifdef USE_PGXSPG_CONFIG=pg_configPGXSPGXS:=$(shell$(PG_CONFIG)-pgxs)include$(PGXS)elseelsesubdir=contrib/showhosttop_builddir=./.include$(top_builddir)/src/Makefile.globalinclude$(top_srcdir)/contrib/contrib-global.mkendifPostgreSQL 中hook 调用示例使用客户端认证 hook 函数实现在日志中记录用户登录信息(control文件)comment=showhostdefault_version=1.01.0module_pathname=$libdir/showhostrelocatable=truePostgreSQL 中hook 调用示例编译安装并配置到 shared_preload_libraries 中PostgreSQL 中hook 调用示例重新启动数据库,并查看日志THANK YOUCONTACT INFORMATION微信/公众号二维码