mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-12 18:34:36 +08:00
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
|
||||
* 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;
|
||||
}
|
||||
|
@ -1543,6 +1543,82 @@ SELECT * FROM y;
|
||||
-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);
|
||||
|
@ -641,6 +641,32 @@ SELECT * FROM t LIMIT 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;
|
||||
|
Loading…
Reference in New Issue
Block a user