Postgresql pg#u restore:can';如果表有一个函数调用另一个函数的约束,则不能导入数据

Postgresql pg#u restore:can';如果表有一个函数调用另一个函数的约束,则不能导入数据,postgresql,pg-dump,pg-restore,Postgresql,Pg Dump,Pg Restore,在仅使用public模式的PostgreSQL中,使用调用其他函数的检查约束函数的表中的数据在使用pg\u dump转储后不会使用pg\u restore导入。但如果check约束中的函数不调用其他函数,则正确导入数据 在从9.3.22到9.3.23以及从9.4.16到9.4.17的小升级之后,我注意到了这种行为;在9.3.22和9.4.17中,工作正常 我理解是由于: 避免在pg_dump和其他客户端中使用不安全的搜索路径设置 节目(诺亚·米什、汤姆·莱恩) 提供pg_转储、pg_升级、vac

在仅使用
public
模式的PostgreSQL中,使用调用其他函数的检查约束函数的表中的数据在使用
pg\u dump
转储后不会使用
pg\u restore
导入。但如果check约束中的函数不调用其他函数,则正确导入数据

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

我理解是由于:

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

提供pg_转储、pg_升级、vacuumdb等PostgreSQL 应用程序本身很容易受到这种类型的劫持 在上一个变更日志条目中描述;由于这些应用程序 通常由超级用户运行,它们表现出特别的吸引力 目标。使其安全,无论安装是否作为 全部已被保护,请修改它们以仅包括pg_目录 搜索路径设置中的架构。自动真空吸尘器现在正在进行加工 也要这样做

如果用户提供的功能是由 这些程序-例如,索引中用户提供的函数 表达式-更紧密的搜索路径可能会导致错误,这将 需要通过将这些用户提供的功能调整为 假设它们在什么搜索路径下被调用。那个 一直以来都是很好的做法,但现在这将是必要的 正确的行为。(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\u check
表格正确导入数据,而
test\u check2
失败。

解决方案是为函数显式设置
搜索路径

那么
pg\u restore
设置
search\u path=pg\u catalog
就无关紧要了,因为它将被函数的设置覆盖

这还将保护函数不被无意中从调用会话中设置的不同模式中拾取函数和运算符(这是更改试图解决的安全问题)


PostgreSQL中的更多信息另一个相关
ALTER FUNCTION is_even_(integer) SET search_path=public;
ALTER FUNCTION is_even_positive(integer) SET search_path=public;