PostgreSQL动态加载共享对象。共享对象基本上是符号到内容(函数等)的映射,这些内容被复制到进程的内存空间中。有关这方面的更多信息,请查找libdl提供dlopen(加载文件)和dlsym(查找符号)。这在 C 中很常见。此功能在 pg和实现libdl中调用。internal_load_libraryload_external_function
PostgreSQL 扩展不仅仅是编译的 C 代码,它还包含版本控制和迁移/升级信息。您可以在此处告诉 PostgreSQL 正在使用共享对象中定义的符号。例如,我制作的扩展中的这段代码,
CREATE FUNCTION repeat_materialize_preferred(object int4, times int4)
RETURNS TABLE(repeat int4)
AS 'MODULE_PATHNAME', 'repeat_materialize_preferred'
LANGUAGE C STRICT VOLATILE;
当你调用时运行CREATE EXTENSION。这就是告诉 PostgreSQL 在 SQL 中可用的名为名为的函数repeat_materialize_preferred在符号中找到的repeat_materialize_preferred,它是一个遵循 C ABI 和 PostgreSQL 调用约定的共享对象;该函数接受两个 int4 参数并返回 int4 的行集。如果不是这样,对CREATE FUNCTION共享对象的调用将被加载到内存中并且对用户不可用。
PostgreSQL动态加载共享对象。共享对象基本上是符号到内容(函数等)的映射,这些内容被复制到进程的内存空间中。有关这方面的更多信息,请查找
libdl
提供dlopen
(加载文件)和dlsym
(查找符号)。这在 C 中很常见。此功能在 pg和实现libdl
中调用。internal_load_library
load_external_function
围绕此的 API 称为扩展。这些共享对象提供的函数必须标记为遵循调用约定(使用
PG_FUNCTION_INFO_V1()
)。然后LOAD
显式地扩展一个扩展,或者您调用CREATE EXTENSION
. 初始化时,PostgreSQL 查找并调用_PG_init
此共享对象中调用的函数,卸载时 PostgreSQL 调用_PG_fini
. 您可以在此处实现任何挂钩,挂钩是 PostgreSQL 在加载扩展后根据服务器触发的事件调用的功能。它不是用户显式调用的功能。PostgreSQL 扩展不仅仅是编译的 C 代码,它还包含版本控制和迁移/升级信息。您可以在此处告诉 PostgreSQL 正在使用共享对象中定义的符号。例如,我制作的扩展中的这段代码,
当你调用时运行
CREATE EXTENSION
。这就是告诉 PostgreSQL 在 SQL 中可用的名为名为的函数repeat_materialize_preferred
在符号中找到的repeat_materialize_preferred
,它是一个遵循 C ABI 和 PostgreSQL 调用约定的共享对象;该函数接受两个 int4 参数并返回 int4 的行集。如果不是这样,对CREATE FUNCTION
共享对象的调用将被加载到内存中并且对用户不可用。至于与服务器分开构建,这是可能的,因为您需要 PostgreSQL 的开发文件——与服务器相对应的头文件、库和工具——您实际上并不需要服务器本身。每个扩展都必须针对其运行的服务器的特定版本构建(尽管如果针对较早的服务器构建,它可能会起作用,因为 PostgreSQL 并没有真正破坏向后兼容性)。
评论中的脚注:虽然这个问题特定于 C,但 PostgreSQL 扩展并不限于 C,还可以用许多其他语言编写,包括 Rust、Node/v8、Python、Perl 和 plpgsql。