Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 000128b

Browse files
committed
Fix order of shutdown processing when CTEs contain inter-references.
We need ExecutorEnd to run the ModifyTable nodes to completion in reverse order of initialization, not forward order. Easily done by constructing the list back-to-front.
1 parent 389af95 commit 000128b

File tree

3 files changed

+108
-3
lines changed

3 files changed

+108
-3
lines changed

src/backend/executor/nodeModifyTable.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,11 +1147,14 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
11471147
* Lastly, if this is not the primary (canSetTag) ModifyTable node, add it
11481148
* to estate->es_auxmodifytables so that it will be run to completion by
11491149
* ExecPostprocessPlan. (It'd actually work fine to add the primary
1150-
* ModifyTable node too, but there's no need.)
1150+
* ModifyTable node too, but there's no need.) Note the use of lcons
1151+
* not lappend: we need later-initialized ModifyTable nodes to be shut
1152+
* down before earlier ones. This ensures that we don't throw away
1153+
* RETURNING rows that need to be seen by a later CTE subplan.
11511154
*/
11521155
if (!mtstate->canSetTag)
1153-
estate->es_auxmodifytables = lappend(estate->es_auxmodifytables,
1154-
mtstate);
1156+
estate->es_auxmodifytables = lcons(mtstate,
1157+
estate->es_auxmodifytables);
11551158

11561159
return mtstate;
11571160
}

src/test/regress/expected/with.out

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,6 +1543,82 @@ SELECT * FROM y;
15431543
-400
15441544
(22 rows)
15451545

1546+
-- check that run to completion happens in proper ordering
1547+
TRUNCATE TABLE y;
1548+
INSERT INTO y SELECT generate_series(1, 3);
1549+
CREATE TEMPORARY TABLE yy (a INTEGER);
1550+
WITH RECURSIVE t1 AS (
1551+
INSERT INTO y SELECT * FROM y RETURNING *
1552+
), t2 AS (
1553+
INSERT INTO yy SELECT * FROM t1 RETURNING *
1554+
)
1555+
SELECT 1;
1556+
?column?
1557+
----------
1558+
1
1559+
(1 row)
1560+
1561+
SELECT * FROM y;
1562+
a
1563+
---
1564+
1
1565+
2
1566+
3
1567+
1
1568+
2
1569+
3
1570+
(6 rows)
1571+
1572+
SELECT * FROM yy;
1573+
a
1574+
---
1575+
1
1576+
2
1577+
3
1578+
(3 rows)
1579+
1580+
WITH RECURSIVE t1 AS (
1581+
INSERT INTO yy SELECT * FROM t2 RETURNING *
1582+
), t2 AS (
1583+
INSERT INTO y SELECT * FROM y RETURNING *
1584+
)
1585+
SELECT 1;
1586+
?column?
1587+
----------
1588+
1
1589+
(1 row)
1590+
1591+
SELECT * FROM y;
1592+
a
1593+
---
1594+
1
1595+
2
1596+
3
1597+
1
1598+
2
1599+
3
1600+
1
1601+
2
1602+
3
1603+
1
1604+
2
1605+
3
1606+
(12 rows)
1607+
1608+
SELECT * FROM yy;
1609+
a
1610+
---
1611+
1
1612+
2
1613+
3
1614+
1
1615+
2
1616+
3
1617+
1
1618+
2
1619+
3
1620+
(9 rows)
1621+
15461622
-- triggers
15471623
TRUNCATE TABLE y;
15481624
INSERT INTO y SELECT generate_series(1, 10);

src/test/regress/sql/with.sql

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,32 @@ SELECT * FROM t LIMIT 10;
641641

642642
SELECT * FROM y;
643643

644+
-- check that run to completion happens in proper ordering
645+
646+
TRUNCATE TABLE y;
647+
INSERT INTO y SELECT generate_series(1, 3);
648+
CREATE TEMPORARY TABLE yy (a INTEGER);
649+
650+
WITH RECURSIVE t1 AS (
651+
INSERT INTO y SELECT * FROM y RETURNING *
652+
), t2 AS (
653+
INSERT INTO yy SELECT * FROM t1 RETURNING *
654+
)
655+
SELECT 1;
656+
657+
SELECT * FROM y;
658+
SELECT * FROM yy;
659+
660+
WITH RECURSIVE t1 AS (
661+
INSERT INTO yy SELECT * FROM t2 RETURNING *
662+
), t2 AS (
663+
INSERT INTO y SELECT * FROM y RETURNING *
664+
)
665+
SELECT 1;
666+
667+
SELECT * FROM y;
668+
SELECT * FROM yy;
669+
644670
-- triggers
645671

646672
TRUNCATE TABLE y;

0 commit comments

Comments
 (0)