扩展打包

来自 PostgreSQL wiki
跳转到导航跳转到搜索

参见 [[1]]

PostgreSQL 扩展

这是关于 PostgreSQL 扩展的用户设计的首轮。我尝试将许多不同的人表达的想法汇集在一起。这里的目标是首先就命名和目标达成一致,然后讨论我们提出的用户设计。

名称

竞争者有 extension、module、bundle 和 package。获胜者是 extension。

module 在 SQL 标准中是其他东西,bundle 是一个不错的选择,package 肯定会让人觉得我们与 Oracle 兼容(我们不想拥有 Ada 这样的骨架和主体),而 extension 正是 PGXS 为之而生,也是我们 -你-命名-它- 作者所做的。

v1.0 目标

我们没有试图在第一轮就做到功能齐全。

必须拥有

- 转储和恢复支持(在升级集群或只是恢复时)

- 易于安装和卸载

- 支持仅限于 SQL/PLpgSQL 的自建扩展,以便简化内部基于 PG 的开发(您不必用 C 编码就能从扩展中受益)

- 支持“基本”模块,提供类型及其操作符和索引支持,例如 ip4r、hstore、temporal、prefix 和许多其他,你随便说,甚至更简单的事情,比如 preprepare 或 backports/min_update。

- 支持过程语言(先验地可以轻松地涵盖在基本模块中,但我不确定),例如 plproxy、pllolcode、pllua、plscheme、plsh 等。

- 支持您在 contrib/ 中为 8.4 找到的所有内容(已经涵盖了吗?)

将会很棒(目标是稍后的提交节)

- 版本支持,支持就地升级(钩子?)

- 支持在同一时间安装同一模块的多个版本,可能(我认为总是,但……)在不同的模式中

- 自定义变量?

- PostGIS 全面支持,包括用户数据依赖性,即使可扩展的 typmod 系统肯定会在更合适的地方解决这个问题。也许有人会提出另一个共享问题的现有扩展,而不是 typmod 解决方案?

- 核心团队批准的扩展列表(替换 contribs,可能添加到其中),其中批准意味着代码已过审,它没有成为核心本身的唯一原因是核心团队认为它不是 RDBMS 的一部分,或者认为代码应该单独维护和发布,直到它获得更多现场曝光……(想想 plproxy)。

稍后再说

- CPAN 或 ports 类似的用于自动下载或多或少准备好的“捆绑包”的基础设施,将其放置在文件系统的正确位置,并在您选择的数据库中安装它

- 对非通用模块(如 pljava)的 ad-hoc 引导的复杂支持

- 依赖关系图求解和自动安装,带有 depends、recommends 和 suggest 部分,以及用于选择默认情况下要拉取哪些内容的规则/设置……

转储和恢复

我们希望 pg_dump 针对每个扩展只发出一个行,即在数据库中安装扩展的那一行,参见语法。

语法

扩展将需要元数据,在阅读了几个建议后,我在这里建议有一个明确的第一步来注册扩展名称和元数据,然后使用“基本”工具来操作它。

创建扩展(创作)

'foo' 扩展的作者需要提供一个 +foo.sql+ 文件,其中包含以下内容

 create extension foo 
   with version 1.0
        install [script] 'foo.install.sql'
        uninstall [script] 'foo.uninstall.sql'
        upgrade function upgrade_foo(old version, new version)
        [ custom_variable_classes 'a,b' 
          configuration file 'foo.conf' ]
   depends on bar version 0.3
       and on baz version >= 1.2;

这里我们假设我们还拥有一个新的数据类型“version”来保存版本信息,以及相关的运算符。参见 http://packages.debian.org/sid/postgresql-9.0-debversion

通过这种方式,我们跳过了提供一种方式来告诉“下一个命令是用于创建属于该扩展的 SQL 对象”的需要,但需要作者管理升级以添加对象。

升级功能是强制性的,必须返回已安装的版本或 null,表示“请再次运行安装脚本,这就是我升级的方式”。错误管理是通过 RAISE EXCEPTION 来完成的。

如果要安装或卸载时调用特定函数,则可以在定义完函数后,在安装脚本中使用 SELECT install_function(); 来轻松完成。为了支持这一点,PG 在运行这些脚本时将提供内部 GUC(在 postgresql.conf 中不公开),并由 PG 设置,名为 current_extension 和 current_extension_version。

安装和删除扩展

 begin;
 install extension foo;
 commit;

扩展及其对象最终会出现在 pg_extension 中,作者不应该明确创建要在其中生存的模式,因为这意味着用户必须考虑调整他们的 search_path,这有时会变得很麻烦。这条规则有一些例外,例如 PGQ/Londiste,您可以将其安装在数据库中,然后使用命令行工具来安装触发器。触发器当然可以轻松地引用 pgq.logutrigga() 函数,因此用户无需直接接触模式选择。在这种情况下,作者可以自由地创建特定模式。

 begin;
 drop extension foo [cascade];
 commit;

“cascade”选项用于处理反向依赖关系。

ACL

扩展对象的大量 ACL 管理被推送到 GRANT/REVOKE 的通配符支持项目中,因此我们不必在这里讨论它会是什么样子。:)

操作系统文件系统交互

PostgreSQL 已经提供了通过 PGXS 安装扩展的标准路径,并且发行版打包者能够适应这些路径。我们应该坚持使用它,这意味着问题已经解决。

在操作系统级别打包扩展

使用 PGXS 和一些粘合剂,我们可以为 PostgreSQL 提出一套基于源代码的扩展打包工具

pg_ext add-mirror http://extensions.postgresql.org/
pg_ext list [remote | available]
pg_ext add plproxy prefix citext
pg_ext install mydatabase plproxy prefix
pg_ext drop [--force] plproxy mydatabase
pg_ext remove <package> ...
...
  • add-mirror 允许直接从远程 url 获取,您获取的是源代码 tarball。存储库将必须按主要 PostgreSQL 版本进行组织,pg_ext 的行为将在其“编译”时确定,因此您将获得与它一起提供的 major 版本的硬编码。
  • add 命令将检索 <extension> 的源代码 tarball,并从(可配置的)临时位置运行 make && make install。为了支持扩展,它必须使用 PGXS 标准,并提供一个简单的 make && make install 机制。这是现实的吗?PostGIS 会适合吗?
  • 然后,install 将为您发出 SQL,就像 drop 一样,因此这些是方便的包装器。
  • remove 命令将仅在您的集群数据库中不再使用扩展时才会从磁盘中删除它,并且它将负责在 SQL 级别删除模块对象。Mrmmm.... 还是会呢?

分发扩展

如果您是发行版打包者,现在可以使用 pg_ext 工具轻松打包扩展。这项工作包括为您支持的架构提供编译的 .so,当发行版级别的包安装好后,下一步是使用安装扩展到其数据库中。因此,它就像这样

apt-get install postgresql-8.5-plproxy
psql mydb
=# install extension plproxy;

或者可能是这样

apt-get install postgresql-8.5-plproxy
pg_ext install mydb plproxy

代码设计

http://archives.postgresql.org/pgsql-hackers/2009-07/msg01425.php

- 创建 pg_catalog.pg_extension 条目以及与版本相关的命令,一次只做一件事

- 在 pg_extension 中引导核心组件,使其依赖于它们(plpgsql,…)

- 实现一个后端函数 pg_execute_commands_from_file('path/ to/file.sql'); 仅供超级用户使用,文件位于通常接受的位置

- 使用前面的函数实现 INSTALL EXTENSION

- 添加一个静态后端局部变量 installing_extension (oid)

- 修改每个 SQL 对象创建语句,以在 pg_depend 中添加条目 - 添加一个用于处理版本号及其比较运算符的特定类型

pg_execute_commands_from_file

http://archives.postgresql.org/pgsql-hackers/2009-07/msg01468.php

特别是,您认为实现类似于 psql 的 \i 的通用后端函数怎么样(除了不支持 \commands 和 :variables)

 SELECT pg_execute_commands_from_file('path/ to/file.sql'); 

您最近关于拥有可重入解析器的作品应该可以实现,通过“扩展”或复制/粘贴 postgres.c:exec_simple_query,对吗?

(区别在于是否覆盖当前未命名的门户,也许

forcing PortalRunMulti() usage, and that there's already a started
transaction (but start_xact_command() is a noop in this case))

开放项目

根据记忆,以下是我们还没有找到解决方案的问题

- 如何让用户能够将扩展的对象安装到除 pg_extension 默认模式之外的其他模式

- 如何为扩展作者提供一种方法,使他们能够拥有主要 PG 版本相关的代码,而无需在他们的 install.sql 文件中实现和维护特定函数