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.
This commit is contained in:
parent
389af95155
commit
000128bc7f
|
@ -1147,11 +1147,14 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
|
||||||
* Lastly, if this is not the primary (canSetTag) ModifyTable node, add it
|
* 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
|
* to estate->es_auxmodifytables so that it will be run to completion by
|
||||||
* ExecPostprocessPlan. (It'd actually work fine to add the primary
|
* 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)
|
if (!mtstate->canSetTag)
|
||||||
estate->es_auxmodifytables = lappend(estate->es_auxmodifytables,
|
estate->es_auxmodifytables = lcons(mtstate,
|
||||||
mtstate);
|
estate->es_auxmodifytables);
|
||||||
|
|
||||||
return mtstate;
|
return mtstate;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1543,6 +1543,82 @@ SELECT * FROM y;
|
||||||
-400
|
-400
|
||||||
(22 rows)
|
(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
|
-- triggers
|
||||||
TRUNCATE TABLE y;
|
TRUNCATE TABLE y;
|
||||||
INSERT INTO y SELECT generate_series(1, 10);
|
INSERT INTO y SELECT generate_series(1, 10);
|
||||||
|
|
|
@ -641,6 +641,32 @@ SELECT * FROM t LIMIT 10;
|
||||||
|
|
||||||
SELECT * FROM y;
|
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
|
-- triggers
|
||||||
|
|
||||||
TRUNCATE TABLE y;
|
TRUNCATE TABLE y;
|
||||||
|
|
Loading…
Reference in New Issue