Неисполнение VOLATILE-функций и INSERTS в Postgresql RULE - PullRequest
2 голосов
/ 18 июля 2011

У меня возникла странная проблема с выполнением (или невыполнением) определенных запросов в правилах postgresql. Это сопутствующий (но другой) вопрос к Выполнению подзапроса Postgresql в правиле ON UPDATE (может быть, ошибка в 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?

1 Ответ

3 голосов
/ 18 июля 2011

Неизменяемые функции оцениваются на этапе планирования перед выполнением запроса.Летучие из них оцениваются по мере необходимости.Вы вернули ноль строк, поэтому они никогда не называются.

...