* Lastly, if this is not the primary (canSetTag) ModifyTable node, add it
* to estate->es_auxmodifytables so that it will be run to completion by
* ExecPostprocessPlan. (It'd actually work fine to add the primary
- * ModifyTable node too, but there's no need.)
+ * ModifyTable node too, but there's no need.) Note the use of lcons
+ * not lappend: we need later-initialized ModifyTable nodes to be shut
+ * down before earlier ones. This ensures that we don't throw away
+ * RETURNING rows that need to be seen by a later CTE subplan.
*/
if (!mtstate->canSetTag)
- estate->es_auxmodifytables = lappend(estate->es_auxmodifytables,
- mtstate);
+ estate->es_auxmodifytables = lcons(mtstate,
+ estate->es_auxmodifytables);
return mtstate;
}
-400
(22 rows)
+-- check that run to completion happens in proper ordering
+TRUNCATE TABLE y;
+INSERT INTO y SELECT generate_series(1, 3);
+CREATE TEMPORARY TABLE yy (a INTEGER);
+WITH RECURSIVE t1 AS (
+ INSERT INTO y SELECT * FROM y RETURNING *
+), t2 AS (
+ INSERT INTO yy SELECT * FROM t1 RETURNING *
+)
+SELECT 1;
+ ?column?
+----------
+ 1
+(1 row)
+
+SELECT * FROM y;
+ a
+---
+ 1
+ 2
+ 3
+ 1
+ 2
+ 3
+(6 rows)
+
+SELECT * FROM yy;
+ a
+---
+ 1
+ 2
+ 3
+(3 rows)
+
+WITH RECURSIVE t1 AS (
+ INSERT INTO yy SELECT * FROM t2 RETURNING *
+), t2 AS (
+ INSERT INTO y SELECT * FROM y RETURNING *
+)
+SELECT 1;
+ ?column?
+----------
+ 1
+(1 row)
+
+SELECT * FROM y;
+ a
+---
+ 1
+ 2
+ 3
+ 1
+ 2
+ 3
+ 1
+ 2
+ 3
+ 1
+ 2
+ 3
+(12 rows)
+
+SELECT * FROM yy;
+ a
+---
+ 1
+ 2
+ 3
+ 1
+ 2
+ 3
+ 1
+ 2
+ 3
+(9 rows)
+
-- triggers
TRUNCATE TABLE y;
INSERT INTO y SELECT generate_series(1, 10);
SELECT * FROM y;
+-- check that run to completion happens in proper ordering
+
+TRUNCATE TABLE y;
+INSERT INTO y SELECT generate_series(1, 3);
+CREATE TEMPORARY TABLE yy (a INTEGER);
+
+WITH RECURSIVE t1 AS (
+ INSERT INTO y SELECT * FROM y RETURNING *
+), t2 AS (
+ INSERT INTO yy SELECT * FROM t1 RETURNING *
+)
+SELECT 1;
+
+SELECT * FROM y;
+SELECT * FROM yy;
+
+WITH RECURSIVE t1 AS (
+ INSERT INTO yy SELECT * FROM t2 RETURNING *
+), t2 AS (
+ INSERT INTO y SELECT * FROM y RETURNING *
+)
+SELECT 1;
+
+SELECT * FROM y;
+SELECT * FROM yy;
+
-- triggers
TRUNCATE TABLE y;