Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4da6439

Browse files
committed
Fix mark_placeholder_maybe_needed to handle LATERAL references.
If a PlaceHolderVar contains a pulled-up LATERAL reference, its minimumpossible evaluation level might be higher in the join tree than itsoriginal syntactic location. That in turn affects the ph_needed level forany contained PlaceHolderVars (that is, those PHVs had better propagate upthe join tree at least to the evaluation level of the outer PHV). We gotthis mostly right, but mark_placeholder_maybe_needed() failed to accountfor the effect, and in consequence could leave the inner PHVs withph_may_need less than what their ultimate ph_needed value will be. That'sbad because it could lead to failure to select a join order that will allowevaluation of the inner PHV at a valid location. Fix that, and add anAssert that checks that we don't ever set ph_needed to more thanph_may_need.
1 parent53fa0c6 commit4da6439

File tree

4 files changed

+67
-4
lines changed

4 files changed

+67
-4
lines changed

‎src/backend/optimizer/plan/initsplan.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,10 +199,13 @@ add_vars_to_targetlist(PlannerInfo *root, List *vars,
199199
/*
200200
* If we are creating PlaceHolderInfos, mark them with the correct
201201
* maybe-needed locations.Otherwise, it's too late to change
202-
* that.
202+
* that, so we'd better not have set ph_needed to more than
203+
* ph_may_need.
203204
*/
204205
if (create_new_ph)
205206
mark_placeholder_maybe_needed(root,phinfo,where_needed);
207+
else
208+
Assert(bms_is_subset(phinfo->ph_needed,phinfo->ph_may_need));
206209
}
207210
else
208211
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(node));

‎src/backend/optimizer/util/placeholder.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,8 @@ void
250250
mark_placeholder_maybe_needed(PlannerInfo*root,PlaceHolderInfo*phinfo,
251251
Relidsrelids)
252252
{
253+
Relidsest_eval_level;
254+
253255
/* Mark the PHV as possibly needed at the given syntactic level */
254256
phinfo->ph_may_need=bms_add_members(phinfo->ph_may_need,relids);
255257

@@ -258,11 +260,18 @@ mark_placeholder_maybe_needed(PlannerInfo *root, PlaceHolderInfo *phinfo,
258260
* lower-level PHVs. We need to get those into the PlaceHolderInfo list,
259261
* but they aren't going to be needed where the outer PHV is referenced.
260262
* Rather, they'll be needed where the outer PHV is evaluated. We can
261-
* estimate that (conservatively) as the syntactic location of the PHV's
262-
* expression.Recurse to take care of any such PHVs.
263+
* estimate that conservatively as the syntactic location of the PHV's
264+
* expression, but not less than the level of any Vars it contains.
265+
* (Normally the Vars would come from below the syntactic location anyway,
266+
* but this might not be true if the PHV contains any LATERAL references.)
263267
*/
268+
est_eval_level=bms_union(phinfo->ph_var->phrels,phinfo->ph_eval_at);
269+
270+
/* Now recurse to take care of any such PHVs */
264271
mark_placeholders_in_expr(root, (Node*)phinfo->ph_var->phexpr,
265-
phinfo->ph_var->phrels);
272+
est_eval_level);
273+
274+
bms_free(est_eval_level);
266275
}
267276

268277
/*

‎src/test/regress/expected/join.out

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3465,6 +3465,46 @@ select v.* from
34653465
-4567890123456789 |
34663466
(20 rows)
34673467

3468+
-- case requiring nested PlaceHolderVars
3469+
explain (verbose, costs off)
3470+
select * from
3471+
int8_tbl c left join (
3472+
int8_tbl a left join (select q1, coalesce(q2,42) as x from int8_tbl b) ss1
3473+
on a.q2 = ss1.q1
3474+
cross join
3475+
lateral (select q1, coalesce(ss1.x,q2) as y from int8_tbl d) ss2
3476+
) on c.q2 = ss2.q1,
3477+
lateral (select ss2.y) ss3;
3478+
QUERY PLAN
3479+
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3480+
Nested Loop
3481+
Output: c.q1, c.q2, a.q1, a.q2, b.q1, (COALESCE(b.q2, 42::bigint)), d.q1, (COALESCE((COALESCE(b.q2, 42::bigint)), d.q2)), ((COALESCE((COALESCE(b.q2, 42::bigint)), d.q2)))
3482+
-> Hash Right Join
3483+
Output: c.q1, c.q2, a.q1, a.q2, b.q1, d.q1, (COALESCE(b.q2, 42::bigint)), (COALESCE((COALESCE(b.q2, 42::bigint)), d.q2))
3484+
Hash Cond: (d.q1 = c.q2)
3485+
-> Nested Loop
3486+
Output: a.q1, a.q2, b.q1, d.q1, (COALESCE(b.q2, 42::bigint)), COALESCE((COALESCE(b.q2, 42::bigint)), d.q2)
3487+
-> Hash Left Join
3488+
Output: a.q1, a.q2, b.q1, (COALESCE(b.q2, 42::bigint))
3489+
Hash Cond: (a.q2 = b.q1)
3490+
-> Seq Scan on public.int8_tbl a
3491+
Output: a.q1, a.q2
3492+
-> Hash
3493+
Output: b.q1, (COALESCE(b.q2, 42::bigint))
3494+
-> Seq Scan on public.int8_tbl b
3495+
Output: b.q1, COALESCE(b.q2, 42::bigint)
3496+
-> Materialize
3497+
Output: d.q1, d.q2
3498+
-> Seq Scan on public.int8_tbl d
3499+
Output: d.q1, d.q2
3500+
-> Hash
3501+
Output: c.q1, c.q2
3502+
-> Seq Scan on public.int8_tbl c
3503+
Output: c.q1, c.q2
3504+
-> Result
3505+
Output: (COALESCE((COALESCE(b.q2, 42::bigint)), d.q2))
3506+
(26 rows)
3507+
34683508
-- test some error cases where LATERAL should have been used but wasn't
34693509
select f1,g from int4_tbl a, generate_series(0, f1) g;
34703510
ERROR: column "f1" does not exist

‎src/test/regress/sql/join.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,17 @@ select v.* from
942942
left join int4_tbl zonz.f1=x.q2,
943943
lateral (selectx.q1,y.q1from dualunion allselectx.q2,y.q2from dual) v(vx,vy);
944944

945+
-- case requiring nested PlaceHolderVars
946+
explain (verbose, costs off)
947+
select*from
948+
int8_tbl cleft join (
949+
int8_tbl aleft join (select q1, coalesce(q2,42)as xfrom int8_tbl b) ss1
950+
ona.q2=ss1.q1
951+
cross join
952+
lateral (select q1, coalesce(ss1.x,q2)as yfrom int8_tbl d) ss2
953+
)onc.q2=ss2.q1,
954+
lateral (selectss2.y) ss3;
955+
945956
-- test some error cases where LATERAL should have been used but wasn't
946957
select f1,gfrom int4_tbl a, generate_series(0, f1) g;
947958
select f1,gfrom int4_tbl a, generate_series(0,a.f1) g;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp