稳定(或不可变)函数可以调用 volatile 函数吗?

Dav*_*vis 4 postgresql logs exception

PostgreSQL文档状态:

任何有副作用的函数都必须标记为 VOLATILE...

考虑以下函数:

CREATE OR REPLACE FUNCTION count_items()
  RETURNS integer AS
$BODY$
DECLARE
  v_result INTEGER DEFAULT 0;
BEGIN
  SELECT
    count( t.id )
  INTO
    v_result
  FROM
    some_table t;

  RETURN v_result;

EXCEPTION
  WHEN OTHERS THEN
    PERFORM error_log_insert( SQLSTATE, SQLERRM, current_query() );
    RETURN 0;
END;
$BODY$
  LANGUAGE plpgsql STABLE
  COST 10;
Run Code Online (Sandbox Code Playgroud)

由于error_log_insert更改数据库(对异常执行插入),这是否意味着该count_items函数具有副作用(尽管是间接的),因此不能声明STABLE,但必须声明VOLATILE

换句话说,函数的稳定性或波动性是否也取决于它在其异常块中调用的函数?

如果是这种情况,那么您将如何STABLE在 PostgreSQL 中创建将所有异常记录到数据库表中的函数?

Tom*_*Tom 7

阅读文档是有序的。那来自一个只是感兴趣但从未使用过 Postgres 的人,并在第一个谷歌链接中找到了答案:

http://www.postgresql.org/docs/current/static/xfunc-volatility.html

您可能要特别强调稳定的那部分:

此类别允许优化器将函数的多个调用优化为单个调用。

所以,问题是 - 您希望记录对方法的调用。但是对一个stable函数的优化会导致该函数可能不会每次都被执行(因为相同参数的返回值是已知的,所以会被复用),所以日志会不完整。

话虽如此:

因为您只想记录异常,所以可能没问题 - 这也会使您的日志更小,因为您在查询中只得到一个实例,即使函数将被调用 1 亿次,只要优化器对其进行优化。因此,在您的情况下 - 异常日志记录 - 实际上可能没问题。您将不得不尝试 postgres 开发人员是否正在对数据库操作进行保护,但我的赌注是否定的,我认为您可以逃脱。


jco*_*and 6

在纯数学环境的情况下,我的理解是,函数f调用volatile函数的前提g也表明它f本质volatile上也是如此。那是因为数学中的函数是等价的,旨在减少解释系统的工作,一个(函数或表达式)可以代替另一个,通常作为句法糖比其他任何东西都重要。

但是,我的回答并不是专门针对 postgres 的,因为我通常不在 PG 中工作。在 PG 中,f函数是stable偶数,而g函数是,这可能是合理的volatile

我鼓励每个开发人员检查他们的代码,因为它们基本上只是公开的数学,因此鼓励您将此处的代码视为volatile.