PostgreSQL新增自定义相似度函数调用报错不存在问题排查
报错原因说明
你遇到的函数不存在报错由多个问题共同导致,按影响优先级排序如下:
- 系统表修改未同步到运行中的数据库
src/include/catalog/pg_proc.h是PostgreSQL初始化数据库集群时生成系统表pg_proc的模板文件,执行make && make install仅会替换安装目录下的可执行文件、初始化模板,已经初始化完成的存量数据库集群的系统表是独立存储在数据目录的磁盘文件,不会随模板修改自动更新,你新增的两条函数注册记录根本没有写入当前连接的数据库的系统表,数据库自然无法识别对应函数。
该问题有两种修复方案:- 停掉当前运行的数据库服务,使用新安装的
initdb命令初始化全新的数据库集群,基于新集群启动数据库后再测试函数调用 - 无需重新初始化集群,直接在当前数据库中执行
CREATE FUNCTION语句手动注册C函数即可
- 停掉当前运行的数据库服务,使用新安装的
- C函数实现缺少必要的调用约定声明
PostgreSQL的V1版本函数调用规范要求,所有可被SQL层调用的C函数,必须在实现前添加对应PG_FUNCTION_INFO_V1宏声明,你当前的两个函数都缺少该声明,即便系统表存在函数记录,数据库加载函数入口时也无法识别正确的调用签名,依然会触发调用失败。 - 函数参数获取写法存在错误
代码中使用的PG_GETARG_DATUM()返回值为Datum类型,不能直接赋值给text*类型指针,text类型参数的正确获取方式是使用PG_GETARG_TEXT_PP()宏,否则函数即使能被正常识别,运行时也会触发内存访问错误。 - 编译安装后未重启数据库服务
源码修改完成重新编译安装后,必须完全停止旧的PostgreSQL进程,再启动新编译的数据库程序,否则内存中运行的还是旧版本二进制,所有源码修改都不会生效。
修正参考
修正后的函数实现示例:
PG_FUNCTION_INFO_V1(levenshtein_distance); Datum levenshtein_distance(PG_FUNCTION_ARGS) { text *str_01 = PG_GETARG_TEXT_PP(0); text *txt_02 = PG_GETARG_TEXT_PP(1); int32 result=1; PG_RETURN_INT32(result); } PG_FUNCTION_INFO_V1(jaccard_index); Datum jaccard_index (PG_FUNCTION_ARGS) { text *str_01 = PG_GETARG_TEXT_PP(0); text *txt_02 = PG_GETARG_TEXT_PP(1); float4 result=1; PG_RETURN_FLOAT4(result); }
如果选择手动注册函数,在数据库中执行如下SQL即可,无需修改pg_proc.h后重新初始化集群:
CREATE FUNCTION levenshtein_distance(text, text) RETURNS int4 LANGUAGE internal STRICT AS 'levenshtein_distance'; CREATE FUNCTION jaccard_index(text, text) RETURNS float4 LANGUAGE internal STRICT AS 'jaccard_index';
内容的提问来源于stack exchange,提问作者atlantic0cean
相关产品推荐
相关产品推荐

