【问题标题】:Why doesn't PostgreSQL give a warning when calling a volatile function from a stable function?为什么从稳定函数调用易失函数时 PostgreSQL 不给出警告?
【发布时间】:2013-09-20 00:18:22
【问题描述】:

例如:

CREATE TABLE x (
    val double);

CREATE FUNCTION g() RETURNS boolean AS $$
    INSERT INTO x SELECT rand() RETURNING val>0.5;
$$ LANGUAGE SQL VOLATILE;

CREATE FUNCTION f() RETURNS boolean AS $$
    SELECT g();         -- this is where the stability-violation happens
$$ LANGUAGE SQL STABLE; -- this is a lie

根据文档,f() 也应该标记为 VOLATILE,因为调用 f() 会产生副作用。 PostgreSQL 没有给出警告(或者更好的是,一个错误),这让我相信一定有一些原因允许这个“明显”的错误存在。

【问题讨论】:

  • 查看这个相关问题:dba.stackexchange.com/questions/43099/…
  • 是的,我读过那篇文章,但它没有提供允许“明显错误”的理由(据我所知)。我希望有人可以解释如何/何时不是错误。

标签: postgresql stored-procedures volatile


【解决方案1】:

这是一个非常有趣的问题,我鼓励您将其加入 PostgreSQL 电子邮件列表。

简短的回答是,这些是通过它们所做的而不是它们调用的函数来强制执行的。

这使您可以做一些相当有趣的事情。例如,假设我想要一个值,它会为每个查询创建一个随机数:

create function rand_im() returns double precision language sql immutable as 
$$ select random(); $$;

现在我有一个不可变的随机数函数,它可以优化为一个单独的调用,发生在查询计划形成之前,因此可以用来确定索引是否有用: p>

chris=# explain analyse select * from profile_matches where id > (4 * rand_im());
                                                 QUERY PLAN                     

--------------------------------------------------------------------------------
-----------------------------
 Seq Scan on profile_matches  (cost=0.00..39.10 rows=647 width=12) (actual time=
0.009..0.010 rows=1 loops=1)
   Filter: ((id)::double precision > 3.24490546248853::double precision)
 Total runtime: 0.022 ms
(3 rows)

所以这里我们有一个“不可变”,它调用了一个明显易变的函数,这实际上很有用,因为它允许我们创建一个将被展平的函数,并且可以为查询提供一个精确的值。

现在,根据另一个链接,我真的不知道关于调用 volatile 函数的稳定函数会发生什么。据我所知,这只是一个优化的事情,保护非常少,但我不能保证总是允许 db 副作用。

此外,需要考虑的一个简单问题是函数是不透明的,并且不可能在所有程序语言上阻止这种事情。考虑一下您可以拥有一个可以标记为不可变但可以运行查询的 Java 函数(这可能不是一件好事)。所以这似乎是一个明显的错误,但它实际上是一个潜在有用的错误。

【讨论】:

  • 你说:这些是由它们所做的,而不是它们调用的函数来强制执行的。调用什么函数不是“他们做什么”的事情吗?
  • 我本来可以更清楚的。这些是针对规划要求执行的。这实际上意味着“他们对您的数据所做的事情”。很抱歉造成混乱。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多