使用hstore在C中编写PostgreSQL UDF

4

我正在用C语言编写一个针对PostgreSQL的扩展程序,需要在我的用户定义函数中使用hstore。 我可以构建它而不出现错误(使用pgxc),但无法在SQL查询中使用任何函数。

我尝试了PG_LIBS=hstore,但在加载库时出现未定义引用错误。

接下来尝试的是SHLIB_LINK=-L/usr/lib/postgresql/9.1/lib -lhstore(系统中不存在libhstore.so,只有hstore.so,因此我尝试使用符号链接和硬链接),但得到了

psql:libname.sql:69: ERROR:  could not load library
"/usr/lib/postgresql/9.1/lib/libname.so": libhstore.so: cannot open shared 
object file: No such file or directory

1
这里的信息实在太少了。根据您共享的对象名称,我猜测您正在使用 Linux 或 BSD,并且似乎正在使用 PostgreSQL 9.1。第一次出现了什么未定义引用错误? - Craig Ringer
是的,它是Linux和PostgreSQL 9.1。未定义的引用是对Pairs、HStore以及在hstore.h中公开的一些函数的引用。 - user1811265
1个回答

6

据记忆,hstore 没有暴露出很多 C API。您必须通过 服务器编程接口 (SPI) 使用它,通过您的 C 扩展使用其 SQL 级别接口。 更新:或者,正如 Tom Lane 在邮件列表中指出的那样,使用 fmgr 调用其公开的 SQL 函数,而不是使用 SPI 运行完整的 SQL 语句。更新2:另一种选择是直接 load_external_function("extension", "symbol") 加载 C 函数;参见 fmgr.h

大多数你尝试使用的hstore函数将被声明为static(因此它们是本地于hstore模块的),这可能是你为什么得到未定义引用的原因。你只能使用在hstore.h中声明为宏或extern函数的内容。你不能直接通过C语言链接调用在(例如)hstore_io.c中找到的任何函数。 PG_LIBS允许您指定要链接的共享库,但hstore.so不是一个典型的共享库,在编译期间进行链接。它是一个PostgreSQL扩展模块,旨在由服务器dlopen()。我认为不支持一个扩展模块链接到另一个扩展模块。这意味着你可能甚至无法使用extern函数而不需要进行大量的黑客工作。
使用SPI、fmgrload_external_function
如果使用load_external_function,你可能需要管理内存上下文和其他调用上下文。尝试找到其使用示例。
参见:

谢谢,我会尽快尝试两个版本,一旦我能够接触到我的电脑。我还回答了您在问题本身上的评论,只是为了其他人能够看到,虽然我不认为操作系统甚至pg版本在这种情况下真的很重要。 - user1811265
@user1811265 可能不需要,但这样做可以节省时间,最好包括在内,即使你不确定,尤其是当涉及到环境变量、链接器错误等时。引用链接器错误也是很好的做法。 - Craig Ringer
1
现在我在_PG_init()函数中只调用一次load_external_function以避免函数查找开销。这些调用在子事务中进行,以防止模块加载失败,例如hstore扩展没有安装或其API在运行时发生更改。指针存储在TopMemoryContext中,并在_PG_fini()函数中进行了pfree处理。当我调用hstore时,我没有看到PostgreSQL切换内存上下文,因为其返回的引用值似乎完好无损,因此没有必要手动切换到顶层上下文以进行每个hstore调用。这是否足够安全? - user1811265
@user1811265,老实说我不确定。如果它能正常工作并且你找不到泄漏的证据,那么可能是可以的。但要确保,我需要进行更多的研究,而目前我无法花费太多时间。 - Craig Ringer
@user1811265,最重要的资源是源代码;那就是我要阅读的内容。 - Craig Ringer
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接