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

摘要

这期主要是想填个坑,在上期中留下了一个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;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传在这里插入图片描述

函数指针的定义如下:

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和插件实现方法,但是对这两种函数的调用流程还不是很清楚,后续把这个坑补上。

备注

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

附录

pg_reload_conf调用栈

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏 克

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值