1

出于测试目的,我提供了我自己的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 将用于查找正确的模式。但是,转储或恢复操作似乎将该功能“绑定”到当前功能。

我对函数的“绑定状态”的理解是否正确?有没有办法在转储/恢复边界上保持函数的无限性?

4

3 回答 3

2

默认值在创建时解析(早期绑定!)。您在 psql、pgAdmin 或其他客户端中看到的是文本表示,但实际上,创建列 default 时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 显示函数模式限定的名称,因为它不会再用当前的search_path.

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

覆盖内置函数

放在public前面pg_catalogsearch_path一个危险的游戏。弱势用户(包括您自己)通常被允许在那里编写并创建可能无意中推翻系统功能的功能 - 具有任意(或恶意)结果。

您需要一个具有受限访问权限的专用模式来覆盖内置函数。改用这样的东西:

SET search_path = override, pg_catalog, public;

dba.SE 上此相关答案中的详细信息。

于 2014-07-31T20:50:01.190 回答
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

如果绑定只发生在插入时,就不会有这种依赖。

于 2014-07-31T20:51:46.437 回答
-3

不要打扰这一切。Postgres 有时会在编译后写一些奇怪的东西。尤其是视图经常在无法识别的情况下发生变化。

并且: 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';

不用担心。

于 2014-07-31T20:21:04.770 回答