首先看下GP7内置函数处理机制:GP7的内置函数机制和GP6稍有不同。其中内置函数元数据信息来自pg_proc.dat。pg_proc.dat中是什么东西呢?
...
...
例如加法的函数int4_sum。这里解释下几个重要成员:oid为函数的OID,descr为函数的描述,proname为函数名,proretype为函数返回值类型,proargtypes为函数所有入参类型,prosrc为函数。这些内容构成了所有内置函数的元数据信息。(如果需要新添加用户自定义函数,可以在这里添加元数据信息)。
GP7通过gen_fmgrtab.pl的perl脚本利用pg_proc.dat元数据生成fmgroids.h、fmgrprotos.h和fmgrtab.c三个文件。
其中fmgroids.h是所有内置函数的OID宏定义:
extern Datum heap_tableam_handler(PG_FUNCTION_ARGS); extern Datum byteaout(PG_FUNCTION_ARGS); extern Datum charout(PG_FUNCTION_ARGS); ...
fmgrprotos.h为所有内置函数的声明:
typedef struct { Oidfoid;/* OID of the function */ shortnargs;/* 0..FUNC_MAX_ARGS, or -1 if variable count */ boolstrict;/* T if function is "strict" */ boolretset;/* T if function returns a set */ const char *funcName;/* C name of the function */ PGFunctionfunc;/* pointer to compiled function */ } FmgrBuiltin; extern const FmgrBuiltin fmgr_builtins[];
fmgrtab.c则是每个内置函数的信息,再介绍该信息前,先看下fmgrtab.h中内置函数描述结构:
typedef struct{Oidfoid;/* OID of the function */shortnargs;/* 0..FUNC_MAX_ARGS, or -1 if variable count */boolstrict;/* T if function is "strict" */boolretset;/* T if function returns a set */const char *funcName;/* C name of the function */PGFunctionfunc;/* pointer to compiled function */} FmgrBuiltin; extern const FmgrBuiltin fmgr_builtins[];
通过fmgr_builtin[]数组来存储内置函数的描述信息,包括其OID、函数名、函数指针等。fmgrtab.c中生成的数组信息:
const FmgrBuiltin fmgr_builtins[] = { {3,1,true,false,"heap_tableam_handler",heap_tableam_handler}, {31,1,true,false,"byteaout",byteaout}, {33,1,true,false,"charout",charout}, ... }
至此,若要开发写一个自定义内置函数,需要以下几步:
1、在pg_proc.dat中填写自定义函数信息
2、编译时gen_fmgrtab.pl脚本可自动生成自定义函数相关元数据信息
3、编写对应自定义函数,注意其返回值、入参个数及类型要和pg_proc.dat中填写的一致