Do not translate dummy SpecialJoinInfos for child joins
authorAmit Langote
Mon, 25 Mar 2024 08:26:27 +0000 (17:26 +0900)
committerAmit Langote
Mon, 25 Mar 2024 09:06:47 +0000 (18:06 +0900)
This teaches build_child_join_sjinfo() to create the dummy
SpecialJoinInfos (those created for inner joins) directly for a given
child join, skipping the unnecessary overhead of translating the
parent joinrel's SpecialJoinInfo.

To that end, this commit moves the code to initialize the dummy
SpecialJoinInfos to a new function named init_dummy_sjinfo() and
changes the few existing sites that have this code and
build_child_join_sjinfo() to call this new function.

Author: Ashutosh Bapat 
Reviewed-by: Richard Guo
Reviewed-by: Amit Langote
Reviewed-by: Andrey Lepikhov
Reviewed-by: Tomas Vondra
Discussion: https://postgr.es/m/CAExHW5tHqEf3ASVqvFFcghYGPfpy7o3xnvhHwBGbJFMRH8KjNw@mail.gmail.com

src/backend/optimizer/path/costsize.c
src/backend/optimizer/path/joinrels.c
src/include/optimizer/paths.h

index 3c14c605a072022263e817b742126c3fa7c2ef01..ee23ed7835db672f16655638d1873f3c7d17b530 100644 (file)
@@ -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)
index c59aff28226aa860b4c0287b7d17847b7eeccd1e..17ef825a345e2a330dc45afb089d6fd8fd4b5a2f 100644 (file)
@@ -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);
index b16094613669f8024946c6ca0beb0162b636cc36..39ba4615483d9f0b213d65231c211b4be5af2499 100644 (file)
@@ -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