diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 3c14c605a0..ee23ed7835 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -5050,23 +5050,7 @@ compute_semi_anti_join_factors(PlannerInfo *root, /* * Also get the normal inner-join selectivity of the join clauses. */ - norm_sjinfo.type = T_SpecialJoinInfo; - norm_sjinfo.min_lefthand = outerrel->relids; - norm_sjinfo.min_righthand = innerrel->relids; - norm_sjinfo.syn_lefthand = outerrel->relids; - norm_sjinfo.syn_righthand = innerrel->relids; - norm_sjinfo.jointype = JOIN_INNER; - norm_sjinfo.ojrelid = 0; - norm_sjinfo.commute_above_l = NULL; - norm_sjinfo.commute_above_r = NULL; - norm_sjinfo.commute_below_l = NULL; - norm_sjinfo.commute_below_r = NULL; - /* we don't bother trying to make the remaining fields valid */ - norm_sjinfo.lhs_strict = false; - norm_sjinfo.semi_can_btree = false; - norm_sjinfo.semi_can_hash = false; - norm_sjinfo.semi_operators = NIL; - norm_sjinfo.semi_rhs_exprs = NIL; + init_dummy_sjinfo(&norm_sjinfo, outerrel->relids, innerrel->relids); nselec = clauselist_selectivity(root, joinquals, @@ -5219,23 +5203,8 @@ approx_tuple_count(PlannerInfo *root, JoinPath *path, List *quals) /* * Make up a SpecialJoinInfo for JOIN_INNER semantics. */ - sjinfo.type = T_SpecialJoinInfo; - sjinfo.min_lefthand = path->outerjoinpath->parent->relids; - sjinfo.min_righthand = path->innerjoinpath->parent->relids; - sjinfo.syn_lefthand = path->outerjoinpath->parent->relids; - sjinfo.syn_righthand = path->innerjoinpath->parent->relids; - sjinfo.jointype = JOIN_INNER; - sjinfo.ojrelid = 0; - sjinfo.commute_above_l = NULL; - sjinfo.commute_above_r = NULL; - sjinfo.commute_below_l = NULL; - sjinfo.commute_below_r = NULL; - /* we don't bother trying to make the remaining fields valid */ - sjinfo.lhs_strict = false; - sjinfo.semi_can_btree = false; - sjinfo.semi_can_hash = false; - sjinfo.semi_operators = NIL; - sjinfo.semi_rhs_exprs = NIL; + init_dummy_sjinfo(&sjinfo, path->outerjoinpath->parent->relids, + path->innerjoinpath->parent->relids); /* Get the approximate selectivity */ foreach(l, quals) diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index c59aff2822..17ef825a34 100644 --- a/src/backend/optimizer/path/joinrels.c +++ b/src/backend/optimizer/path/joinrels.c @@ -654,6 +654,38 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, return true; } +/* + * init_dummy_sjinfo + * Populate the given SpecialJoinInfo for a plain inner join between rel1 + * and rel2 + * + * Normally, an inner join does not have a SpecialJoinInfo node associated with + * it. But some functions involved in join planning require one containing at + * least the information of which relations are being joined. So we initialize + * that information here. + */ +void +init_dummy_sjinfo(SpecialJoinInfo *sjinfo, Relids left_relids, + Relids right_relids) +{ + sjinfo->type = T_SpecialJoinInfo; + sjinfo->min_lefthand = left_relids; + sjinfo->min_righthand = right_relids; + sjinfo->syn_lefthand = left_relids; + sjinfo->syn_righthand = right_relids; + sjinfo->jointype = JOIN_INNER; + sjinfo->ojrelid = 0; + sjinfo->commute_above_l = NULL; + sjinfo->commute_above_r = NULL; + sjinfo->commute_below_l = NULL; + sjinfo->commute_below_r = NULL; + /* we don't bother trying to make the remaining fields valid */ + sjinfo->lhs_strict = false; + sjinfo->semi_can_btree = false; + sjinfo->semi_can_hash = false; + sjinfo->semi_operators = NIL; + sjinfo->semi_rhs_exprs = NIL; +} /* * make_join_rel @@ -717,23 +749,7 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2) if (sjinfo == NULL) { sjinfo = &sjinfo_data; - sjinfo->type = T_SpecialJoinInfo; - sjinfo->min_lefthand = rel1->relids; - sjinfo->min_righthand = rel2->relids; - sjinfo->syn_lefthand = rel1->relids; - sjinfo->syn_righthand = rel2->relids; - sjinfo->jointype = JOIN_INNER; - sjinfo->ojrelid = 0; - sjinfo->commute_above_l = NULL; - sjinfo->commute_above_r = NULL; - sjinfo->commute_below_l = NULL; - sjinfo->commute_below_r = NULL; - /* we don't bother trying to make the remaining fields valid */ - sjinfo->lhs_strict = false; - sjinfo->semi_can_btree = false; - sjinfo->semi_can_hash = false; - sjinfo->semi_operators = NIL; - sjinfo->semi_rhs_exprs = NIL; + init_dummy_sjinfo(sjinfo, rel1->relids, rel2->relids); } /* @@ -1682,6 +1698,14 @@ build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo, AppendRelInfo **right_appinfos; int right_nappinfos; + /* Dummy SpecialJoinInfos can be created without any translation. */ + if (parent_sjinfo->jointype == JOIN_INNER) + { + Assert(parent_sjinfo->ojrelid == 0); + init_dummy_sjinfo(sjinfo, left_relids, right_relids); + return sjinfo; + } + memcpy(sjinfo, parent_sjinfo, sizeof(SpecialJoinInfo)); left_appinfos = find_appinfos_by_relids(root, left_relids, &left_nappinfos); diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h index b160946136..39ba461548 100644 --- a/src/include/optimizer/paths.h +++ b/src/include/optimizer/paths.h @@ -112,6 +112,8 @@ extern bool have_join_order_restriction(PlannerInfo *root, extern bool have_dangerous_phv(PlannerInfo *root, Relids outer_relids, Relids inner_params); extern void mark_dummy_rel(RelOptInfo *rel); +extern void init_dummy_sjinfo(SpecialJoinInfo *sjinfo, Relids left_relids, + Relids right_relids); /* * equivclass.c