暂无图片
暂无图片
3
暂无图片
暂无图片
暂无图片

postgresql 15源码浅析(4)—— Hello PostgreSQL 15

原创 夏克 2022-06-04
2226

摘要

这期主要是想填个坑,在上期中留下了一个pg_reload_conf()处理流程,找到代码看了一下,发现这块只有寥寥几行,该函数就是向postmaster进程发了一个SIGHUP信号,后续流程就是上期中的信号“1”处理流程,但pg_reload_conf()是一个内建函数,那么内建函数的调用过程涉及sql的接收、解析、执行等等,这个包含了sql引擎的一部分流程,是比较核心的内容,现阶段我还没这个能力去把这部分讲清楚,所以先从简单的开始,先介绍如何写一个内建函数,通过一个内建函数例子来学习和梳理内建函数的实现过程,同时也填上上期挖的坑。

先填坑

pg_reload_conf()函数位于postgres/src/backend/storage/ipc/signalfuncs.c文件中,实际上就是通过kill()向postmaster进程发送SIGHUP信号,而后续postmaster进程收到SIGGUP信号后的流程参见“postgresql 15源码浅析(3)—— 信号"1"的使命“。

/* * Signal to reload the database configuration * * Permission checking for this function is managed through the normal * GRANT system. */ Datum pg_reload_conf(PG_FUNCTION_ARGS) { if (kill(PostmasterPid, SIGHUP)) { ereport(WARNING,(errmsg("failed to send signal to postmaster: %m"))); PG_RETURN_BOOL(false); } PG_RETURN_BOOL(true); }
复制

内建(builtin)函数

内建函数就是postgres的内置函数,可以通过select方式调用,在第一期中介绍初始化的时候提到过,这些函数在初始化的时候被创建,通过执行postgres.bki中的后端接口将函数插入到pg_proc表中,而这些内建函数是在postgres/src/backend/utils/fmgrtab.c中注册在fmgr_builtins[]数组里。

/* * This table stores info about all the built-in functions (ie, functions * that are compiled into the Postgres executable). */ typedef struct { Oid foid; /* OID of the function */ short nargs; /* 0..FUNC_MAX_ARGS, or -1 if variable count */ bool strict; /* T if function is "strict" */ bool retset; /* T if function returns a set */ const char *funcName; /* C name of the function */ PGFunction func; /* pointer to compiled function */ } FmgrBuiltin;
复制

image.png

函数指针的定义如下:

typedef Datum (*PGFunction) (FunctionCallInfo fcinfo);
复制
  • 返回值 Datum :在32位系统中为 unsigned int型,在64位系统中位 unsigned long int,可以表示一个值或者一个指针。
  • 参数 PG_FUNCTION_ARGS:FunctionCallInfoBaseData
typedef struct FunctionCallInfoBaseData { FmgrInfo *flinfo; /* ptr to lookup info used for this call */ fmNodePtr context; /* pass info about context of call */ fmNodePtr resultinfo; /* pass or return extra info about result */ Oid fncollation; /* collation for function to use */ #define FIELDNO_FUNCTIONCALLINFODATA_ISNULL 4 bool isnull; /* function must set true if result is NULL */ short nargs; /* # arguments actually passed */ #define FIELDNO_FUNCTIONCALLINFODATA_ARGS 6 NullableDatum args[FLEXIBLE_ARRAY_MEMBER]; } FunctionCallInfoBaseData;
复制
typedef struct NullableDatum { #define FIELDNO_NULLABLE_DATUM_DATUM 0 Datum value; #define FIELDNO_NULLABLE_DATUM_ISNULL 1 bool isnull; /* due to alignment padding this could be used for flags for free */ } NullableDatum;
复制

参数列表保存在args[]中。

Hello PostgreSQL 15

实现函数功能

实现一个Hello()函数,功能非常简单,就是输出“Hello PostgreSQL 15”的字符串。

/*------------------------------------------------------------------------- * * hello.c * Returns the Hello PostgreSQL 15 string * * Copyright (c) 1998-2022, PostgreSQL Global Development Group * * IDENTIFICATION * * src/backend/utils/adt/hello.c * *------------------------------------------------------------------------- */ #include "postgres.h" #include "utils/builtins.h" Datum hello(PG_FUNCTION_ARGS) { PG_RETURN_TEXT_P(cstring_to_text("Hello PostgresSQL 15.")); }
复制

理论上可以把这个文件放在任何位置,为了“优雅”一点,我们把它放在src/backend/utils/adt/hello.c下面。

注意:需要包含两个头文件postgres.h和utils/builtins.h

修改Makefile

在这里插入图片描述

在OBJS中添加我们新建的hello目标文件。

注册hello函数

postgres/src/include/catalog/pg_proc.dat中注册hello()函数。

在这里插入图片描述

实际上pg_proc.dat是配置文件,通过postgres/src/backend/utils/Gen_fmgrtab.pl读取改文件,生成fmgrprotos.h和fmgrtab.c。

同时,postgres/src/backend/genbki.pl会生产postgres.bki文件。

文件内容如下:

  • fmgrprotos.h

在这里插入图片描述

  • fmgrtab.c

在这里插入图片描述

  • postgres.bki

在这里插入图片描述

验证

编译安装

#!/bin/bash rm -rf /home/frank/pgsql #./configure --prefix=/home/frank/pgsql --enable-debug ./configure --prefix=/usr/local/pgsql --enable-debug make -j 7 sudo make install make clean
复制

运行验证

在这里插入图片描述

总结

为PostgreSQL 15添加一个内建函数还是相对比较简单的,总结下来一共三步:1.添加函数功能(按照规范实现一个具体功能的.c代码;2.修改Makefile文件,添加新增的OBJS;3.修改pg_proc.dat配置文件,注册内建函数;

其实与写内建函数类似的做法还要两种,一是C FUNCTION;二是contrib下增加插件;这三种方法实现函数的格式基本一直,但注册方法略有不同。

今天填了一个坑。之前也写过C FUNCTION和插件实现方法,但是对这两种函数的调用流程还不是很清楚,后续把这个坑补上。

备注

待填的坑 挖坑时间 填坑帖子 填坑时间
理解bki 2022-05-22
实现自定义命令的psql 2022-05-24
pg_reload_conf()处理流程 2022-05-29 Hello PostgreSQL 15 2022-06-04
插件是如何加载的 2022-06-04

附录

pg_reload_conf调用栈

image.png

最后修改时间:2022-06-09 22:32:59
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
1人已赞赏
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论

目录
  • 摘要
  • 先填坑
  • 内建(builtin)函数
  • Hello PostgreSQL 15
    • 实现函数功能
    • 修改Makefile
    • 注册hello函数
  • 验证
    • 编译安装
    • 运行验证
  • 总结
  • 备注
  • 附录
    • pg_reload_conf调用栈