Skip to content

Commit 555494d

Browse files
committed
Fix placement of initPlans when forcibly materializing a subplan.
If we forcibly place a Material node atop a finished subplan, we need to move any initPlans attached to the subplan up to the Material node, in order to keep SS_finalize_plan() happy. I'd figured this out in commit 7b67a0a for the case of materializing a cursor plan, but out of an abundance of caution, I put the initPlan movement hack at the call site for that case, rather than inside materialize_finished_plan(). That was the wrong thing, because it turns out to also be necessary for the only other caller of materialize_finished_plan(), ie subselect.c. We lacked any test cases that exposed the mistake, but bug#14524 from Wei Congrui shows that it's possible to get an initPlan reference into the top tlist in that case too, and then SS_finalize_plan() complains. Hence, move the hack into materialize_finished_plan(). In HEAD, also relocate some recently-added tests in subselect.sql, which I'd unthinkingly dropped into the middle of a sequence of related tests. Report: https://postgr.es/m/20170202060020.1400.89021@wrigleys.postgresql.org
1 parent aa09b9d commit 555494d

File tree

4 files changed

+72
-48
lines changed

4 files changed

+72
-48
lines changed

src/backend/optimizer/plan/createplan.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5704,6 +5704,16 @@ materialize_finished_plan(Plan *subplan)
57045704

57055705
matplan = (Plan *) make_material(subplan);
57065706

5707+
/*
5708+
* XXX horrid kluge: if there are any initPlans attached to the subplan,
5709+
* move them up to the Material node, which is now effectively the top
5710+
* plan node in its query level. This prevents failure in
5711+
* SS_finalize_plan(), which see for comments. We don't bother adjusting
5712+
* the subplan's cost estimate for this.
5713+
*/
5714+
matplan->initPlan = subplan->initPlan;
5715+
subplan->initPlan = NIL;
5716+
57075717
/* Set cost data */
57085718
cost_material(&matpath,
57095719
subplan->startup_cost,

src/backend/optimizer/plan/planner.c

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -316,21 +316,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
316316
if (cursorOptions & CURSOR_OPT_SCROLL)
317317
{
318318
if (!ExecSupportsBackwardScan(top_plan))
319-
{
320-
Plan *sub_plan = top_plan;
321-
322-
top_plan = materialize_finished_plan(sub_plan);
323-
324-
/*
325-
* XXX horrid kluge: if there are any initPlans attached to the
326-
* formerly-top plan node, move them up to the Material node. This
327-
* prevents failure in SS_finalize_plan, which see for comments.
328-
* We don't bother adjusting the sub_plan's cost estimate for
329-
* this.
330-
*/
331-
top_plan->initPlan = sub_plan->initPlan;
332-
sub_plan->initPlan = NIL;
333-
}
319+
top_plan = materialize_finished_plan(top_plan);
334320
}
335321

336322
/*

src/test/regress/expected/subselect.out

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,31 @@ SELECT '' AS five, f1 AS "Correlated Field"
196196
| 3
197197
(5 rows)
198198

199+
--
200+
-- Use some existing tables in the regression test
201+
--
202+
SELECT '' AS eight, ss.f1 AS "Correlated Field", ss.f3 AS "Second Field"
203+
FROM SUBSELECT_TBL ss
204+
WHERE f1 NOT IN (SELECT f1+1 FROM INT4_TBL
205+
WHERE f1 != ss.f1 AND f1 < 2147483647);
206+
eight | Correlated Field | Second Field
207+
-------+------------------+--------------
208+
| 2 | 4
209+
| 3 | 5
210+
| 2 | 2
211+
| 3 | 3
212+
| 6 | 8
213+
| 8 |
214+
(6 rows)
215+
216+
select q1, float8(count(*)) / (select count(*) from int8_tbl)
217+
from int8_tbl group by q1 order by q1;
218+
q1 | ?column?
219+
------------------+----------
220+
123 | 0.4
221+
4567890123456789 | 0.6
222+
(2 rows)
223+
199224
-- Unspecified-type literals in output columns should resolve as text
200225
SELECT *, pg_typeof(f1) FROM
201226
(SELECT 'foo' AS f1 FROM generate_series(1,3)) ss ORDER BY 1;
@@ -227,30 +252,28 @@ explain verbose select '42' union all select 43;
227252
Output: 43
228253
(5 rows)
229254

230-
--
231-
-- Use some existing tables in the regression test
232-
--
233-
SELECT '' AS eight, ss.f1 AS "Correlated Field", ss.f3 AS "Second Field"
234-
FROM SUBSELECT_TBL ss
235-
WHERE f1 NOT IN (SELECT f1+1 FROM INT4_TBL
236-
WHERE f1 != ss.f1 AND f1 < 2147483647);
237-
eight | Correlated Field | Second Field
238-
-------+------------------+--------------
239-
| 2 | 4
240-
| 3 | 5
241-
| 2 | 2
242-
| 3 | 3
243-
| 6 | 8
244-
| 8 |
245-
(6 rows)
255+
-- check materialization of an initplan reference (bug #14524)
256+
explain (verbose, costs off)
257+
select 1 = all (select (select 1));
258+
QUERY PLAN
259+
-----------------------------------
260+
Result
261+
Output: (SubPlan 2)
262+
SubPlan 2
263+
-> Materialize
264+
Output: ($0)
265+
InitPlan 1 (returns $0)
266+
-> Result
267+
Output: 1
268+
-> Result
269+
Output: $0
270+
(10 rows)
246271

247-
select q1, float8(count(*)) / (select count(*) from int8_tbl)
248-
from int8_tbl group by q1 order by q1;
249-
q1 | ?column?
250-
------------------+----------
251-
123 | 0.4
252-
4567890123456789 | 0.6
253-
(2 rows)
272+
select 1 = all (select (select 1));
273+
?column?
274+
----------
275+
t
276+
(1 row)
254277

255278
--
256279
-- Check EXISTS simplification with LIMIT

src/test/regress/sql/subselect.sql

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,6 @@ SELECT '' AS five, f1 AS "Correlated Field"
8080
WHERE (f1, f2) IN (SELECT f2, CAST(f3 AS int4) FROM SUBSELECT_TBL
8181
WHERE f3 IS NOT NULL);
8282

83-
-- Unspecified-type literals in output columns should resolve as text
84-
85-
SELECT *, pg_typeof(f1) FROM
86-
(SELECT 'foo' AS f1 FROM generate_series(1,3)) ss ORDER BY 1;
87-
88-
-- ... unless there's context to suggest differently
89-
90-
explain verbose select '42' union all select '43';
91-
explain verbose select '42' union all select 43;
92-
9383
--
9484
-- Use some existing tables in the regression test
9585
--
@@ -102,6 +92,21 @@ SELECT '' AS eight, ss.f1 AS "Correlated Field", ss.f3 AS "Second Field"
10292
select q1, float8(count(*)) / (select count(*) from int8_tbl)
10393
from int8_tbl group by q1 order by q1;
10494

95+
-- Unspecified-type literals in output columns should resolve as text
96+
97+
SELECT *, pg_typeof(f1) FROM
98+
(SELECT 'foo' AS f1 FROM generate_series(1,3)) ss ORDER BY 1;
99+
100+
-- ... unless there's context to suggest differently
101+
102+
explain verbose select '42' union all select '43';
103+
explain verbose select '42' union all select 43;
104+
105+
-- check materialization of an initplan reference (bug #14524)
106+
explain (verbose, costs off)
107+
select 1 = all (select (select 1));
108+
select 1 = all (select (select 1));
109+
105110
--
106111
-- Check EXISTS simplification with LIMIT
107112
--

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy