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

Commit0655c03

Browse files
committed
Centralize fixups for mismatched nullingrels in nestloop params.
It turns out that the fixes we applied in commitsbfd332band63e4f13 were not nearly enough to solve the problem.We'd focused narrowly on subquery RTEs with lateral references,but lateral references can occur in several other RTE kindssuch as function RTEs. Putting the same hack into half a dozencode paths seems quite unattractive. Hence, revert the code changes(but not the test cases) from those commits and instead solve itcentrally in identify_current_nestloop_params(), as Richard proposedoriginally. This is a bit annoying because it could mask erroneousnullingrels in nestloop params that are generated from non-LATERALparameterized paths; but on balance I don't see a better way.Maybe at some future time we'll be motivated to find a more rigorousapproach to nestloop params, but that's not happening for beta2.Richard Guo and Tom LaneDiscussion:https://postgr.es/m/CAMbWs48Jcw-NvnxT23WiHP324wG44DvzcH1j4hc0Zn+3sR9cfg@mail.gmail.com
1 parent5961141 commit0655c03

File tree

5 files changed

+69
-72
lines changed

5 files changed

+69
-72
lines changed

‎src/backend/optimizer/path/joinpath.c

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -430,24 +430,6 @@ have_unsafe_outer_join_ref(PlannerInfo *root,
430430
* These are returned in parallel lists in *param_exprs and *operators.
431431
* We also set *binary_mode to indicate whether strict binary matching is
432432
* required.
433-
*
434-
* A complication is that innerrel's lateral_vars may contain nullingrel
435-
* markers that need adjustment. This occurs if we have applied outer join
436-
* identity 3,
437-
*(A leftjoin B on (Pab)) leftjoin C on (Pb*c)
438-
*= A leftjoin (B leftjoin C on (Pbc)) on (Pab)
439-
* and C contains lateral references to B. It's still safe to apply the
440-
* identity, but the parser will have created those references in the form
441-
* "b*" (i.e., with varnullingrels listing the A/B join), while what we will
442-
* have available from the nestloop's outer side is just "b". We deal with
443-
* that here by stripping the nullingrels down to what is available from the
444-
* outer side according to outerrel->relids.
445-
* That fixes matters for the case of forward application of identity 3.
446-
* If the identity was applied in the reverse direction, we will have
447-
* innerrel's lateral_vars containing too few nullingrel bits rather than
448-
* too many. Currently, that causes no problems because setrefs.c applies
449-
* only a subset check to nullingrels in NestLoopParams, but we'd have to
450-
* work harder if we ever want to tighten that check.
451433
*/
452434
staticbool
453435
paraminfo_get_equal_hashops(PlannerInfo*root,ParamPathInfo*param_info,
@@ -551,25 +533,6 @@ paraminfo_get_equal_hashops(PlannerInfo *root, ParamPathInfo *param_info,
551533
return false;
552534
}
553535

554-
/* OK, but adjust its nullingrels before adding it to result */
555-
expr=copyObject(expr);
556-
if (IsA(expr,Var))
557-
{
558-
Var*var= (Var*)expr;
559-
560-
var->varnullingrels=bms_intersect(var->varnullingrels,
561-
outerrel->relids);
562-
}
563-
elseif (IsA(expr,PlaceHolderVar))
564-
{
565-
PlaceHolderVar*phv= (PlaceHolderVar*)expr;
566-
567-
phv->phnullingrels=bms_intersect(phv->phnullingrels,
568-
outerrel->relids);
569-
}
570-
else
571-
Assert(false);
572-
573536
*operators=lappend_oid(*operators,typentry->eq_opr);
574537
*param_exprs=lappend(*param_exprs,expr);
575538

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2289,11 +2289,11 @@ set_join_references(PlannerInfo *root, Join *join, int rtoffset)
22892289
* the outer-join level at which they are used, Vars seen in the
22902290
* NestLoopParam expression may have nullingrels that are just a
22912291
* subset of those in the Vars actually available from the outer
2292-
* side. Lateral references cancreate the same situation, as
2293-
*explained inthe comments forprocess_subquery_nestloop_params
2294-
*and paraminfo_get_equal_hashops. Notchecking this exactly is
2295-
*a bit grotty, but the work needed to make things match up
2296-
*perfectly seems well out of proportion tothe value.
2292+
* side.(Lateral references canalso cause this, as explained in
2293+
* the comments foridentify_current_nestloop_params.) Not
2294+
* checking this exactly is a bit grotty, but the work needed to
2295+
*make things match up perfectly seems well out of proportion to
2296+
* the value.
22972297
*/
22982298
nlp->paramval= (Var*)fix_upper_expr(root,
22992299
(Node*)nlp->paramval,

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

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -421,26 +421,8 @@ replace_nestloop_param_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
421421
* provide these values. This differs from replace_nestloop_param_var in
422422
* that the PARAM_EXEC slots to use have already been determined.
423423
*
424-
* An additional complication is that the subplan_params may contain
425-
* nullingrel markers that need adjustment. This occurs if we have applied
426-
* outer join identity 3,
427-
*(A leftjoin B on (Pab)) leftjoin C on (Pb*c)
428-
*= A leftjoin (B leftjoin C on (Pbc)) on (Pab)
429-
* and C is a subquery containing lateral references to B. It's still safe
430-
* to apply the identity, but the parser will have created those references
431-
* in the form "b*" (i.e., with varnullingrels listing the A/B join), while
432-
* what we will have available from the nestloop's outer side is just "b".
433-
* We deal with that here by stripping the nullingrels down to what is
434-
* available from the outer side according to root->curOuterRels.
435-
* That fixes matters for the case of forward application of identity 3.
436-
* If the identity was applied in the reverse direction, we will have
437-
* subplan_params containing too few nullingrel bits rather than too many.
438-
* Currently, that causes no problems because setrefs.c applies only a
439-
* subset check to nullingrels in NestLoopParams, but we'd have to work
440-
* harder if we ever want to tighten that check.
441-
*
442424
* Note that we also use root->curOuterRels as an implicit parameter for
443-
* sanity checks and nullingrel adjustments.
425+
* sanity checks.
444426
*/
445427
void
446428
process_subquery_nestloop_params(PlannerInfo*root,List*subplan_params)
@@ -467,19 +449,17 @@ process_subquery_nestloop_params(PlannerInfo *root, List *subplan_params)
467449
nlp= (NestLoopParam*)lfirst(lc2);
468450
if (nlp->paramno==pitem->paramId)
469451
{
452+
Assert(equal(var,nlp->paramval));
470453
/* Present, so nothing to do */
471454
break;
472455
}
473456
}
474457
if (lc2==NULL)
475458
{
476-
/* No, so add it after adjusting its nullingrels */
477-
var=copyObject(var);
478-
var->varnullingrels=bms_intersect(var->varnullingrels,
479-
root->curOuterRels);
459+
/* No, so add it */
480460
nlp=makeNode(NestLoopParam);
481461
nlp->paramno=pitem->paramId;
482-
nlp->paramval=var;
462+
nlp->paramval=copyObject(var);
483463
root->curOuterParams=lappend(root->curOuterParams,nlp);
484464
}
485465
}
@@ -500,19 +480,17 @@ process_subquery_nestloop_params(PlannerInfo *root, List *subplan_params)
500480
nlp= (NestLoopParam*)lfirst(lc2);
501481
if (nlp->paramno==pitem->paramId)
502482
{
483+
Assert(equal(phv,nlp->paramval));
503484
/* Present, so nothing to do */
504485
break;
505486
}
506487
}
507488
if (lc2==NULL)
508489
{
509-
/* No, so add it after adjusting its nullingrels */
510-
phv=copyObject(phv);
511-
phv->phnullingrels=bms_intersect(phv->phnullingrels,
512-
root->curOuterRels);
490+
/* No, so add it */
513491
nlp=makeNode(NestLoopParam);
514492
nlp->paramno=pitem->paramId;
515-
nlp->paramval= (Var*)phv;
493+
nlp->paramval= (Var*)copyObject(phv);
516494
root->curOuterParams=lappend(root->curOuterParams,nlp);
517495
}
518496
}
@@ -525,6 +503,28 @@ process_subquery_nestloop_params(PlannerInfo *root, List *subplan_params)
525503
* Identify any NestLoopParams that should be supplied by a NestLoop plan
526504
* node with the specified lefthand rels. Remove them from the active
527505
* root->curOuterParams list and return them as the result list.
506+
*
507+
* XXX Here we also hack up the returned Vars and PHVs so that they do not
508+
* contain nullingrel sets exceeding what is available from the outer side.
509+
* This is needed if we have applied outer join identity 3,
510+
*(A leftjoin B on (Pab)) leftjoin C on (Pb*c)
511+
*= A leftjoin (B leftjoin C on (Pbc)) on (Pab)
512+
* and C contains lateral references to B. It's still safe to apply the
513+
* identity, but the parser will have created those references in the form
514+
* "b*" (i.e., with varnullingrels listing the A/B join), while what we will
515+
* have available from the nestloop's outer side is just "b". We deal with
516+
* that here by stripping the nullingrels down to what is available from the
517+
* outer side according to leftrelids.
518+
*
519+
* That fixes matters for the case of forward application of identity 3.
520+
* If the identity was applied in the reverse direction, we will have
521+
* parameter Vars containing too few nullingrel bits rather than too many.
522+
* Currently, that causes no problems because setrefs.c applies only a
523+
* subset check to nullingrels in NestLoopParams, but we'd have to work
524+
* harder if we ever want to tighten that check. This is all pretty annoying
525+
* because it greatly weakens setrefs.c's cross-check, but the alternative
526+
* seems to be to generate multiple versions of each laterally-parameterized
527+
* subquery, which'd be unduly expensive.
528528
*/
529529
List*
530530
identify_current_nestloop_params(PlannerInfo*root,Relidsleftrelids)
@@ -539,22 +539,32 @@ identify_current_nestloop_params(PlannerInfo *root, Relids leftrelids)
539539

540540
/*
541541
* We are looking for Vars and PHVs that can be supplied by the
542-
* lefthand rels.
542+
* lefthand rels. When we find one, it's okay to modify it in-place
543+
* because all the routines above make a fresh copy to put into
544+
* curOuterParams.
543545
*/
544546
if (IsA(nlp->paramval,Var)&&
545547
bms_is_member(nlp->paramval->varno,leftrelids))
546548
{
549+
Var*var= (Var*)nlp->paramval;
550+
547551
root->curOuterParams=foreach_delete_current(root->curOuterParams,
548552
cell);
553+
var->varnullingrels=bms_intersect(var->varnullingrels,
554+
leftrelids);
549555
result=lappend(result,nlp);
550556
}
551557
elseif (IsA(nlp->paramval,PlaceHolderVar)&&
552558
bms_is_subset(find_placeholder_info(root,
553559
(PlaceHolderVar*)nlp->paramval)->ph_eval_at,
554560
leftrelids))
555561
{
562+
PlaceHolderVar*phv= (PlaceHolderVar*)nlp->paramval;
563+
556564
root->curOuterParams=foreach_delete_current(root->curOuterParams,
557565
cell);
566+
phv->phnullingrels=bms_intersect(phv->phnullingrels,
567+
leftrelids);
558568
result=lappend(result,nlp);
559569
}
560570
}

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2607,6 +2607,23 @@ select * from int8_tbl t1
26072607
Filter: (q1 = t2.q1)
26082608
(8 rows)
26092609

2610+
explain (costs off)
2611+
select * from int8_tbl t1
2612+
left join int8_tbl t2 on true
2613+
left join lateral
2614+
(select * from generate_series(t2.q1, 100)) s
2615+
on t2.q1 = 1;
2616+
QUERY PLAN
2617+
----------------------------------------------------
2618+
Nested Loop Left Join
2619+
-> Seq Scan on int8_tbl t1
2620+
-> Materialize
2621+
-> Nested Loop Left Join
2622+
Join Filter: (t2.q1 = 1)
2623+
-> Seq Scan on int8_tbl t2
2624+
-> Function Scan on generate_series
2625+
(7 rows)
2626+
26102627
explain (costs off)
26112628
select * from onek t1
26122629
left join onek t2 on true

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,13 @@ select * from int8_tbl t1
521521
(select*from int8_tbl t3wheret3.q1=t2.q1 offset0) s
522522
ont2.q1=1;
523523

524+
explain (costs off)
525+
select*from int8_tbl t1
526+
left join int8_tbl t2on true
527+
left join lateral
528+
(select*from generate_series(t2.q1,100)) s
529+
ont2.q1=1;
530+
524531
explain (costs off)
525532
select*from onek t1
526533
left join onek t2on true

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp