关于search_path,何时/如何绑定默认值表达式函数?
-
26-12-2019 - |
题
出于测试目的,我提供了我自己的 now()
功能是 public.now()
.使用 search_path
复盖默认值 pg_catalog.now()
与我自己的版本大多工作,但我有一个表与默认表达式的表 now()
.显示该表会产生类似于以下内容的内容:
start_date | date | not null default now()
但是,在模式保存和还原(到测试数据库)后,会生成相同的显示表
start_date | date | not null default pg_catalog.now()
我从中假设,最初默认表达式中的函数不绑定到任何模式,search_path将用于查找正确的模式。但是,转储或还原操作似乎将函数"绑定"到当前函数。
我对函数的"绑定状态"的理解是否正确?有没有办法保持跨转储/恢复边界的函数的未绑定性?
解决方案
默认值在创建时解析(早期绑定!).您在psql,pgAdmin或其他客户端中看到的是文本表示,但实际上, OID
的功能 now()
在创建列时,默认值存储在系统目录中 pg_attrdef
.我引用:
adbin pg_node_tree The internal representation of the column default value
adsrc text A human-readable representation of the default value
当你改变 search_path
, ,这会导致Postgres显示函数schema限定的名称,因为它不会被正确解析与当前 search_path
.
转储和还原与您的自定义无关 search_path
设置。他们明确地设置了它。所以你看到的与转储/恢复周期无关。
复盖内置函数
配售 public
以前 pg_catalog
在 search_path
是一个 危险游戏.弱势用户(包括你自己)通常被允许在那里编写并创建可能无意中复盖系统功能的函数-具有任意(或恶意)结果。
你想要一个 具有受限访问权限的专用架构 复盖内置函数。用这样的东西代替:
SET search_path = 复盖,pg_catalog, public;
详情请参阅 有关答案dba.SE.
其他提示
默认函数在创建默认约束时为"绑定"。显示非限定名称的视图只是缩写它。
这可以通过在阴影函数之前和之后插入行来证明:
Set search_path to public,pg_catalog;
Create Temp Table foo (
test date not null default now()
);
Insert Into foo default values;
Create Function public.now() Returns timestamp with time zone Language SQL As $$
-- No idea why I chose this date.
Select '1942-05-09'::timestamp with time zone;
$$;
Insert Into foo default values;
Select * from foo;
请注意,两行(在函数创建之前和之后插入)都包含今天的日期,而不是假日期。
此外,创建一个具有上述函数的表已经在作用域中,然后尝试删除该函数,会导致依赖性错误:
Set search_path to public,pg_catalog;
Create Function public.now() Returns timestamp with time zone Language SQL As $$
Select '1942-05-09'::timestamp with time zone;
$$;
Create Temp Table bar (
test date not null default now()
);
Insert Into bar default values;
Select * from bar;
-- Single row containing the dummy date rather than today
Drop Function public.now();
-- ERROR: cannot drop function now() because other objects depend on it
如果绑定只发生在insert上,则不会有这样的依赖关系。
别那么麻烦了。Postgres有时会在编译之后编写weired东西。特别是观点经常被改变超过认可。
和:now()和pg_catalog。现在()通常是一样的。见:
CREATE OR REPLACE FUNCTION now()
RETURNS timestamp with time zone AS
'now'
LANGUAGE internal STABLE STRICT
COST 1;
ALTER FUNCTION now()
OWNER TO postgres;
COMMENT ON FUNCTION now() IS 'current transaction time';
别担心。