Skip to content

Commit 4fcf484

Browse files
committed
Get rid of the planner's LateralJoinInfo data structure.
I originally modeled this data structure on SpecialJoinInfo, but after commit acfcd45 that looks like a pretty poor decision. All we really need is relid sets identifying laterally-referenced rels; and most of the time, what we want to know about includes indirect lateral references, a case the LateralJoinInfo data was unsuited to compute with any efficiency. The previous commit redefined RelOptInfo.lateral_relids as the transitive closure of lateral references, so that it easily supports checking indirect references. For the places where we really do want just direct references, add a new RelOptInfo field direct_lateral_relids, which is easily set up as a copy of lateral_relids before we perform the transitive closure calculation. Then we can just drop lateral_info_list and LateralJoinInfo and the supporting code. This makes the planner's handling of lateral references noticeably more efficient, and shorter too. Such a change can't be back-patched into stable branches for fear of breaking extensions that might be looking at the planner's data structures; but it seems not too late to push it into 9.5, so I've done so.
1 parent ed8bec9 commit 4fcf484

File tree

17 files changed

+100
-289
lines changed

17 files changed

+100
-289
lines changed

src/backend/nodes/copyfuncs.c

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2066,20 +2066,6 @@ _copySpecialJoinInfo(const SpecialJoinInfo *from)
20662066
return newnode;
20672067
}
20682068

2069-
/*
2070-
* _copyLateralJoinInfo
2071-
*/
2072-
static LateralJoinInfo *
2073-
_copyLateralJoinInfo(const LateralJoinInfo *from)
2074-
{
2075-
LateralJoinInfo *newnode = makeNode(LateralJoinInfo);
2076-
2077-
COPY_BITMAPSET_FIELD(lateral_lhs);
2078-
COPY_BITMAPSET_FIELD(lateral_rhs);
2079-
2080-
return newnode;
2081-
}
2082-
20832069
/*
20842070
* _copyAppendRelInfo
20852071
*/
@@ -4519,9 +4505,6 @@ copyObject(const void *from)
45194505
case T_SpecialJoinInfo:
45204506
retval = _copySpecialJoinInfo(from);
45214507
break;
4522-
case T_LateralJoinInfo:
4523-
retval = _copyLateralJoinInfo(from);
4524-
break;
45254508
case T_AppendRelInfo:
45264509
retval = _copyAppendRelInfo(from);
45274510
break;

src/backend/nodes/equalfuncs.c

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -845,15 +845,6 @@ _equalSpecialJoinInfo(const SpecialJoinInfo *a, const SpecialJoinInfo *b)
845845
return true;
846846
}
847847

848-
static bool
849-
_equalLateralJoinInfo(const LateralJoinInfo *a, const LateralJoinInfo *b)
850-
{
851-
COMPARE_BITMAPSET_FIELD(lateral_lhs);
852-
COMPARE_BITMAPSET_FIELD(lateral_rhs);
853-
854-
return true;
855-
}
856-
857848
static bool
858849
_equalAppendRelInfo(const AppendRelInfo *a, const AppendRelInfo *b)
859850
{
@@ -2860,9 +2851,6 @@ equal(const void *a, const void *b)
28602851
case T_SpecialJoinInfo:
28612852
retval = _equalSpecialJoinInfo(a, b);
28622853
break;
2863-
case T_LateralJoinInfo:
2864-
retval = _equalLateralJoinInfo(a, b);
2865-
break;
28662854
case T_AppendRelInfo:
28672855
retval = _equalAppendRelInfo(a, b);
28682856
break;

src/backend/nodes/outfuncs.c

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1847,7 +1847,6 @@ _outPlannerInfo(StringInfo str, const PlannerInfo *node)
18471847
WRITE_NODE_FIELD(right_join_clauses);
18481848
WRITE_NODE_FIELD(full_join_clauses);
18491849
WRITE_NODE_FIELD(join_info_list);
1850-
WRITE_NODE_FIELD(lateral_info_list);
18511850
WRITE_NODE_FIELD(append_rel_list);
18521851
WRITE_NODE_FIELD(rowMarks);
18531852
WRITE_NODE_FIELD(placeholder_list);
@@ -1892,6 +1891,7 @@ _outRelOptInfo(StringInfo str, const RelOptInfo *node)
18921891
WRITE_NODE_FIELD(cheapest_total_path);
18931892
WRITE_NODE_FIELD(cheapest_unique_path);
18941893
WRITE_NODE_FIELD(cheapest_parameterized_paths);
1894+
WRITE_BITMAPSET_FIELD(direct_lateral_relids);
18951895
WRITE_BITMAPSET_FIELD(lateral_relids);
18961896
WRITE_UINT_FIELD(relid);
18971897
WRITE_OID_FIELD(reltablespace);
@@ -2056,15 +2056,6 @@ _outSpecialJoinInfo(StringInfo str, const SpecialJoinInfo *node)
20562056
WRITE_NODE_FIELD(semi_rhs_exprs);
20572057
}
20582058

2059-
static void
2060-
_outLateralJoinInfo(StringInfo str, const LateralJoinInfo *node)
2061-
{
2062-
WRITE_NODE_TYPE("LATERALJOININFO");
2063-
2064-
WRITE_BITMAPSET_FIELD(lateral_lhs);
2065-
WRITE_BITMAPSET_FIELD(lateral_rhs);
2066-
}
2067-
20682059
static void
20692060
_outAppendRelInfo(StringInfo str, const AppendRelInfo *node)
20702061
{
@@ -3355,9 +3346,6 @@ _outNode(StringInfo str, const void *obj)
33553346
case T_SpecialJoinInfo:
33563347
_outSpecialJoinInfo(str, obj);
33573348
break;
3358-
case T_LateralJoinInfo:
3359-
_outLateralJoinInfo(str, obj);
3360-
break;
33613349
case T_AppendRelInfo:
33623350
_outAppendRelInfo(str, obj);
33633351
break;

src/backend/optimizer/path/joinrels.c

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ join_search_one_level(PlannerInfo *root, int level)
231231
*/
232232
if (joinrels[level] == NIL &&
233233
root->join_info_list == NIL &&
234-
root->lateral_info_list == NIL)
234+
!root->hasLateralRTEs)
235235
elog(ERROR, "failed to build any %d-way joins", level);
236236
}
237237
}
@@ -559,15 +559,7 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
559559
match_sjinfo->jointype == JOIN_FULL))
560560
return false; /* not implementable as nestloop */
561561
/* check there is a direct reference from rel2 to rel1 */
562-
foreach(l, root->lateral_info_list)
563-
{
564-
LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(l);
565-
566-
if (bms_is_subset(ljinfo->lateral_rhs, rel2->relids) &&
567-
bms_is_subset(ljinfo->lateral_lhs, rel1->relids))
568-
break;
569-
}
570-
if (l == NULL)
562+
if (!bms_overlap(rel1->relids, rel2->direct_lateral_relids))
571563
return false; /* only indirect refs, so reject */
572564
/* check we won't have a dangerous PHV */
573565
if (have_dangerous_phv(root, rel1->relids, rel2->lateral_relids))
@@ -582,15 +574,7 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
582574
match_sjinfo->jointype == JOIN_FULL))
583575
return false; /* not implementable as nestloop */
584576
/* check there is a direct reference from rel1 to rel2 */
585-
foreach(l, root->lateral_info_list)
586-
{
587-
LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(l);
588-
589-
if (bms_is_subset(ljinfo->lateral_rhs, rel1->relids) &&
590-
bms_is_subset(ljinfo->lateral_lhs, rel2->relids))
591-
break;
592-
}
593-
if (l == NULL)
577+
if (!bms_overlap(rel2->relids, rel1->direct_lateral_relids))
594578
return false; /* only indirect refs, so reject */
595579
/* check we won't have a dangerous PHV */
596580
if (have_dangerous_phv(root, rel2->relids, rel1->lateral_relids))
@@ -922,17 +906,9 @@ have_join_order_restriction(PlannerInfo *root,
922906
* If either side has a direct lateral reference to the other, attempt the
923907
* join regardless of outer-join considerations.
924908
*/
925-
foreach(l, root->lateral_info_list)
926-
{
927-
LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(l);
928-
929-
if (bms_is_subset(ljinfo->lateral_rhs, rel2->relids) &&
930-
bms_overlap(ljinfo->lateral_lhs, rel1->relids))
931-
return true;
932-
if (bms_is_subset(ljinfo->lateral_rhs, rel1->relids) &&
933-
bms_overlap(ljinfo->lateral_lhs, rel2->relids))
934-
return true;
935-
}
909+
if (bms_overlap(rel1->relids, rel2->direct_lateral_relids) ||
910+
bms_overlap(rel2->relids, rel1->direct_lateral_relids))
911+
return true;
936912

937913
/*
938914
* Likewise, if both rels are needed to compute some PlaceHolderVar,

src/backend/optimizer/plan/analyzejoins.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -439,9 +439,6 @@ remove_rel_from_query(PlannerInfo *root, int relid, Relids joinrelids)
439439
sjinfo->syn_righthand = bms_del_member(sjinfo->syn_righthand, relid);
440440
}
441441

442-
/* There shouldn't be any LATERAL info to translate, as yet */
443-
Assert(root->lateral_info_list == NIL);
444-
445442
/*
446443
* Likewise remove references from PlaceHolderVar data structures,
447444
* removing any no-longer-needed placeholders entirely.

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