pg_restore:如果表具有函数调用另一个函数的约束,则无法导入数据



在仅使用public模式的PostgreSQL中,在检查约束中使用调用其他函数的表中的数据在与pg_dump一起转储后不会与pg_restore一起导入。但是,如果检查约束中的函数不调用其他函数,则会正确导入数据。

从 9.3.22 到 9.3.23 和从 9.4.16 到 9.4.17 的小升级后,我注意到了这种行为; 在 9.3.22 和 9.4.17 中它工作正常。

我了解是由于search_path的变化:

避免在pg_dump和其他客户端中使用不安全的search_path设置 节目(诺亚·米施、汤姆·莱恩)

pg_dump、pg_upgrade、vacuumdb 和其他 PostgreSQL 提供的 应用程序本身容易受到劫持类型的攻击 在前面的更新日志条目中描述;由于这些应用程序 通常由超级用户运行,它们特别有吸引力 目标。使它们安全,无论安装是否作为 整体已得到保护,请修改它们以仅包含pg_catalog 其search_path设置中的架构。自动真空作业过程现在 也这样做。

在用户提供的功能由 这些程序 — 例如,索引中用户提供的函数 表达式 — search_path越紧密可能会导致错误,这将 需要通过将用户提供的功能调整为不 假设它们在哪个搜索路径下调用。那 一直是很好的做法,但现在有必要 正确的行为。(CVE-2018-1058 或 CVE-2018-1058)

我仍然不清楚为什么允许拥有一级公共函数,但不是这些函数可以调用其他函数。

例如,具有以下结构和数据:

CREATE OR REPLACE FUNCTION is_even(n integer) RETURNS boolean AS $BODY$ 
BEGIN
return n%2 = 0;  
END ; $BODY$  LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION is_even_positive(n integer) RETURNS boolean AS $BODY$ 
BEGIN
return is_even(n) and n > 0;  
END ; $BODY$  LANGUAGE plpgsql;

CREATE TABLE test_check (
n integer
CONSTRAINT even_chk CHECK (is_even(n)));
CREATE TABLE test_check2(
n integer
CONSTRAINT even_positive_chk CHECK (is_even_positive(n)));
insert into test_check values (2);
insert into test_check values (-2);
insert into test_check2 values (2);

导出时:

pg_dump -h localhost -p 5432  -F c -b -v -f test.dmp test -U test

并将其导入新数据库:

$ pg_restore -d test2 -U test -v test.dmp -h localhost
pg_restore: connecting to database for restore
pg_restore: creating SCHEMA "public"
pg_restore: creating COMMENT "SCHEMA public"
pg_restore: creating EXTENSION "plpgsql"
pg_restore: creating COMMENT "EXTENSION plpgsql"
pg_restore: creating FUNCTION "public.is_even(integer)"
pg_restore: creating FUNCTION "public.is_even_positive(integer)"
pg_restore: creating TABLE "public.test_check"
pg_restore: creating TABLE "public.test_check2"
pg_restore: processing data for table "public.test_check"
pg_restore: processing data for table "public.test_check2"
pg_restore: [archiver (db)] Error while PROCESSING TOC:
pg_restore: [archiver (db)] Error from TOC entry 2035; 0 7784774 TABLE DATA test_check2 tad
pg_restore: [archiver (db)] COPY failed for table "test_check2": ERROR:  function is_even(integer) does not exist
LINE 1: SELECT is_even(n) and n > 0
^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
QUERY:  SELECT is_even(n) and n > 0
CONTEXT:  PL/pgSQL function public.is_even_positive(integer) line 3 at RETURN
COPY test_check2, line 1: "2"
pg_restore: creating ACL "SCHEMA public"
WARNING: errors ignored on restore: 1

请注意test_check表与数据一起正确导入,而test_check2失败。

解决方案是为函数显式设置search_path

那么pg_restore设置search_path = pg_catalog就没关系了,因为它将被函数的设置覆盖。

这还将防止函数无意中从调用会话中设置的不同架构中选取函数和运算符(这是更改试图修复的安全问题)。

ALTER FUNCTION is_even_(integer) SET search_path=public;
ALTER FUNCTION is_even_positive(integer) SET search_path=public;

相关内容

  • 没有找到相关文章

最新更新