这期内容当中小编将会给大家带来有关PostgreSQL中怎么载入外部C语言函数,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
quanzl-mac:postgresql.builtin_pool quanzl$ nm lib/plpgsql.so ... 0000000000007e10 T _pg_finfo_plpgsql_call_handler 000000000001c888 s _pg_finfo_plpgsql_call_handler.my_finfo ... 0000000000007e20 T _plpgsql_call_handler ...
这是怎么来的?直接看函数定义(src/pl/plpgsql/src/pl_handler.c):
... PG_FUNCTION_INFO_V1(plpgsql_call_handler); Datum plpgsql_call_handler(PG_FUNCTION_ARGS) { ...
所有外挂模块中的函数都是这种形式定义,返回值必须是Datum,参数必须使用预处理符 PG_FUNCTION_ARGS。plpgsql_call_handler是定义在pg_language中的存储过程处理入口,调用方式与可以在SQL中使用的函数有所不同,所以它直接使用return方式返回值。而一般的SQL函数比如earthdistance模块中的geo_distance
... PG_FUNCTION_INFO_V1(geo_distance); Datum geo_distance(PG_FUNCTION_ARGS) { ... PG_RETURN_FLOAT8(result); }
SQL定义
CREATE FUNCTION geo_distance (point, point) RETURNS float8 LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE AS 'MODULE_PATHNAME';
它必须使用 PG_RETURN_xxx 系列预处理符来返回。
返回值的使用可以参考DirectFunctionCalln(n为数字,表是参数个数)定义去理解,有必要的话另文再写,这里简单一提,主要还是讲预处理符PG_FUNCTION_INFO_V1,下边是它的定义:
#define PG_FUNCTION_INFO_V1(funcname) \ extern Datum funcname(PG_FUNCTION_ARGS); \ extern PGDLLEXPORT const Pg_finfo_record * CppConcat(pg_finfo_,funcname)(void); \ const Pg_finfo_record * \ CppConcat(pg_finfo_,funcname) (void) \ { \ static const Pg_finfo_record my_finfo = { 1 }; \ return &my_finfo; \ } \ extern int no_such_variable
再看earthdistance.so的symbol:
0000000000000de0 T _geo_distance 0000000000000dd0 T _pg_finfo_geo_distance 0000000000000fb0 s _pg_finfo_geo_distance.my_finfo
CppConcat(pg_finfo_,funcname)新定义一个前缀 pg_finfo_ 的函数,pg_finfo_geo_distance就是这么来的,它很简单,返回结构体 Pg_finfo_record,其成员 api_version 为 1。
强大的PG已经为今后扩展做好准备。
函数加载部分(src/backend/utils/fmgr/fmgr.c)的检查 fetch_finfo_record:
const Pg_finfo_record *inforec; infofuncname = psprintf("pg_finfo_%s", funcname); /* Try to look up the info function */ infofunc = (PGFInfoFunction) lookup_external_function(filehandle, infofuncname); ... inforec = (*infofunc) (); ...
上述就是小编为大家分享的PostgreSQL中怎么载入外部C语言函数了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。