]> granicus.if.org Git - postgresql/commitdiff
Fix handling of init_plans list in inheritance_planner().
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 29 Jan 2012 01:24:42 +0000 (20:24 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 29 Jan 2012 01:24:42 +0000 (20:24 -0500)
Formerly we passed an empty list to each per-child-table invocation of
grouping_planner, and then merged the results into the global list.
However, that fails if there's a CTE attached to the statement, because
create_ctescan_plan uses the list to find the plan referenced by a CTE
reference; so it was unable to find any CTEs attached to the outer UPDATE
or DELETE.  But there's no real reason not to use the same list throughout
the process, and doing so is simpler and faster anyway.

Per report from Josh Berkus of "could not find plan for CTE" failures.
Back-patch to 9.1 where we added support for WITH attached to UPDATE or
DELETE.  Add some regression test cases, too.

src/backend/optimizer/plan/planner.c
src/test/regress/expected/with.out
src/test/regress/sql/with.sql

index 921262948bb8cc5b42c32170c447a0d8008bea34..2e8ea5afad78ec28ae85908cff430edab93bd9b8 100644 (file)
@@ -835,8 +835,6 @@ inheritance_planner(PlannerInfo *root)
                Assert(subroot.join_info_list == NIL);
                /* and we haven't created PlaceHolderInfos, either */
                Assert(subroot.placeholder_list == NIL);
-               /* build a separate list of initplans for each child */
-               subroot.init_plans = NIL;
                /* hack to mark target relation as an inheritance partition */
                subroot.hasInheritedTarget = true;
 
@@ -883,7 +881,7 @@ inheritance_planner(PlannerInfo *root)
                save_rel_array = subroot.simple_rel_array;
 
                /* Make sure any initplans from this rel get into the outer list */
-               root->init_plans = list_concat(root->init_plans, subroot.init_plans);
+               root->init_plans = subroot.init_plans;
 
                /* Build list of target-relation RT indexes */
                resultRelations = lappend_int(resultRelations, appinfo->child_relid);
index c4b045604b604043fcab40dcb172ea7cb7d88c25..a58739b68ef5921d6fbf310d2aafa251cfdd504f 100644 (file)
@@ -1800,6 +1800,62 @@ SELECT * FROM y;
 
 DROP TRIGGER y_trig ON y;
 DROP FUNCTION y_trigger();
+-- WITH attached to inherited UPDATE or DELETE
+CREATE TEMP TABLE parent ( id int, val text );
+CREATE TEMP TABLE child1 ( ) INHERITS ( parent );
+CREATE TEMP TABLE child2 ( ) INHERITS ( parent );
+INSERT INTO parent VALUES ( 1, 'p1' );
+INSERT INTO child1 VALUES ( 11, 'c11' ),( 12, 'c12' );
+INSERT INTO child2 VALUES ( 23, 'c21' ),( 24, 'c22' );
+WITH rcte AS ( SELECT sum(id) AS totalid FROM parent )
+UPDATE parent SET id = id + totalid FROM rcte;
+SELECT * FROM parent;
+ id | val 
+----+-----
+ 72 | p1
+ 82 | c11
+ 83 | c12
+ 94 | c21
+ 95 | c22
+(5 rows)
+
+WITH wcte AS ( INSERT INTO child1 VALUES ( 42, 'new' ) RETURNING id AS newid )
+UPDATE parent SET id = id + newid FROM wcte;
+SELECT * FROM parent;
+ id  | val 
+-----+-----
+ 114 | p1
+  42 | new
+ 124 | c11
+ 125 | c12
+ 136 | c21
+ 137 | c22
+(6 rows)
+
+WITH rcte AS ( SELECT max(id) AS maxid FROM parent )
+DELETE FROM parent USING rcte WHERE id = maxid;
+SELECT * FROM parent;
+ id  | val 
+-----+-----
+ 114 | p1
+  42 | new
+ 124 | c11
+ 125 | c12
+ 136 | c21
+(5 rows)
+
+WITH wcte AS ( INSERT INTO child2 VALUES ( 42, 'new2' ) RETURNING id AS newid )
+DELETE FROM parent USING wcte WHERE id = newid;
+SELECT * FROM parent;
+ id  | val  
+-----+------
+ 114 | p1
+ 124 | c11
+ 125 | c12
+ 136 | c21
+  42 | new2
+(5 rows)
+
 -- error cases
 -- data-modifying WITH tries to use its own output
 WITH RECURSIVE t AS (
index bc340e4543f8196df3dc19bf819f01eb87d4e8e6..1479422c9c66cbcdfb38b18f1f1f144238580baa 100644 (file)
@@ -761,6 +761,36 @@ SELECT * FROM y;
 DROP TRIGGER y_trig ON y;
 DROP FUNCTION y_trigger();
 
+-- WITH attached to inherited UPDATE or DELETE
+
+CREATE TEMP TABLE parent ( id int, val text );
+CREATE TEMP TABLE child1 ( ) INHERITS ( parent );
+CREATE TEMP TABLE child2 ( ) INHERITS ( parent );
+
+INSERT INTO parent VALUES ( 1, 'p1' );
+INSERT INTO child1 VALUES ( 11, 'c11' ),( 12, 'c12' );
+INSERT INTO child2 VALUES ( 23, 'c21' ),( 24, 'c22' );
+
+WITH rcte AS ( SELECT sum(id) AS totalid FROM parent )
+UPDATE parent SET id = id + totalid FROM rcte;
+
+SELECT * FROM parent;
+
+WITH wcte AS ( INSERT INTO child1 VALUES ( 42, 'new' ) RETURNING id AS newid )
+UPDATE parent SET id = id + newid FROM wcte;
+
+SELECT * FROM parent;
+
+WITH rcte AS ( SELECT max(id) AS maxid FROM parent )
+DELETE FROM parent USING rcte WHERE id = maxid;
+
+SELECT * FROM parent;
+
+WITH wcte AS ( INSERT INTO child2 VALUES ( 42, 'new2' ) RETURNING id AS newid )
+DELETE FROM parent USING wcte WHERE id = newid;
+
+SELECT * FROM parent;
+
 -- error cases
 
 -- data-modifying WITH tries to use its own output