2011-07-18 46 views
2

我在執行(或不執行)postgresql RULES中的特定查詢時遇到了一個奇怪的問題。這是Postgresql subquery execution within ON UPDATE rule (maybe bug in postgresql?)的一個伴侶(但不同)問題 - 但事實證明,在postgresql RULE中有一些根本不執行某些查詢的相關問題,而僅僅是查詢執行順序的問題。在Postgresql中不執行VOLATILE函數和INSERTS規則

考慮下面的代碼塊:

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?

+0

要點是你濫用(而且似乎誤解)規則系統。您只需調查生成的查詢計劃即可完成您想要調查的內容。 – wildplasser

回答

3

在執行查詢之前,在計劃階段評估不可變函數。揮發性成分是根據需要評估的。你沒有返回行,所以他們永遠不會被調用。

+0

確定你是對的!我添加了以下內容(INSERT INTO foo_table(c1)VALUES('aaa');)在更新之前將一行插入到foo_table中,現在執行所有6個查詢!謝謝! – archmeta