2025年9月25日: PostgreSQL 18 发布!
支持的版本: 当前 (18) / 17 / 16 / 15 / 14 / 13
开发版本: devel
不支持的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1

36.17. 将相关对象打包到扩展中 #

一个有用的 PostgreSQL 扩展通常包含多个 SQL 对象;例如,一种新的数据类型需要新的函数、新的运算符,可能还需要新的索引运算符类。将所有这些对象收集到一个包中可以简化数据库管理。 PostgreSQL 将这种包称为 扩展。要定义一个扩展,您至少需要一个 脚本文件,其中包含用于创建扩展对象的SQL命令,以及一个 控制文件,用于指定扩展本身的一些基本属性。如果扩展包含 C 代码,通常还会有一个共享库文件,C 代码将被构建到其中。一旦您拥有了这些文件,一个简单的 CREATE EXTENSION 命令就可以将这些对象加载到您的数据库中。

使用扩展的主要优点是,而不是仅仅运行SQL脚本将一堆“松散”对象加载到数据库中,PostgreSQL 将会理解扩展的对象是相关的。您可以使用单个 DROP EXTENSION 命令删除所有对象(无需维护单独的“卸载”脚本)。更有用的是,pg_dump 知道它不应该转储扩展的单个成员对象——它将只在转储中包含一个 CREATE EXTENSION 命令。这极大地简化了迁移到扩展的新版本,而新版本可能包含比旧版本更多或不同的对象。请注意,在将此类转储加载到新数据库时,您必须有扩展的控制文件、脚本文件和其他文件可用。

PostgreSQL 不允许您删除扩展中包含的单个对象,除非删除整个扩展。此外,虽然您可以更改扩展成员对象的定义(例如,通过 CREATE OR REPLACE FUNCTION 定义函数),但请记住,修改后的定义不会被 pg_dump 转储。这种更改通常只有在您同时在扩展的脚本文件中进行相同的更改时才有意义。(但对于包含配置数据的表有特殊规定;请参阅 第 36.17.3 节。)在生产环境中,通常最好创建扩展更新脚本来执行对扩展成员对象的更改。

扩展脚本可以使用 GRANTREVOKE 语句为属于扩展的对象设置权限。每个对象的最终权限集(如果设置了任何权限)将存储在 pg_init_privs 系统目录中。当使用 pg_dump 时,转储中将包含 CREATE EXTENSION 命令,然后是必要的 GRANTREVOKE 语句集,以将对象权限设置为转储时获得的权限。

PostgreSQL 目前不支持扩展脚本发出 CREATE POLICYSECURITY LABEL 语句。这些语句应在扩展创建后设置。所有 RLS 策略和安全标签将在 pg_dump 创建的转储中包含。

扩展机制还提供了打包修改脚本的机制,这些脚本可以调整扩展中包含的 SQL 对象定义。例如,如果扩展的 1.1 版本与 1.0 版本相比增加了一个函数并更改了另一个函数的正文,扩展作者可以提供一个 更新脚本 来仅进行这两个更改。然后可以使用 ALTER EXTENSION UPDATE 命令来应用这些更改并跟踪实际安装在给定数据库中的扩展版本。

可以在 ALTER EXTENSION 的描述中找到可以作为扩展成员的 SQL 对象类型。特别是,数据库集群范围的对象,如数据库、角色和表空间,不能成为扩展成员,因为扩展只在一个数据库内已知。(尽管扩展脚本不禁止创建此类对象,但如果创建了,它们也不会被跟踪为扩展的一部分。)还要注意,虽然表可以成为扩展的成员,但其附属对象(如索引)不直接被视为扩展的成员。另一个重要的点是,模式可以属于扩展,反之则不然:扩展本身具有不限定的名称,并且不存在于任何模式“之内”。然而,扩展的成员对象将在适当的时候属于模式,具体取决于其对象类型。扩展可能拥有其成员对象所在的模式,也可能不拥有。

如果扩展脚本创建了任何临时对象(如临时表),则这些对象在当前会话的剩余时间内被视为扩展成员,但会在会话结束时自动删除,就像任何临时对象一样。这是扩展成员对象不能在不删除整个扩展的情况下删除的规则的一个例外。

36.17.1. 扩展文件 #

CREATE EXTENSION 命令依赖于每个扩展的控制文件,该文件必须命名为与扩展名相同,并以 .control 作为后缀,并且必须放置在安装的 SHAREDIR/extension 目录中。还必须至少有一个SQL脚本文件,其命名模式为 extension--version.sql(例如,扩展 foo1.0 版本为 foo--1.0.sql)。默认情况下,脚本文件也放置在 SHAREDIR/extension 目录中;但控制文件可以为脚本文件指定不同的目录。

可以使用参数 extension_control_path 配置扩展控制文件的其他位置。

扩展控制文件的文件格式与 postgresql.conf 文件相同,即每行一个 parameter_name = value 赋值。允许空行和以 # 开头的注释。请确保引用任何不是单个单词或数字的值。

控制文件可以设置以下参数

directory (string) #

包含扩展SQL脚本文件的目录。除非给出绝对路径,否则名称相对于找到控制文件的目录。默认情况下,脚本文件在找到控制文件的同一目录中查找。

default_version (string) #

扩展的默认版本(如果 CREATE EXTENSION 中未指定版本,则安装该版本)。尽管可以省略此项,但如果 CREATE EXTENSION 中未出现 VERSION 选项,则会导致 CREATE EXTENSION 失败,因此通常不应这样做。

comment (string) #

关于扩展的注释(任意字符串)。在首次创建扩展时应用注释,但在扩展更新期间不应用(因为这可能会覆盖用户添加的注释)。或者,可以通过在脚本文件中编写 COMMENT 命令来设置扩展的注释。

encoding (string) #

脚本文件使用的字符集编码。如果脚本文件包含任何非 ASCII 字符,则应指定此项。否则,假定文件采用数据库编码。

module_pathname (string) #

此参数的值将替换脚本文件中的每个 MODULE_PATHNAME 出现。如果未设置,则不进行替换。通常,此参数设置为 shared_library_name,然后在 C 语言函数的 CREATE FUNCTION 命令中使用 MODULE_PATHNAME,这样脚本文件就不需要硬编码共享库的名称。

requires (string) #

此扩展依赖的扩展名称列表,例如 requires = 'foo, bar'。这些扩展必须先安装,然后才能安装此扩展。

no_relocate (string) #

此扩展依赖的扩展名称列表,这些扩展应被阻止通过 ALTER EXTENSION ... SET SCHEMA 更改其模式。如果此扩展的脚本引用了必需扩展的模式名称(使用 @extschema:name@ 语法)且无法跟踪重命名,则需要此项。

superuser (boolean) #

如果此参数为 true(这是默认值),则只有超级用户才能创建该扩展或将其更新到新版本(但另请参阅下面的 trusted)。如果设置为 false,则只需要执行安装或更新脚本中的命令所需的权限。如果脚本中的任何命令需要超级用户权限,则此参数通常应设置为 true。(这些命令无论如何都会失败,但提前给出错误会更方便用户。)

trusted (boolean) #

此参数如果设置为 true(这不是默认值),则允许一些非超级用户安装具有 superuser 设置为 true 的扩展。具体来说,只要对当前数据库具有 CREATE 权限的用户就可以安装。当执行 CREATE EXTENSION 的用户不是超级用户但由于此参数而允许安装时,安装或更新脚本将以引导超级用户的身份运行,而不是以调用用户的身份运行。如果 superuserfalse,则此参数无关紧要。通常,不应为可能允许访问通常只有超级用户才能访问的功能(如文件系统访问)的扩展将此参数设置为 true。此外,将扩展标记为受信任需要大量额外工作来安全地编写扩展的安装和更新脚本;请参阅 第 36.17.6 节

relocatable (boolean) #

如果一个扩展可以在初始创建后将其包含的对象移动到不同的模式中,那么它就是一个 可重定位 的扩展。默认值为 false,即该扩展不可重定位。有关更多信息,请参阅 第 36.17.2 节

schema (string) #

此参数只能为不可重定位的扩展设置。它强制扩展加载到指定的模式中,而不是任何其他模式。 schema 参数仅在首次创建扩展时使用,而在扩展更新期间不使用。有关更多信息,请参阅 第 36.17.2 节

除了主控制文件 extension.control 之外,扩展还可以拥有命名为 extension--version.control 风格的辅助控制文件。如果提供了这些文件,它们必须位于脚本文件目录中。辅助控制文件遵循与主控制文件相同的格式。在安装或更新到该扩展版本时,辅助控制文件中设置的任何参数都会覆盖主控制文件。但是,directorydefault_version 参数不能在辅助控制文件中设置。

扩展的SQL脚本文件可以包含任何 SQL 命令,但事务控制命令(BEGINCOMMIT 等)和不能在事务块内执行的命令(如 VACUUM)除外。这是因为脚本文件是隐式在事务块内执行的。

扩展的SQL脚本文件还可以包含以 \echo 开头的行,这些行将被扩展机制忽略(视为注释)。此约定通常用于在脚本文件被馈送到 psql 而不是通过 CREATE EXTENSION 加载时抛出错误(参见 第 36.17.7 节 中的示例脚本)。如果没有这个,用户可能会意外地将扩展内容加载为“松散”对象而不是作为扩展,这种情况恢复起来有些麻烦。

如果扩展脚本包含字符串 @extowner@,则该字符串将被替换为调用 CREATE EXTENSIONALTER EXTENSION 的用户的(适当加引号的)名称。通常,此功能由标记为受信任的扩展使用,用于将选定对象的拥有权分配给调用用户而不是引导超级用户。(不过,这样做应该小心。例如,将 C 语言函数的拥有权分配给非超级用户将为该用户创建特权提升路径。)

虽然脚本文件可以包含指定编码允许的任何字符,但控制文件应仅包含纯 ASCII,因为 PostgreSQL 无法知道控制文件的编码。实际上,这只在您想在扩展的注释中使用非 ASCII 字符时才是一个问题。在这种情况下,建议的做法是不使用控制文件的 comment 参数,而是使用脚本文件中的 COMMENT ON EXTENSION 来设置注释。

36.17.2. 扩展的可重定位性 #

用户通常希望将扩展中包含的对象加载到与扩展作者设想的不同模式中。有三种支持的可重定位级别

  • 完全可重定位的扩展可以在任何时候移动到另一个模式中,即使它已经被加载到数据库中。这是通过 ALTER EXTENSION SET SCHEMA 命令完成的,该命令会自动将所有成员对象重命名到新模式中。通常,只有当扩展不包含关于其任何对象位于哪个模式中的内部假设时,才可能这样做。此外,扩展的对象必须全部位于一个模式中(忽略不属于任何模式的对象,如过程语言)。通过在其控制文件中设置 relocatable = true 来标记完全可重定位的扩展。

  • 扩展在安装时可能可重定位,但之后不可。这通常是由于扩展脚本需要显式引用目标模式,例如在为 SQL 函数设置 search_path 属性时。对于此类扩展,在其控制文件中设置 relocatable = false,并在脚本文件中使用 @extschema@ 来引用目标模式。在脚本执行之前,此字符串的所有出现都将替换为实际目标模式的名称(如果需要,会加上双引号)。用户可以使用 CREATE EXTENSIONSCHEMA 选项来设置目标模式。

  • 如果扩展根本不支持重定位,请在其控制文件中设置 relocatable = false,并设置 schema 为目标模式的名称。这将阻止使用 CREATE EXTENSIONSCHEMA 选项,除非它指定了控制文件中命名的相同模式。当扩展包含无法通过使用 @extschema@ 替换的模式名称的内部假设时,通常需要此选项。在这种情况下,@extschema@ 替换机制也可用,尽管它的用处有限,因为模式名称由控制文件确定。

在所有情况下,脚本文件都将以 search_path 初始化为指向目标模式来执行;也就是说,CREATE EXTENSION 会执行等效于此的操作

SET LOCAL search_path TO @extschema@, pg_temp;

这允许脚本文件创建的对象进入目标模式。脚本文件可以根据需要更改 search_path,但这通常是不希望的。search_pathCREATE EXTENSION 完成后会恢复到其先前的设置。

目标模式由控制文件中的 schema 参数(如果给定)确定,否则由 CREATE EXTENSIONSCHEMA 选项(如果给定)确定,否则为当前的默认对象创建模式(调用者的 search_path 中的第一个)。当使用控制文件 schema 参数时,如果目标模式不存在,将被创建,但在其他两种情况下,它必须已经存在。

如果任何先决扩展在控制文件中的 requires 中列出,则它们的目標模式将添加到 search_path 的初始设置中,位于新扩展的目标模式之后。这允许新扩展的脚本文件可见它们的中的对象。

出于安全原因,pg_temp 会自动添加到所有情况下的 search_path 末尾。

尽管不可重定位的扩展可能包含分布在多个模式中的对象,但通常最好将所有打算供外部使用的对象放在一个模式中,该模式被视为扩展的目标模式。这种安排与依赖扩展创建期间的 search_path 默认设置非常方便。

如果扩展引用属于另一个扩展的对象,建议对这些引用进行模式限定。为此,请在扩展的脚本文件中写入 @extschema:name@,其中 name 是另一个扩展的名称(必须在此扩展的 requires 列表中)。此字符串将被替换为该扩展的目标模式的名称(如果需要,加上双引号)。虽然这种表示法避免了在扩展脚本文件中对模式名称进行硬编码的假设,但它的使用可能会将其他扩展的模式名称嵌入到此扩展的已安装对象中。(通常,当 @extschema:name@ 在字符串字面量中使用时,例如函数体或 search_path 设置。在其他情况下,对象引用在解析时会简化为 OID,并且不需要后续查找。)如果其他扩展的模式名称以这种方式嵌入,您应该防止在您的扩展安装后重新定位其他扩展,方法是将其他扩展的名称添加到此扩展的 no_relocate 列表中。

36.17.3. 扩展配置文件 #

一些扩展包含配置文件,其中包含用户在扩展安装后可能添加或更改的数据。通常,如果一个表属于一个扩展,那么 pg_dump 不会转储该表的定义或其内容。但对于配置文件来说,这种行为是不希望的;用户对数据所做的任何更改都需要包含在转储中,否则扩展在转储和恢复后将表现不同。

为了解决这个问题,扩展的脚本文件可以将它创建的表或序列标记为配置关系,这将导致 pg_dump 在转储中包含表或序列的内容(而不是其定义)。要做到这一点,请在创建表或序列后调用函数 pg_extension_config_dump(regclass, text),例如

CREATE TABLE my_config (key text, value text);
CREATE SEQUENCE my_config_seq;

SELECT pg_catalog.pg_extension_config_dump('my_config', '');
SELECT pg_catalog.pg_extension_config_dump('my_config_seq', '');

可以以这种方式标记任意数量的表或序列。与 serialbigserial 列关联的序列也可以被标记。

pg_extension_config_dump 的第二个参数为空字符串时,pg_dump 会转储表的所有内容。这通常只有在表最初是空的时才正确,就像它由扩展脚本创建的那样。如果表中存在初始数据和用户提供的数据的混合,pg_extension_config_dump 的第二个参数提供一个 WHERE 条件来选择要转储的数据。例如,您可以这样做

CREATE TABLE my_config (key text, value text, standard_entry boolean);

SELECT pg_catalog.pg_extension_config_dump('my_config', 'WHERE NOT standard_entry');

然后确保 standard_entry 仅在扩展脚本创建的行中为 true。

对于序列,pg_extension_config_dump 的第二个参数没有影响。

更复杂的情况,例如用户可能会修改的初始提供的行,可以通过在配置表上创建触发器来处理,以确保修改后的行被正确标记。

您可以通过再次调用 pg_extension_config_dump 来更改与配置表关联的过滤条件。(这通常在扩展更新脚本中有用。)将表标记为不再是配置表的唯一方法是使用 ALTER EXTENSION ... DROP TABLE 将其与扩展分离。

请注意,这些表之间的外键关系将决定 pg_dump 转储这些表的顺序。具体来说,pg_dump 将尝试先转储被引用表,然后再转储引用表。由于外键关系是在 CREATE EXTENSION 时建立的(在数据加载到表中之前),因此不支持循环依赖。当存在循环依赖时,数据仍会被转储,但转储将无法直接恢复,需要用户干预。

serialbigserial 列关联的序列需要直接标记才能转储其状态。仅标记其父关系不足以达到此目的。

36.17.4. 扩展更新 #

扩展机制的一个优点是它提供了管理扩展对象定义 SQL 命令更新的便捷方法。这是通过为扩展安装脚本的每个发布版本关联一个版本名称或编号来实现的。此外,如果您希望用户能够动态地从一个版本更新到下一个版本,您应该提供 更新脚本,这些脚本进行必要的更改以从一个版本到下一个版本。更新脚本的名称遵循 extension--old_version--target_version.sql 的模式(例如,foo--1.0--1.1.sql 包含将扩展 foo1.0 版本修改为 1.1 版本的命令)。

鉴于存在合适的更新脚本,ALTER EXTENSION UPDATE 命令可以将已安装的扩展更新到指定的最新版本。更新脚本在与 CREATE EXTENSION 为安装脚本提供的相同环境中运行:特别是,search_path 以相同的方式设置,脚本创建的任何新对象都会自动添加到扩展中。此外,如果脚本选择删除扩展成员对象,它们将自动与扩展分离。

如果扩展具有辅助控制文件,则用于更新脚本的控制参数是与脚本的目标(新)版本关联的参数。

ALTER EXTENSION 能够执行一系列更新脚本文件来实现请求的更新。例如,如果只有 foo--1.0--1.1.sqlfoo--1.1--2.0.sql 可用,当当前安装的是 1.0 而请求更新到 2.0 时,ALTER EXTENSION 将按顺序应用它们。

PostgreSQL 不假定版本名称的属性:例如,它不知道 1.1 是否遵循 1.0。它只是匹配可用版本名称,并遵循需要应用最少更新脚本的路径。(版本名称实际上可以是任何不包含 -- 或前导/尾随 - 的字符串。)

有时提供“降级”脚本很有用,例如 foo--1.1--1.0.sql 以允许撤销与版本 1.1 相关的更改。如果您这样做,请注意降级脚本可能会意外应用的可能性がある,因为它会产生更短的路径。风险情况是存在一个“快速路径”更新脚本,该脚本可以跳过几个版本,还有一个降级脚本可以回到快速路径的起点。应用降级然后再应用快速路径可能比逐个版本向前移动需要更少的步骤。如果降级脚本删除了任何不可替换的对象,这将产生不期望的结果。

要检查意外的更新路径,请使用此命令

SELECT * FROM pg_extension_update_paths('extension_name');

这会显示指定扩展的每对不同的已知版本名称,以及从源版本到目标版本将要采取的更新路径序列,或者如果不存在可用的更新路径,则显示 NULL。路径以文本形式显示,使用 -- 分隔符。如果您更喜欢数组格式,可以使用 regexp_split_to_array(path,'--')

36.17.5. 使用更新脚本安装扩展 #

一个存在已久的扩展可能存在多个版本,作者需要为这些版本编写更新脚本。例如,如果您发布了一个 foo 扩展,版本为 1.01.11.2,则应该有更新脚本 foo--1.0--1.1.sqlfoo--1.1--1.2.sql。在 PostgreSQL 10 之前,还必须创建新的脚本文件 foo--1.1.sqlfoo--1.2.sql,这些文件直接构建较新的扩展版本,否则较新版本只能通过安装 1.0 然后更新来安装。这很麻烦且重复,但现在不再需要了,因为 CREATE EXTENSION 可以自动跟踪更新链。例如,如果只有脚本文件 foo--1.0.sqlfoo--1.0--1.1.sqlfoo--1.1--1.2.sql 可用,那么安装版本 1.2 的请求将通过按顺序运行这三个脚本来处理。处理方式与您先安装 1.0 然后更新到 1.2 相同。(与 ALTER EXTENSION UPDATE 类似,如果有多个可用路径,则首选最短路径。)以这种方式组织扩展的脚本文件可以减少生成小更新所需的维护工作。

如果您在以这种风格维护的扩展中使用辅助(版本特定)控制文件,请记住每个版本都需要一个控制文件,即使它没有独立的安装脚本,因为该控制文件将决定如何执行到该版本的隐式更新。例如,如果 foo--1.0.control 指定了 requires = 'bar'foo 的其他控制文件没有,则在从 1.0 更新到其他版本时,扩展对 bar 的依赖关系将被删除。

36.17.6. 扩展的安全性注意事项 #

广泛分发的扩展应假定其所在的数据库非常少。因此,以安全的方式编写扩展提供的函数是合适的,这种方式无法被基于搜索路径的攻击所破坏。

如果扩展的 superuser 属性设置为 true,则还必须考虑其安装和更新脚本中操作的安全性风险。恶意用户很容易创建特洛伊木马对象,这些对象会破坏粗心编写的扩展脚本的后续执行,从而允许该用户获得超级用户权限。

如果一个扩展被标记为 trusted,那么它的安装模式可以由安装用户选择,安装用户可能故意使用不安全的模式,希望获得超级用户权限。因此,受信任的扩展从安全角度来看非常危险,并且必须仔细检查其所有脚本命令,以确保不会发生任何安全漏洞。

关于安全编写函数的建议在下面的 第 36.17.6.1 节 中提供,关于安全编写安装脚本的建议在下面的 第 36.17.6.2 节 中提供。

36.17.6.1. 扩展函数的安全性注意事项 #

SQL 语言和 PL 语言函数存在被搜索路径攻击的风险,因为这些函数的解析发生在执行时而不是创建时。

CREATE FUNCTION 参考页包含关于安全编写 SECURITY DEFINER 函数的建议。对于由扩展提供的任何函数,应用这些技术都是一个好习惯,因为该函数可能由具有高权限的用户调用。

如果无法将 search_path 设置为仅包含安全模式,则假定每个不限定名称的对象都可以解析为恶意用户定义的另一个对象。注意那些隐式依赖于 search_path 的构造;例如,INCASE expression WHEN 总是使用搜索路径选择运算符。在它们的位置,使用 OPERATOR(schema.=) ANYCASE WHEN expression

通用扩展通常不应假定它已安装到安全模式中,这意味着即使是对其自身对象的模式限定引用也不是完全安全的。例如,如果扩展定义了一个函数 myschema.myfunc(bigint),那么调用 myschema.myfunc(42) 可能会被一个恶意的函数 myschema.myfunc(integer) 捕获。请注意,函数和运算符参数的数据类型必须与声明的参数类型完全匹配,并在必要时使用显式转换。

36.17.6.2. 扩展脚本的安全性注意事项 #

应编写扩展安装或更新脚本,以防范脚本执行时发生的基于搜索路径的攻击。如果脚本中的对象引用可以解析为与脚本作者意图不同的对象,那么可能会立即发生安全漏洞,或者在误定义的扩展对象使用时发生。

DDL 命令如 CREATE FUNCTIONCREATE OPERATOR CLASS 通常是安全的,但要注意任何将通用表达式作为组件的命令。例如,CREATE VIEW 需要审查,CREATE FUNCTION 中的 DEFAULT 表达式也需要审查。

有时扩展脚本可能需要执行通用 SQL,例如进行无法通过 DDL 实现的目录调整。请注意使用安全的 search_path 来执行此类命令;*不要* 信任 CREATE/ALTER EXTENSION 提供的路径是安全的。最佳实践是暂时将 search_path 设置为 pg_catalog, pg_temp,并在需要时显式插入对扩展安装模式的引用。(这种做法也可能有助于创建视图。)示例可以在 PostgreSQL 源代码发行版的 contrib 模块中找到。

安全的跨扩展引用通常需要对其他扩展的对象名称进行模式限定,使用 @extschema:name@ 语法,此外还需要仔细匹配函数和运算符的参数类型。

36.17.7. 扩展示例 #

这是一个完整的示例,用于一个SQL-only 扩展,一个可以将其槽中的任何类型的值存储的二维复合类型,这些槽被命名为“k”和“v”。非文本值会自动强制转换为文本进行存储。

脚本文件 pair--1.0.sql 如下所示

-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION pair" to load this file. \quit

CREATE TYPE pair AS ( k text, v text );

CREATE FUNCTION pair(text, text)
RETURNS pair LANGUAGE SQL AS 'SELECT ROW($1, $2)::@extschema@.pair;';

CREATE OPERATOR ~> (LEFTARG = text, RIGHTARG = text, FUNCTION = pair);

-- "SET search_path" is easy to get right, but qualified names perform better.
CREATE FUNCTION lower(pair)
RETURNS pair LANGUAGE SQL
AS 'SELECT ROW(lower($1.k), lower($1.v))::@extschema@.pair;'
SET search_path = pg_temp;

CREATE FUNCTION pair_concat(pair, pair)
RETURNS pair LANGUAGE SQL
AS 'SELECT ROW($1.k OPERATOR(pg_catalog.||) $2.k,
               $1.v OPERATOR(pg_catalog.||) $2.v)::@extschema@.pair;';

控制文件 pair.control 如下所示

# pair extension
comment = 'A key/value pair data type'
default_version = '1.0'
# cannot be relocatable because of use of @extschema@
relocatable = false

虽然您几乎不需要 makefile 将这两个文件安装到正确目录,但您可以使用包含此内容的 Makefile

EXTENSION = pair
DATA = pair--1.0.sql

PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)

此 makefile 依赖于PGXS,其描述在 第 36.18 节 中。 make install 命令将把控制文件和脚本文件安装到 pg_config 报告的正确目录中。

文件安装完成后,使用 CREATE EXTENSION 命令将对象加载到任何特定的数据库中。

提交更正

如果您在文档中发现任何不正确、与您对特定功能的体验不符或需要进一步澄清的内容,请使用 此表单 报告文档问题。