【问题标题】:Non-execution of VOLATILE functions and INSERTS within Postgresql RULE在 Postgresql RULE 中不执行 VOLATILE 函数和 INSERTS
【发布时间】:2011-07-18 02:15:10
【问题描述】:

我在 postgresql RULES 中执行(或不执行)某些查询时遇到了一个奇怪的问题。这是Postgresql subquery execution within ON UPDATE rule (maybe bug in postgresql?) 的一个伴随问题(但不同) - 但事实证明,某些查询在 postgresql 规则中根本没有执行,而不仅仅是查询执行顺序的问题。

考虑以下代码块:

DROP TABLE foo_table;
DROP TABLE bar_table;

--------------

CREATE TABLE foo_table (c1 text, c2 int);
CREATE TABLE bar_table (c1 text, c2 int);

--------------

CREATE OR REPLACE FUNCTION debug_immutable(anyelement) RETURNS integer AS $$

pg_raise('notice', 'debug(): ' . json_encode($args[0]));

return rand(1, 10000);

$$ LANGUAGE PLPHP IMMUTABLE;

CREATE OR REPLACE FUNCTION debug_volatile(anyelement) RETURNS integer AS $$

pg_raise('notice', 'debug(): ' . json_encode($args[0]));

return rand(1, 10000);

$$ LANGUAGE PLPHP VOLATILE;

-------------

CREATE OR REPLACE RULE foo_update_rule AS ON UPDATE TO foo_table DO INSTEAD
(

SELECT debug_immutable('debug_immutable call 1'::text); -- Query #1

SELECT debug_volatile('debug_volatile call 1'::text);   -- Query #2

INSERT INTO foo_table (c1, c2) values ('foo', 123456);  -- Query #3

INSERT INTO bar_table (c1, c2) values ('bar', 123456);  -- Query #4

SELECT debug_immutable('debug_immutable call 2'::text); -- Query #5

SELECT debug_volatile('debug_volatile call 2'::text);   -- Query #6
);

-----------------------------------------------

UPDATE foo_table SET c1 = NULL where c1 = 'aaa';

SELECT * FROM foo_table;

SELECT * FROM bar_table;

输出仅显示以下内容:

NOTICE:  plphp: debug(): "debug_immutable call 1"
NOTICE:  plphp: debug(): "debug_immutable call 2"
Total query runtime: 46 ms.
0 rows retrieved.

并且代码块执行后 foo_table 和 bar_table 都显示为空:

# select * from foo_table;
 c1 | c2 
----+----
(0 rows)

# select * from bar_table;
 c1 | c2 
----+----
(0 rows)

输出意味着只有查询 #1 和 #5 被执行,而查询 #2、3、4 和 6 永远不会执行。为什么是这样?如何更改上述代码块以执行查询#2、3、4 和 6?

【问题讨论】:

  • 重点是您滥用(并且似乎误解了)规则系统。您想要调查的内容可以通过调查生成的查询计划来完成。

标签: postgresql immutability rules


【解决方案1】:

在执行查询之前,在规划阶段评估不可变函数。挥发性的根据需要进行评估。您返回了零行,因此它们永远不会被调用。

【讨论】:

  • 确认你是对的!!我添加了以下内容(INSERT INTO foo_table (c1) VALUES('aaa');)在更新之前向 foo_table 中插入一行,现在所有 6 个查询都已执行!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-30
  • 2014-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多