openGauss系统函数添加指导

本文介绍了openGauss数据库系统函数的架构,包括函数的身份注册和底层功能实现。详细讲解了内置函数的四种注册方式:builtin、升级脚本、CREATE FUNCTION和EXTENSION,并阐述了四种语言(INTERNAL, SQL, PLPGSQL, C)的实现特点。同时,文章提供了添加普通INTERNAL函数和聚集函数的步骤,包括声明函数身份、实现功能代码、关联声明实现和编写升级脚本。此外,还讨论了函数的验证过程,确保功能的正确性和升级的顺利进行。" 118341382,8392978,使用Zeppelin的Helium模块增强可视化,"['大数据开发', '数据可视化', 'zeppelin', 'helium']
摘要由CSDN通过智能技术生成

函数架构简介

openGauss内函数可以分为两个部分:

  • 身份注册声明:openGauss中存在一个系统表 pg_proc,这个表存放了所有函数的基本元信息,相当于函数的“户口本”,只有在其中可以查到的函数,才可以在SQL语句中进行调用,才有“数据库函数”的身份。常见的注册方式有四种:builtin、升级脚本、CREATE FUNCTION语句、EXTENSION。

  • 底层功能实现:实现其功能的具体逻辑代码,可以根据其所用的语言分为四类:INTERNAL, SQL, PLPGSQL、C.

四种常见的函数注册创建方式,分别对应着着不同的场景:

  • builtin:源代码中存在一个名为builtin_funcs.ini的文件,存放着一系列内置函数的元信息,在初始化安装数据库时,会通过某些方式,全量扫描此文件,将里面罗列的函数批量注册到pg_proc系统表。

  • 升级脚本:数据库由老版本升级到新版本的场景下,不会也不能遍历重刷builtin_funcs.ini到pg_proc,因此若新版本有新增函数,就需要编写一个升级脚本,在升级过程中通过升级脚本将新增函数注册到pg_proc之中。

  • CREATE FUNCTION:通过CREATE FUNCTION ... BEGIN ... END语句,一把完成注册和实现。

  • EXTENSION:随着extension进行注册和加载。

四类语言实现方案分别有不同的实现特征:

  • INTERNAL: 通常通过builtin或升级脚本进行注册,底层功能通过C语言实现的函数,也是数据库最常见的内置函数,如pg_sleep()。其底层功能函数函数名可以再pg_proc的prosrc列查到。

  • SQL: 底层功能通过一句SQL实现的函数,也是数据库内置函数的一种。如to_char() ,在数据库底层会转换为一句`select CAST(... AS VARCHAR2);`,这一句在pg_proc的prosrc列可以查到,通常是为了复用已有功能模块来适配新接口而采用这种实现方案。

  • PLPGSQL: 这个就是我们所熟知的,使用plpgsql进行编写创建的函数了,通过语句一次完成声明与实现。pg_proc的prosrc列存放了这个语句的源代码。

  • C: 出现在各种extension之中,内部功能使用C语言实现。这个和INTERNAL比较类似,区别在于其具体注册方式为通过extension进行注册,并且底层代码是在外部lib之中,而INTERNAL是在gaussdb二进制内的。可以在pg_proc的prosrc、probin列查到其lib路径以及函数符号信息。

其实无论是升级脚本还是extension,最终也都是通过create function去注册的。在create function语句中有一个language属性,便对应着四种语言,详细语法可以参考官网文档。

一个普通函数调用流程大致为:

  1. 解析SQL语句,获取到函数名以及参数值与类型等信息。

  2. 根据以上信息,在pg_proc中检索到这个函数的元数据,元数据中包含默认值、实现语言、底层函数、估算代价等所有信息。

  3. 根据其实现语言,调用其具体底层接口模块。如:INTERNAL类型会直接调用其元数据中的底层C语言代码函数;C类型会根据元数据信息加载相关lib后调用lib中的C语言代码函数;SQL类型会直接转而执行元数据prosrc中存放的sql语句;PLPGSQL类型会转而走过程语言模块解释执行prosrc中存放的源代码。

另外还有一种稍微特殊的函数——聚集函数,它其实是在普通函数的架构基础上做的功能变更与扩展,其架构和添加流程与普通函数有些差异。我们分两章介绍如何添加普通的INTERNAL函数和聚集函数。

如何添加一个普通的INTERNAL函数

了解了上面的架构与流程后,不难得出,添加一个普通的INTERNAL函数,可分为四个步骤:

  1. 声明函数身份。将我们已经提前设计好的函数的各种属性,如参数数量类型、返回值类型、稳定性等等,按照特定的格式添加进buitin_funcs.ini文件之中。

  2. 实现功能代码。在内核代码合适位置,实现一个C语言的函数,来实现对应的功能。

  3. 关联声明实现。将上一个步骤编写函数的函数名,添加到builtin_funcs.ini对应条目的对应位置。

  4. 编写升级脚本。用于在升级流程之中注册SQL函数身份。

2.1 声明函数身份

在这之前我们需要已经提前设计好自己的函数属性以及功能,如参数数量类型、返回值类型、稳定性等等,将这些信息按照特定的格式和顺序填写到./src/common/backend/catalog/builtin_funcs.ini 文件之中。

这个文件中需要按照如下结构进行书写:

AddFuncGroup(    "pg_sleep", 1,    AddBuiltinFunc(_0(2626), _1("pg_sleep"), _2(1), _3(true), _4(false), _5(pg_sleep), _6(2278), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('v'), _19(0), _20(1, 701), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("pg_sleep"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL),  _36(0), _37(false))),

可以看到其有内外两层组成。

外层为AddFuncGroup("pg_sleep", 1, AddBuiltinFunc(...)),其第一个成员变量为函数名,第二个成员变量为重载数量,后面的AddBuiltinFunc结构为函数元信息。这个结构会匹配内核代码中的结构体struct FuncGroup。需要十分注意的是,这个结构需要按照第一个成员也就是函数名的ASCII大小升序,添加到对应的位置。

内层AddBuiltinFunc为函数元信息,其目前一共含有38个属性,与内核代码结构体struct Builtin_func和系统表pg_proc都有对应关系。我们根据如下表每个属性含义,完善AddBuiltinFunc结构(可暂不关注属性5与25)。

编号

含义

对应Builtin_func

0

oid,函数的唯一标识id,需要小于10000且不可以和已有函数重复。

Oid foid;

1

函数名

const char* funcName

2

参数数量

int2 nargs

3

是否STRICT ( NULL IN NULL OUT,即若入参有NULL,则不执行,直接返回一个NULL)

bool strict

4

是否返回一个集合,就是返回多行的意思。

bool retset

5

底层C语言功能代码函数名。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值