Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita7d71c4

Browse files
committed
Fix mishandling of OLD/NEW references in subqueries in rule actions.
If a rule action contains a subquery that refers to columns from OLDor NEW, then those are really lateral references, and the planner willcomplain if it sees such things in a subquery that isn't marked aslateral. However, at rule-definition time, the user isn't required tomark the subquery with LATERAL, and so it can fail when the rule isused.Fix this by marking such subqueries as lateral in the rewriter, at thepoint where they're used.Dean Rasheed and Tom Lane, per report from Alexander Lakhin.Back-patch to all supported branches.Discussion:https://postgr.es/m/5e09da43-aaba-7ea7-0a51-a2eb981b058b%40gmail.com
1 parent05fc551 commita7d71c4

File tree

3 files changed

+60
-4
lines changed

3 files changed

+60
-4
lines changed

‎src/backend/rewrite/rewriteHandler.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ rewriteRuleAction(Query *parsetree,
353353
Query*sub_action;
354354
Query**sub_action_ptr;
355355
acquireLocksOnSubLinks_contextcontext;
356+
ListCell*lc;
356357

357358
context.for_execute= true;
358359

@@ -391,6 +392,23 @@ rewriteRuleAction(Query *parsetree,
391392
ChangeVarNodes(rule_qual,
392393
PRS2_OLD_VARNO+rt_length,rt_index,0);
393394

395+
/*
396+
* Mark any subquery RTEs in the rule action as LATERAL if they contain
397+
* Vars referring to the current query level (references to NEW/OLD).
398+
* Those really are lateral references, but we've historically not
399+
* required users to mark such subqueries with LATERAL explicitly. But
400+
* the planner will complain if such Vars exist in a non-LATERAL subquery,
401+
* so we have to fix things up here.
402+
*/
403+
foreach(lc,sub_action->rtable)
404+
{
405+
RangeTblEntry*rte= (RangeTblEntry*)lfirst(lc);
406+
407+
if (rte->rtekind==RTE_SUBQUERY&& !rte->lateral&&
408+
contain_vars_of_level((Node*)rte->subquery,1))
409+
rte->lateral= true;
410+
}
411+
394412
/*
395413
* Generate expanded rtable consisting of main parsetree's rtable plus
396414
* rule action's rtable; this becomes the complete rtable for the rule
@@ -439,8 +457,6 @@ rewriteRuleAction(Query *parsetree,
439457
*/
440458
if (parsetree->hasSubLinks&& !sub_action->hasSubLinks)
441459
{
442-
ListCell*lc;
443-
444460
foreach(lc,parsetree->rtable)
445461
{
446462
RangeTblEntry*rte= (RangeTblEntry*)lfirst(lc);
@@ -538,8 +554,6 @@ rewriteRuleAction(Query *parsetree,
538554
*/
539555
if (parsetree->cteList!=NIL&&sub_action->commandType!=CMD_UTILITY)
540556
{
541-
ListCell*lc;
542-
543557
/*
544558
* Annoying implementation restriction: because CTEs are identified by
545559
* name within a cteList, we can't merge a CTE from the original query

‎src/test/regress/expected/rules.out

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3083,6 +3083,31 @@ Rules:
30833083

30843084
drop table rule_t1, rule_dest;
30853085
--
3086+
-- Test implicit LATERAL references to old/new in rules
3087+
--
3088+
CREATE TABLE rule_t1(a int, b text DEFAULT 'xxx', c int);
3089+
CREATE VIEW rule_v1 AS SELECT * FROM rule_t1;
3090+
CREATE RULE v1_ins AS ON INSERT TO rule_v1
3091+
DO ALSO INSERT INTO rule_t1
3092+
SELECT * FROM (SELECT a + 10 FROM rule_t1 WHERE a = NEW.a) tt;
3093+
CREATE RULE v1_upd AS ON UPDATE TO rule_v1
3094+
DO ALSO UPDATE rule_t1 t
3095+
SET c = tt.a * 10
3096+
FROM (SELECT a FROM rule_t1 WHERE a = OLD.a) tt WHERE t.a = tt.a;
3097+
INSERT INTO rule_v1 VALUES (1, 'a'), (2, 'b');
3098+
UPDATE rule_v1 SET b = upper(b);
3099+
SELECT * FROM rule_t1;
3100+
a | b | c
3101+
----+-----+-----
3102+
1 | A | 10
3103+
2 | B | 20
3104+
11 | XXX | 110
3105+
12 | XXX | 120
3106+
(4 rows)
3107+
3108+
DROP TABLE rule_t1 CASCADE;
3109+
NOTICE: drop cascades to view rule_v1
3110+
--
30863111
-- check alter rename rule
30873112
--
30883113
CREATE TABLE rule_t1 (a INT);

‎src/test/regress/sql/rules.sql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,6 +1046,23 @@ create rule rr as on update to rule_t1 do instead UPDATE rule_dest trgt
10461046
\d+ rule_t1
10471047
droptable rule_t1, rule_dest;
10481048

1049+
--
1050+
-- Test implicit LATERAL references to old/new in rules
1051+
--
1052+
CREATETABLErule_t1(aint, btext DEFAULT'xxx', cint);
1053+
CREATEVIEWrule_v1ASSELECT*FROM rule_t1;
1054+
CREATERULEv1_insASON INSERT TO rule_v1
1055+
DO ALSOINSERT INTO rule_t1
1056+
SELECT*FROM (SELECT a+10FROM rule_t1WHERE a=NEW.a) tt;
1057+
CREATERULEv1_updASONUPDATE TO rule_v1
1058+
DO ALSOUPDATE rule_t1 t
1059+
SET c=tt.a*10
1060+
FROM (SELECT aFROM rule_t1WHERE a=OLD.a) ttWHEREt.a=tt.a;
1061+
INSERT INTO rule_v1VALUES (1,'a'), (2,'b');
1062+
UPDATE rule_v1SET b=upper(b);
1063+
SELECT*FROM rule_t1;
1064+
DROPTABLE rule_t1 CASCADE;
1065+
10491066
--
10501067
-- check alter rename rule
10511068
--

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp