什么是默认值表达式函数绑定到search_path?

时间:2014-07-31 20:07:50

标签: sql postgresql default search-path

出于测试目的,我提供了自己now()函数的实现,即public.now()。使用search_path覆盖我自己版本的默认pg_catalog.now()大部分都有效,但我有一个表格,其表格的默认表达式为now()。显示该表会产生类似于以下内容的内容:

 start_date   | date    | not null default now()

但是,在架构保存和恢复(到测试数据库)之后,同一个show table会生成

 start_date   | date    | not null default pg_catalog.now()

我假设,最初默认表达式中的函数没有绑定到任何模式,search_path将用于查找正确的模式。但是,转储或恢复操作似乎"绑定"当前的功能。

我对"绑定状态的理解"功能正确吗? 有没有办法在转储/恢复边界之间保持函数的非绑定性?

3 个答案:

答案 0 :(得分:2)

在创建时解析默认值(早期绑定!)。您在psql,pgAdmin或其他客户端中看到的是文本表示,但实际上,在创建列默认值时,函数OID的{​​{1}}存储在系统目录{{3 }}。我引用:

now()

当您更改pg_attrdef时,会导致Postgres显示符合模式的函数的名称,因为使用当前adbin pg_node_tree The internal representation of the column default value adsrc text A human-readable representation of the default value 无法正确解析它。

转储和恢复与您的自定义search_path设置无关。他们明确地设定了它。所以你看到的与转储/恢复周期无关。

覆盖内置函数

search_path public之前放置pg_catalog危险游戏。弱势用户(包括你自己)经常被允许在那里写作并创建可能无意中否决系统功能的功能 - 具有任意(或恶意)结果。

您希望专用架构具有受限访问权限来覆盖内置函数。请改用这样的东西:

search_path

search_path中的详细信息。

答案 1 :(得分:2)

默认功能是"绑定"在创建默认约束时。显示不合格名称的视图只是缩写它。

这可以通过在遮蔽函数之前和之后插入行来证明:

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

如果绑定仅发生在插入上,则不存在此类依赖关系。

答案 2 :(得分:-3)

不要打扰这一切。 Postgres有时会在编译完东西之后编写我们的东西。尤其是视图经常被改变为beyound识别。

而且:now()和pg_catalog.now()通常是一样的。参见:

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';
不要担心。