使用 SQL 获取属于 `pg_dump` 的相同函数列表

Posted

技术标签:

【中文标题】使用 SQL 获取属于 `pg_dump` 的相同函数列表【英文标题】:Use SQL to get the same list of function that are part of a `pg_dump` 【发布时间】:2022-01-12 22:55:12 【问题描述】:

使用pg_dump,我们得到一个包含函数定义(以及许多其他数据)的转储。这是一个输出函数名称的简单 bash 脚本:

pg_dump --no-owner mydatabase | grep ^"CREATE FUNCTION" | cut -f 3 -d " " | cut -f 1 -d "("

如何使用纯 postgres SQL 获得等效列表?。我在***上尝试了许多其他答案来列出postgres中的函数,而且我通常会得到更多的函数。

编辑:

如果这很重要,我在 postgres 10.14。这是一个支持 postgis 的数据库,mydatabase 被创建为空,然后安装了一些扩展(其中包括postgis),然后通过重放包含(在常规表模式和数据中)一个列表的转储来初始化它的CREATE FUNCTION ...。我怀疑该应用程序在运行后可能会添加其他一些应用程序,并且我在pg_dump 中获得的功能列表与重放的初始转储中的功能列表接近。

bash 脚本不输出 postgis 函数名称。

如果有帮助:

$ echo "\df" | psql -qAt mydatabase | wc -l
756
$ pg_dump --no-owner mydatabase | grep ^"CREATE FUNCTION" | cut -f 3 -d " " | cut -f 1 -d "(" | wc -l
30

EDIT2:

主要问题似乎分为两部分:

选择正确的目录(似乎至少是“public”,而不是“information_schema”或“pg”) 并设法拥有与检查 findOwningExtension 等效的 SQL,因为这是防止转储来自扩展的所有函数的明显主要方法。

【问题讨论】:

使用 psql 用于\df 的 SQL 有什么问题? (我认为,这是您在其他答案中发现的内容,但我不清楚其中包含您不想要的内容。) @AdamKG 我已经编辑了问题,以便更准确地说明\df 没有给我相同的结果。 【参考方案1】:

以下是相关代码:

https://github.com/postgres/postgres/blob/65aaed22a849c0763f38f81338a1cad04ffc0e2c/src/bin/pg_dump/pg_dump.c#L6087

另请参阅前面约 30 行的详细解释性注释。我将字符串复制/粘贴到 python shell 中以连接这些行,结果是:

SELECT p.tableoid, p.oid, p.proname, p.prolang, p.pronargs, p.proargtypes, p.prorettype, p.proacl, acldefault('f', p.proowner) AS acldefault, p.pronamespace, (%s p.proowner) AS rolname FROM pg_proc p LEFT JOIN pg_init_privs pip ON (p.oid = pip.objoid AND pip.classoid = 'pg_proc'::regclass AND pip.objsubid = 0) WHERE %s
  AND NOT EXISTS (SELECT 1 FROM pg_depend WHERE classid = 'pg_proc'::regclass AND objid = p.oid AND deptype = 'i')
  AND (
  pronamespace != (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog')
  OR EXISTS (SELECT 1 FROM pg_cast
  WHERE pg_cast.oid > %u 
  AND p.oid = pg_cast.castfunc)
  OR EXISTS (SELECT 1 FROM pg_transform
  WHERE pg_transform.oid > %u AND 
  (p.oid = pg_transform.trffromsql
  OR p.oid = pg_transform.trftosql)

从查看代码可知,第一个%s应该是username_subquery,第二个应该是not_agg_check,最后两个是g_last_builtin_oid。我确实不得不在文件周围挖掘一下才能找到这些值(对于 g_last_builtin_oid,谷歌搜索它定义的 FirstNormalObjectId)。 PG 10 的最终结果,仅保留与人类相关的列(新版本略有不同):

testdb=# SELECT p.proname, p.pronamespace, (SELECT rolname FROM pg_catalog.pg_roles WHERE oid =p.proowner) AS rolname FROM pg_proc p LEFT JOIN pg_init_privs pip ON (p.oid = pip.objoid AND pip.classoid = 'pg_proc'::regclass AND pip.objsubid = 0) WHERE NOT p.proisagg
  AND NOT EXISTS (SELECT 1 FROM pg_depend WHERE classid = 'pg_proc'::regclass AND objid = p.oid AND deptype = 'i')
  AND (
  pronamespace != (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog')
  OR EXISTS (SELECT 1 FROM pg_cast
  WHERE pg_cast.oid > 16384
  AND p.oid = pg_cast.castfunc)
  OR EXISTS (SELECT 1 FROM pg_transform
  WHERE pg_transform.oid > 16384 AND 
  (p.oid = pg_transform.trffromsql
  OR p.oid = pg_transform.trftosql)));
           proname           | pronamespace | rolname  
-----------------------------+--------------+----------
 blhandler                   |         2200 | myrole
 bar                         |         2200 | myrole
 foo                         |         2200 | myrole
 _pg_expandarray             |        13327 | postgres
 _pg_keysequal               |        13327 | postgres
 _pg_index_position          |        13327 | postgres
 _pg_truetypid               |        13327 | postgres
 _pg_truetypmod              |        13327 | postgres
 _pg_char_max_length         |        13327 | postgres
 _pg_char_octet_length       |        13327 | postgres
 _pg_numeric_precision       |        13327 | postgres
 _pg_numeric_precision_radix |        13327 | postgres
 _pg_numeric_scale           |        13327 | postgres
 _pg_datetime_precision      |        13327 | postgres
 _pg_interval_type           |        13327 | postgres
(15 rows)

(这是我躺在的一个测试数据库中,不确定那些_pg_* funcs 是什么,但命名空间是 information_schema 等等)

【讨论】:

感谢这一巨大的进步,代码中的注释似乎表明答案并非微不足道。我很遗憾地告诉你,最后一个查询给了我 751 行。我的任务还没有完成,我将更深入地查看代码。真相就在编码中!。

以上是关于使用 SQL 获取属于 `pg_dump` 的相同函数列表的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL 备份与还原命令 pg_dump

PostgreSQL逻辑备份恢复--pg_dump导出及psql导入案例

使用pg_dump导出postgres db不起作用,数据库“db_name”不存在

PostgreSQL数据库备份和还原

如何修复 pg_dump 版本不匹配错误?

pg_dump命令怎么安装