LCOV - code coverage report
Current view: top level - src/backend/optimizer/path - joinrels.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 95.5 % 801 765
Test Date: 2026-01-26 10:56:24 Functions: 100.0 % 20 20
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 82.2 % 704 579

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * joinrels.c
       4                 :             :  *        Routines to determine which relations should be joined
       5                 :             :  *
       6                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :             :  *
       9                 :             :  *
      10                 :             :  * IDENTIFICATION
      11                 :             :  *        src/backend/optimizer/path/joinrels.c
      12                 :             :  *
      13                 :             :  *-------------------------------------------------------------------------
      14                 :             :  */
      15                 :             : #include "postgres.h"
      16                 :             : 
      17                 :             : #include "miscadmin.h"
      18                 :             : #include "optimizer/appendinfo.h"
      19                 :             : #include "optimizer/cost.h"
      20                 :             : #include "optimizer/joininfo.h"
      21                 :             : #include "optimizer/pathnode.h"
      22                 :             : #include "optimizer/paths.h"
      23                 :             : #include "optimizer/planner.h"
      24                 :             : #include "partitioning/partbounds.h"
      25                 :             : #include "utils/memutils.h"
      26                 :             : 
      27                 :             : 
      28                 :             : static void make_rels_by_clause_joins(PlannerInfo *root,
      29                 :             :                                                                           RelOptInfo *old_rel,
      30                 :             :                                                                           List *other_rels,
      31                 :             :                                                                           int first_rel_idx);
      32                 :             : static void make_rels_by_clauseless_joins(PlannerInfo *root,
      33                 :             :                                                                                   RelOptInfo *old_rel,
      34                 :             :                                                                                   List *other_rels);
      35                 :             : static bool has_join_restriction(PlannerInfo *root, RelOptInfo *rel);
      36                 :             : static bool has_legal_joinclause(PlannerInfo *root, RelOptInfo *rel);
      37                 :             : static bool restriction_is_constant_false(List *restrictlist,
      38                 :             :                                                                                   RelOptInfo *joinrel,
      39                 :             :                                                                                   bool only_pushed_down);
      40                 :             : static void make_grouped_join_rel(PlannerInfo *root, RelOptInfo *rel1,
      41                 :             :                                                                   RelOptInfo *rel2, RelOptInfo *joinrel,
      42                 :             :                                                                   SpecialJoinInfo *sjinfo, List *restrictlist);
      43                 :             : static void populate_joinrel_with_paths(PlannerInfo *root, RelOptInfo *rel1,
      44                 :             :                                                                                 RelOptInfo *rel2, RelOptInfo *joinrel,
      45                 :             :                                                                                 SpecialJoinInfo *sjinfo, List *restrictlist);
      46                 :             : static void try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1,
      47                 :             :                                                                    RelOptInfo *rel2, RelOptInfo *joinrel,
      48                 :             :                                                                    SpecialJoinInfo *parent_sjinfo,
      49                 :             :                                                                    List *parent_restrictlist);
      50                 :             : static SpecialJoinInfo *build_child_join_sjinfo(PlannerInfo *root,
      51                 :             :                                                                                                 SpecialJoinInfo *parent_sjinfo,
      52                 :             :                                                                                                 Relids left_relids, Relids right_relids);
      53                 :             : static void free_child_join_sjinfo(SpecialJoinInfo *child_sjinfo,
      54                 :             :                                                                    SpecialJoinInfo *parent_sjinfo);
      55                 :             : static void compute_partition_bounds(PlannerInfo *root, RelOptInfo *rel1,
      56                 :             :                                                                          RelOptInfo *rel2, RelOptInfo *joinrel,
      57                 :             :                                                                          SpecialJoinInfo *parent_sjinfo,
      58                 :             :                                                                          List **parts1, List **parts2);
      59                 :             : static void get_matching_part_pairs(PlannerInfo *root, RelOptInfo *joinrel,
      60                 :             :                                                                         RelOptInfo *rel1, RelOptInfo *rel2,
      61                 :             :                                                                         List **parts1, List **parts2);
      62                 :             : 
      63                 :             : 
      64                 :             : /*
      65                 :             :  * join_search_one_level
      66                 :             :  *        Consider ways to produce join relations containing exactly 'level'
      67                 :             :  *        jointree items.  (This is one step of the dynamic-programming method
      68                 :             :  *        embodied in standard_join_search.)  Join rel nodes for each feasible
      69                 :             :  *        combination of lower-level rels are created and returned in a list.
      70                 :             :  *        Implementation paths are created for each such joinrel, too.
      71                 :             :  *
      72                 :             :  * level: level of rels we want to make this time
      73                 :             :  * root->join_rel_level[j], 1 <= j < level, is a list of rels containing j items
      74                 :             :  *
      75                 :             :  * The result is returned in root->join_rel_level[level].
      76                 :             :  */
      77                 :             : void
      78                 :       12523 : join_search_one_level(PlannerInfo *root, int level)
      79                 :             : {
      80                 :       12523 :         List      **joinrels = root->join_rel_level;
      81                 :       12523 :         ListCell   *r;
      82                 :       12523 :         int                     k;
      83                 :             : 
      84         [ +  - ]:       12523 :         Assert(joinrels[level] == NIL);
      85                 :             : 
      86                 :             :         /* Set join_cur_level so that new joinrels are added to proper list */
      87                 :       12523 :         root->join_cur_level = level;
      88                 :             : 
      89                 :             :         /*
      90                 :             :          * First, consider left-sided and right-sided plans, in which rels of
      91                 :             :          * exactly level-1 member relations are joined against initial relations.
      92                 :             :          * We prefer to join using join clauses, but if we find a rel of level-1
      93                 :             :          * members that has no join clauses, we will generate Cartesian-product
      94                 :             :          * joins against all initial rels not already contained in it.
      95                 :             :          */
      96   [ +  +  +  +  :       42715 :         foreach(r, joinrels[level - 1])
                   +  + ]
      97                 :             :         {
      98                 :       30192 :                 RelOptInfo *old_rel = (RelOptInfo *) lfirst(r);
      99                 :             : 
     100   [ +  +  +  +  :       30192 :                 if (old_rel->joininfo != NIL || old_rel->has_eclass_joins ||
                   +  + ]
     101                 :        2376 :                         has_join_restriction(root, old_rel))
     102                 :             :                 {
     103                 :       28469 :                         int                     first_rel;
     104                 :             : 
     105                 :             :                         /*
     106                 :             :                          * There are join clauses or join order restrictions relevant to
     107                 :             :                          * this rel, so consider joins between this rel and (only) those
     108                 :             :                          * initial rels it is linked to by a clause or restriction.
     109                 :             :                          *
     110                 :             :                          * At level 2 this condition is symmetric, so there is no need to
     111                 :             :                          * look at initial rels before this one in the list; we already
     112                 :             :                          * considered such joins when we were at the earlier rel.  (The
     113                 :             :                          * mirror-image joins are handled automatically by make_join_rel.)
     114                 :             :                          * In later passes (level > 2), we join rels of the previous level
     115                 :             :                          * to each initial rel they don't already include but have a join
     116                 :             :                          * clause or restriction with.
     117                 :             :                          */
     118         [ +  + ]:       28469 :                         if (level == 2)         /* consider remaining initial rels */
     119                 :       20339 :                                 first_rel = foreach_current_index(r) + 1;
     120                 :             :                         else
     121                 :        8130 :                                 first_rel = 0;
     122                 :             : 
     123                 :       28469 :                         make_rels_by_clause_joins(root, old_rel, joinrels[1], first_rel);
     124                 :       28469 :                 }
     125                 :             :                 else
     126                 :             :                 {
     127                 :             :                         /*
     128                 :             :                          * Oops, we have a relation that is not joined to any other
     129                 :             :                          * relation, either directly or by join-order restrictions.
     130                 :             :                          * Cartesian product time.
     131                 :             :                          *
     132                 :             :                          * We consider a cartesian product with each not-already-included
     133                 :             :                          * initial rel, whether it has other join clauses or not.  At
     134                 :             :                          * level 2, if there are two or more clauseless initial rels, we
     135                 :             :                          * will redundantly consider joining them in both directions; but
     136                 :             :                          * such cases aren't common enough to justify adding complexity to
     137                 :             :                          * avoid the duplicated effort.
     138                 :             :                          */
     139                 :        3446 :                         make_rels_by_clauseless_joins(root,
     140                 :        1723 :                                                                                   old_rel,
     141                 :        1723 :                                                                                   joinrels[1]);
     142                 :             :                 }
     143                 :       30192 :         }
     144                 :             : 
     145                 :             :         /*
     146                 :             :          * Now, consider "bushy plans" in which relations of k initial rels are
     147                 :             :          * joined to relations of level-k initial rels, for 2 <= k <= level-2.
     148                 :             :          *
     149                 :             :          * We only consider bushy-plan joins for pairs of rels where there is a
     150                 :             :          * suitable join clause (or join order restriction), in order to avoid
     151                 :             :          * unreasonable growth of planning time.
     152                 :             :          */
     153                 :       13362 :         for (k = 2;; k++)
     154                 :             :         {
     155                 :       13362 :                 int                     other_level = level - k;
     156                 :             : 
     157                 :             :                 /*
     158                 :             :                  * Since make_join_rel(x, y) handles both x,y and y,x cases, we only
     159                 :             :                  * need to go as far as the halfway point.
     160                 :             :                  */
     161         [ +  + ]:       13362 :                 if (k > other_level)
     162                 :       12523 :                         break;
     163                 :             : 
     164   [ +  -  +  +  :        4121 :                 foreach(r, joinrels[k])
                   +  + ]
     165                 :             :                 {
     166                 :        3282 :                         RelOptInfo *old_rel = (RelOptInfo *) lfirst(r);
     167                 :        3282 :                         int                     first_rel;
     168                 :        3282 :                         ListCell   *r2;
     169                 :             : 
     170                 :             :                         /*
     171                 :             :                          * We can ignore relations without join clauses here, unless they
     172                 :             :                          * participate in join-order restrictions --- then we might have
     173                 :             :                          * to force a bushy join plan.
     174                 :             :                          */
     175   [ +  +  +  +  :        3282 :                         if (old_rel->joininfo == NIL && !old_rel->has_eclass_joins &&
                   +  + ]
     176                 :          66 :                                 !has_join_restriction(root, old_rel))
     177                 :          44 :                                 continue;
     178                 :             : 
     179         [ +  + ]:        3238 :                         if (k == other_level)   /* only consider remaining rels */
     180                 :        2155 :                                 first_rel = foreach_current_index(r) + 1;
     181                 :             :                         else
     182                 :        1083 :                                 first_rel = 0;
     183                 :             : 
     184   [ +  -  +  +  :       12352 :                         for_each_from(r2, joinrels[other_level], first_rel)
                   +  + ]
     185                 :             :                         {
     186                 :        9114 :                                 RelOptInfo *new_rel = (RelOptInfo *) lfirst(r2);
     187                 :             : 
     188         [ +  + ]:        9114 :                                 if (!bms_overlap(old_rel->relids, new_rel->relids))
     189                 :             :                                 {
     190                 :             :                                         /*
     191                 :             :                                          * OK, we can build a rel of the right level from this
     192                 :             :                                          * pair of rels.  Do so if there is at least one relevant
     193                 :             :                                          * join clause or join order restriction.
     194                 :             :                                          */
     195   [ +  +  +  + ]:        1588 :                                         if (have_relevant_joinclause(root, old_rel, new_rel) ||
     196                 :         191 :                                                 have_join_order_restriction(root, old_rel, new_rel))
     197                 :             :                                         {
     198                 :        1408 :                                                 (void) make_join_rel(root, old_rel, new_rel);
     199                 :        1408 :                                         }
     200                 :        1588 :                                 }
     201                 :        9114 :                         }
     202         [ +  + ]:        3282 :                 }
     203         [ +  + ]:       13362 :         }
     204                 :             : 
     205                 :             :         /*----------
     206                 :             :          * Last-ditch effort: if we failed to find any usable joins so far, force
     207                 :             :          * a set of cartesian-product joins to be generated.  This handles the
     208                 :             :          * special case where all the available rels have join clauses but we
     209                 :             :          * cannot use any of those clauses yet.  This can only happen when we are
     210                 :             :          * considering a join sub-problem (a sub-joinlist) and all the rels in the
     211                 :             :          * sub-problem have only join clauses with rels outside the sub-problem.
     212                 :             :          * An example is
     213                 :             :          *
     214                 :             :          *              SELECT ... FROM a INNER JOIN b ON TRUE, c, d, ...
     215                 :             :          *              WHERE a.w = c.x and b.y = d.z;
     216                 :             :          *
     217                 :             :          * If the "a INNER JOIN b" sub-problem does not get flattened into the
     218                 :             :          * upper level, we must be willing to make a cartesian join of a and b;
     219                 :             :          * but the code above will not have done so, because it thought that both
     220                 :             :          * a and b have joinclauses.  We consider only left-sided and right-sided
     221                 :             :          * cartesian joins in this case (no bushy).
     222                 :             :          *----------
     223                 :             :          */
     224         [ +  + ]:       12523 :         if (joinrels[level] == NIL)
     225                 :             :         {
     226                 :             :                 /*
     227                 :             :                  * This loop is just like the first one, except we always call
     228                 :             :                  * make_rels_by_clauseless_joins().
     229                 :             :                  */
     230   [ +  -  +  +  :           9 :                 foreach(r, joinrels[level - 1])
                   +  + ]
     231                 :             :                 {
     232                 :           6 :                         RelOptInfo *old_rel = (RelOptInfo *) lfirst(r);
     233                 :             : 
     234                 :          12 :                         make_rels_by_clauseless_joins(root,
     235                 :           6 :                                                                                   old_rel,
     236                 :           6 :                                                                                   joinrels[1]);
     237                 :           6 :                 }
     238                 :             : 
     239                 :             :                 /*----------
     240                 :             :                  * When special joins are involved, there may be no legal way
     241                 :             :                  * to make an N-way join for some values of N.  For example consider
     242                 :             :                  *
     243                 :             :                  * SELECT ... FROM t1 WHERE
     244                 :             :                  *       x IN (SELECT ... FROM t2,t3 WHERE ...) AND
     245                 :             :                  *       y IN (SELECT ... FROM t4,t5 WHERE ...)
     246                 :             :                  *
     247                 :             :                  * We will flatten this query to a 5-way join problem, but there are
     248                 :             :                  * no 4-way joins that join_is_legal() will consider legal.  We have
     249                 :             :                  * to accept failure at level 4 and go on to discover a workable
     250                 :             :                  * bushy plan at level 5.
     251                 :             :                  *
     252                 :             :                  * However, if there are no special joins and no lateral references
     253                 :             :                  * then join_is_legal() should never fail, and so the following sanity
     254                 :             :                  * check is useful.
     255                 :             :                  *----------
     256                 :             :                  */
     257         [ +  + ]:           3 :                 if (joinrels[level] == NIL &&
     258   [ -  +  #  # ]:           1 :                         root->join_info_list == NIL &&
     259                 :           0 :                         !root->hasLateralRTEs)
     260   [ #  #  #  # ]:           0 :                         elog(ERROR, "failed to build any %d-way joins", level);
     261                 :           3 :         }
     262                 :       12523 : }
     263                 :             : 
     264                 :             : /*
     265                 :             :  * make_rels_by_clause_joins
     266                 :             :  *        Build joins between the given relation 'old_rel' and other relations
     267                 :             :  *        that participate in join clauses that 'old_rel' also participates in
     268                 :             :  *        (or participate in join-order restrictions with it).
     269                 :             :  *        The join rels are returned in root->join_rel_level[join_cur_level].
     270                 :             :  *
     271                 :             :  * Note: at levels above 2 we will generate the same joined relation in
     272                 :             :  * multiple ways --- for example (a join b) join c is the same RelOptInfo as
     273                 :             :  * (b join c) join a, though the second case will add a different set of Paths
     274                 :             :  * to it.  This is the reason for using the join_rel_level mechanism, which
     275                 :             :  * automatically ensures that each new joinrel is only added to the list once.
     276                 :             :  *
     277                 :             :  * 'old_rel' is the relation entry for the relation to be joined
     278                 :             :  * 'other_rels': a list containing the other rels to be considered for joining
     279                 :             :  * 'first_rel_idx': the first rel to be considered in 'other_rels'
     280                 :             :  *
     281                 :             :  * Currently, this is only used with initial rels in other_rels, but it
     282                 :             :  * will work for joining to joinrels too.
     283                 :             :  */
     284                 :             : static void
     285                 :       28469 : make_rels_by_clause_joins(PlannerInfo *root,
     286                 :             :                                                   RelOptInfo *old_rel,
     287                 :             :                                                   List *other_rels,
     288                 :             :                                                   int first_rel_idx)
     289                 :             : {
     290                 :       28469 :         ListCell   *l;
     291                 :             : 
     292   [ +  -  +  +  :       76130 :         for_each_from(l, other_rels, first_rel_idx)
                   +  + ]
     293                 :             :         {
     294                 :       47661 :                 RelOptInfo *other_rel = (RelOptInfo *) lfirst(l);
     295                 :             : 
     296   [ +  +  +  + ]:       52766 :                 if (!bms_overlap(old_rel->relids, other_rel->relids) &&
     297         [ +  + ]:       28202 :                         (have_relevant_joinclause(root, old_rel, other_rel) ||
     298                 :        5105 :                          have_join_order_restriction(root, old_rel, other_rel)))
     299                 :             :                 {
     300                 :       23657 :                         (void) make_join_rel(root, old_rel, other_rel);
     301                 :       23657 :                 }
     302                 :       47661 :         }
     303                 :       28469 : }
     304                 :             : 
     305                 :             : /*
     306                 :             :  * make_rels_by_clauseless_joins
     307                 :             :  *        Given a relation 'old_rel' and a list of other relations
     308                 :             :  *        'other_rels', create a join relation between 'old_rel' and each
     309                 :             :  *        member of 'other_rels' that isn't already included in 'old_rel'.
     310                 :             :  *        The join rels are returned in root->join_rel_level[join_cur_level].
     311                 :             :  *
     312                 :             :  * 'old_rel' is the relation entry for the relation to be joined
     313                 :             :  * 'other_rels': a list containing the other rels to be considered for joining
     314                 :             :  *
     315                 :             :  * Currently, this is only used with initial rels in other_rels, but it would
     316                 :             :  * work for joining to joinrels too.
     317                 :             :  */
     318                 :             : static void
     319                 :        1729 : make_rels_by_clauseless_joins(PlannerInfo *root,
     320                 :             :                                                           RelOptInfo *old_rel,
     321                 :             :                                                           List *other_rels)
     322                 :             : {
     323                 :        1729 :         ListCell   *l;
     324                 :             : 
     325   [ +  -  +  +  :        5521 :         foreach(l, other_rels)
                   +  + ]
     326                 :             :         {
     327                 :        3792 :                 RelOptInfo *other_rel = (RelOptInfo *) lfirst(l);
     328                 :             : 
     329         [ +  + ]:        3792 :                 if (!bms_overlap(other_rel->relids, old_rel->relids))
     330                 :             :                 {
     331                 :        1868 :                         (void) make_join_rel(root, old_rel, other_rel);
     332                 :        1868 :                 }
     333                 :        3792 :         }
     334                 :        1729 : }
     335                 :             : 
     336                 :             : 
     337                 :             : /*
     338                 :             :  * join_is_legal
     339                 :             :  *         Determine whether a proposed join is legal given the query's
     340                 :             :  *         join order constraints; and if it is, determine the join type.
     341                 :             :  *
     342                 :             :  * Caller must supply not only the two rels, but the union of their relids.
     343                 :             :  * (We could simplify the API by computing joinrelids locally, but this
     344                 :             :  * would be redundant work in the normal path through make_join_rel.
     345                 :             :  * Note that this value does NOT include the RT index of any outer join that
     346                 :             :  * might need to be performed here, so it's not the canonical identifier
     347                 :             :  * of the join relation.)
     348                 :             :  *
     349                 :             :  * On success, *sjinfo_p is set to NULL if this is to be a plain inner join,
     350                 :             :  * else it's set to point to the associated SpecialJoinInfo node.  Also,
     351                 :             :  * *reversed_p is set true if the given relations need to be swapped to
     352                 :             :  * match the SpecialJoinInfo node.
     353                 :             :  */
     354                 :             : static bool
     355                 :       28407 : join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
     356                 :             :                           Relids joinrelids,
     357                 :             :                           SpecialJoinInfo **sjinfo_p, bool *reversed_p)
     358                 :             : {
     359                 :       28407 :         SpecialJoinInfo *match_sjinfo;
     360                 :       28407 :         bool            reversed;
     361                 :       28407 :         bool            unique_ified;
     362                 :       28407 :         bool            must_be_leftjoin;
     363                 :       28407 :         ListCell   *l;
     364                 :             : 
     365                 :             :         /*
     366                 :             :          * Ensure output params are set on failure return.  This is just to
     367                 :             :          * suppress uninitialized-variable warnings from overly anal compilers.
     368                 :             :          */
     369                 :       28407 :         *sjinfo_p = NULL;
     370                 :       28407 :         *reversed_p = false;
     371                 :             : 
     372                 :             :         /*
     373                 :             :          * If we have any special joins, the proposed join might be illegal; and
     374                 :             :          * in any case we have to determine its join type.  Scan the join info
     375                 :             :          * list for matches and conflicts.
     376                 :             :          */
     377                 :       28407 :         match_sjinfo = NULL;
     378                 :       28407 :         reversed = false;
     379                 :       28407 :         unique_ified = false;
     380                 :       28407 :         must_be_leftjoin = false;
     381                 :             : 
     382   [ +  +  +  +  :       50784 :         foreach(l, root->join_info_list)
             +  +  +  + ]
     383                 :             :         {
     384                 :       22377 :                 SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(l);
     385                 :             : 
     386                 :             :                 /*
     387                 :             :                  * This special join is not relevant unless its RHS overlaps the
     388                 :             :                  * proposed join.  (Check this first as a fast path for dismissing
     389                 :             :                  * most irrelevant SJs quickly.)
     390                 :             :                  */
     391         [ +  + ]:       22377 :                 if (!bms_overlap(sjinfo->min_righthand, joinrelids))
     392                 :        7516 :                         continue;
     393                 :             : 
     394                 :             :                 /*
     395                 :             :                  * Also, not relevant if proposed join is fully contained within RHS
     396                 :             :                  * (ie, we're still building up the RHS).
     397                 :             :                  */
     398         [ +  + ]:       14861 :                 if (bms_is_subset(joinrelids, sjinfo->min_righthand))
     399                 :         855 :                         continue;
     400                 :             : 
     401                 :             :                 /*
     402                 :             :                  * Also, not relevant if SJ is already done within either input.
     403                 :             :                  */
     404   [ +  +  +  + ]:       14006 :                 if (bms_is_subset(sjinfo->min_lefthand, rel1->relids) &&
     405                 :       11662 :                         bms_is_subset(sjinfo->min_righthand, rel1->relids))
     406                 :        4215 :                         continue;
     407   [ +  +  +  + ]:        9791 :                 if (bms_is_subset(sjinfo->min_lefthand, rel2->relids) &&
     408                 :        1372 :                         bms_is_subset(sjinfo->min_righthand, rel2->relids))
     409                 :         586 :                         continue;
     410                 :             : 
     411                 :             :                 /*
     412                 :             :                  * If it's a semijoin and we already joined the RHS to any other rels
     413                 :             :                  * within either input, then we must have unique-ified the RHS at that
     414                 :             :                  * point (see below).  Therefore the semijoin is no longer relevant in
     415                 :             :                  * this join path.
     416                 :             :                  */
     417         [ +  + ]:        9205 :                 if (sjinfo->jointype == JOIN_SEMI)
     418                 :             :                 {
     419   [ +  +  +  + ]:        1520 :                         if (bms_is_subset(sjinfo->syn_righthand, rel1->relids) &&
     420                 :         206 :                                 !bms_equal(sjinfo->syn_righthand, rel1->relids))
     421                 :          65 :                                 continue;
     422   [ +  +  +  + ]:        1455 :                         if (bms_is_subset(sjinfo->syn_righthand, rel2->relids) &&
     423                 :         961 :                                 !bms_equal(sjinfo->syn_righthand, rel2->relids))
     424                 :          21 :                                 continue;
     425                 :        1434 :                 }
     426                 :             : 
     427                 :             :                 /*
     428                 :             :                  * If one input contains min_lefthand and the other contains
     429                 :             :                  * min_righthand, then we can perform the SJ at this join.
     430                 :             :                  *
     431                 :             :                  * Reject if we get matches to more than one SJ; that implies we're
     432                 :             :                  * considering something that's not really valid.
     433                 :             :                  */
     434   [ +  +  +  + ]:        9119 :                 if (bms_is_subset(sjinfo->min_lefthand, rel1->relids) &&
     435                 :        7434 :                         bms_is_subset(sjinfo->min_righthand, rel2->relids))
     436                 :             :                 {
     437         [ -  + ]:        6396 :                         if (match_sjinfo)
     438                 :           0 :                                 return false;   /* invalid join path */
     439                 :        6396 :                         match_sjinfo = sjinfo;
     440                 :        6396 :                         reversed = false;
     441                 :        6396 :                 }
     442   [ +  +  +  + ]:        2723 :                 else if (bms_is_subset(sjinfo->min_lefthand, rel2->relids) &&
     443                 :         758 :                                  bms_is_subset(sjinfo->min_righthand, rel1->relids))
     444                 :             :                 {
     445         [ -  + ]:         554 :                         if (match_sjinfo)
     446                 :           0 :                                 return false;   /* invalid join path */
     447                 :         554 :                         match_sjinfo = sjinfo;
     448                 :         554 :                         reversed = true;
     449                 :         554 :                 }
     450         [ +  + ]:        2169 :                 else if (sjinfo->jointype == JOIN_SEMI &&
     451   [ +  +  +  + ]:         467 :                                  bms_equal(sjinfo->syn_righthand, rel2->relids) &&
     452                 :          75 :                                  create_unique_paths(root, rel2, sjinfo) != NULL)
     453                 :             :                 {
     454                 :             :                         /*----------
     455                 :             :                          * For a semijoin, we can join the RHS to anything else by
     456                 :             :                          * unique-ifying the RHS (if the RHS can be unique-ified).
     457                 :             :                          * We will only get here if we have the full RHS but less
     458                 :             :                          * than min_lefthand on the LHS.
     459                 :             :                          *
     460                 :             :                          * The reason to consider such a join path is exemplified by
     461                 :             :                          *      SELECT ... FROM a,b WHERE (a.x,b.y) IN (SELECT c1,c2 FROM c)
     462                 :             :                          * If we insist on doing this as a semijoin we will first have
     463                 :             :                          * to form the cartesian product of A*B.  But if we unique-ify
     464                 :             :                          * C then the semijoin becomes a plain innerjoin and we can join
     465                 :             :                          * in any order, eg C to A and then to B.  When C is much smaller
     466                 :             :                          * than A and B this can be a huge win.  So we allow C to be
     467                 :             :                          * joined to just A or just B here, and then make_join_rel has
     468                 :             :                          * to handle the case properly.
     469                 :             :                          *
     470                 :             :                          * Note that actually we'll allow unique-ified C to be joined to
     471                 :             :                          * some other relation D here, too.  That is legal, if usually not
     472                 :             :                          * very sane, and this routine is only concerned with legality not
     473                 :             :                          * with whether the join is good strategy.
     474                 :             :                          *----------
     475                 :             :                          */
     476         [ +  + ]:          39 :                         if (match_sjinfo)
     477                 :           1 :                                 return false;   /* invalid join path */
     478                 :          38 :                         match_sjinfo = sjinfo;
     479                 :          38 :                         reversed = false;
     480                 :          38 :                         unique_ified = true;
     481                 :          38 :                 }
     482         [ +  + ]:        2130 :                 else if (sjinfo->jointype == JOIN_SEMI &&
     483   [ +  +  +  + ]:         428 :                                  bms_equal(sjinfo->syn_righthand, rel1->relids) &&
     484                 :          39 :                                  create_unique_paths(root, rel1, sjinfo) != NULL)
     485                 :             :                 {
     486                 :             :                         /* Reversed semijoin case */
     487         [ -  + ]:          17 :                         if (match_sjinfo)
     488                 :           0 :                                 return false;   /* invalid join path */
     489                 :          17 :                         match_sjinfo = sjinfo;
     490                 :          17 :                         reversed = true;
     491                 :          17 :                         unique_ified = true;
     492                 :          17 :                 }
     493                 :             :                 else
     494                 :             :                 {
     495                 :             :                         /*
     496                 :             :                          * Otherwise, the proposed join overlaps the RHS but isn't a valid
     497                 :             :                          * implementation of this SJ.  But don't panic quite yet: the RHS
     498                 :             :                          * violation might have occurred previously, in one or both input
     499                 :             :                          * relations, in which case we must have previously decided that
     500                 :             :                          * it was OK to commute some other SJ with this one.  If we need
     501                 :             :                          * to perform this join to finish building up the RHS, rejecting
     502                 :             :                          * it could lead to not finding any plan at all.  (This can occur
     503                 :             :                          * because of the heuristics elsewhere in this file that postpone
     504                 :             :                          * clauseless joins: we might not consider doing a clauseless join
     505                 :             :                          * within the RHS until after we've performed other, validly
     506                 :             :                          * commutable SJs with one or both sides of the clauseless join.)
     507                 :             :                          * This consideration boils down to the rule that if both inputs
     508                 :             :                          * overlap the RHS, we can allow the join --- they are either
     509                 :             :                          * fully within the RHS, or represent previously-allowed joins to
     510                 :             :                          * rels outside it.
     511                 :             :                          */
     512   [ +  +  +  + ]:        2113 :                         if (bms_overlap(rel1->relids, sjinfo->min_righthand) &&
     513                 :         648 :                                 bms_overlap(rel2->relids, sjinfo->min_righthand))
     514                 :          29 :                                 continue;               /* assume valid previous violation of RHS */
     515                 :             : 
     516                 :             :                         /*
     517                 :             :                          * The proposed join could still be legal, but only if we're
     518                 :             :                          * allowed to associate it into the RHS of this SJ.  That means
     519                 :             :                          * this SJ must be a LEFT join (not SEMI or ANTI, and certainly
     520                 :             :                          * not FULL) and the proposed join must not overlap the LHS.
     521                 :             :                          */
     522   [ +  +  +  + ]:        2084 :                         if (sjinfo->jointype != JOIN_LEFT ||
     523                 :        1651 :                                 bms_overlap(joinrelids, sjinfo->min_lefthand))
     524                 :        1464 :                                 return false;   /* invalid join path */
     525                 :             : 
     526                 :             :                         /*
     527                 :             :                          * To be valid, the proposed join must be a LEFT join; otherwise
     528                 :             :                          * it can't associate into this SJ's RHS.  But we may not yet have
     529                 :             :                          * found the SpecialJoinInfo matching the proposed join, so we
     530                 :             :                          * can't test that yet.  Remember the requirement for later.
     531                 :             :                          */
     532                 :         620 :                         must_be_leftjoin = true;
     533                 :             :                 }
     534      [ +  +  + ]:       22377 :         }
     535                 :             : 
     536                 :             :         /*
     537                 :             :          * Fail if violated any SJ's RHS and didn't match to a LEFT SJ: the
     538                 :             :          * proposed join can't associate into an SJ's RHS.
     539                 :             :          *
     540                 :             :          * Also, fail if the proposed join's predicate isn't strict; we're
     541                 :             :          * essentially checking to see if we can apply outer-join identity 3, and
     542                 :             :          * that's a requirement.  (This check may be redundant with checks in
     543                 :             :          * make_outerjoininfo, but I'm not quite sure, and it's cheap to test.)
     544                 :             :          */
     545   [ +  +  +  - ]:       27095 :         if (must_be_leftjoin &&
     546         [ +  + ]:         393 :                 (match_sjinfo == NULL ||
     547         [ +  - ]:         153 :                  match_sjinfo->jointype != JOIN_LEFT ||
     548                 :         153 :                  !match_sjinfo->lhs_strict))
     549                 :         240 :                 return false;                   /* invalid join path */
     550                 :             : 
     551                 :             :         /*
     552                 :             :          * We also have to check for constraints imposed by LATERAL references.
     553                 :             :          */
     554         [ +  + ]:       26702 :         if (root->hasLateralRTEs)
     555                 :             :         {
     556                 :        1437 :                 bool            lateral_fwd;
     557                 :        1437 :                 bool            lateral_rev;
     558                 :        1437 :                 Relids          join_lateral_rels;
     559                 :             : 
     560                 :             :                 /*
     561                 :             :                  * The proposed rels could each contain lateral references to the
     562                 :             :                  * other, in which case the join is impossible.  If there are lateral
     563                 :             :                  * references in just one direction, then the join has to be done with
     564                 :             :                  * a nestloop with the lateral referencer on the inside.  If the join
     565                 :             :                  * matches an SJ that cannot be implemented by such a nestloop, the
     566                 :             :                  * join is impossible.
     567                 :             :                  *
     568                 :             :                  * Also, if the lateral reference is only indirect, we should reject
     569                 :             :                  * the join; whatever rel(s) the reference chain goes through must be
     570                 :             :                  * joined to first.
     571                 :             :                  */
     572                 :        1437 :                 lateral_fwd = bms_overlap(rel1->relids, rel2->lateral_relids);
     573                 :        1437 :                 lateral_rev = bms_overlap(rel2->relids, rel1->lateral_relids);
     574   [ +  +  +  + ]:        1437 :                 if (lateral_fwd && lateral_rev)
     575                 :           3 :                         return false;           /* have lateral refs in both directions */
     576         [ +  + ]:        1434 :                 if (lateral_fwd)
     577                 :             :                 {
     578                 :             :                         /* has to be implemented as nestloop with rel1 on left */
     579   [ +  +  -  + ]:         549 :                         if (match_sjinfo &&
     580         [ +  - ]:          71 :                                 (reversed ||
     581         [ +  + ]:          71 :                                  unique_ified ||
     582                 :          68 :                                  match_sjinfo->jointype == JOIN_FULL))
     583                 :           3 :                                 return false;   /* not implementable as nestloop */
     584                 :             :                         /* check there is a direct reference from rel2 to rel1 */
     585         [ +  + ]:         478 :                         if (!bms_overlap(rel1->relids, rel2->direct_lateral_relids))
     586                 :           7 :                                 return false;   /* only indirect refs, so reject */
     587                 :         471 :                 }
     588         [ +  + ]:         953 :                 else if (lateral_rev)
     589                 :             :                 {
     590                 :             :                         /* has to be implemented as nestloop with rel2 on left */
     591   [ +  +  -  + ]:         199 :                         if (match_sjinfo &&
     592         [ +  - ]:          13 :                                 (!reversed ||
     593         [ +  - ]:          13 :                                  unique_ified ||
     594                 :          13 :                                  match_sjinfo->jointype == JOIN_FULL))
     595                 :           0 :                                 return false;   /* not implementable as nestloop */
     596                 :             :                         /* check there is a direct reference from rel1 to rel2 */
     597         [ +  - ]:         186 :                         if (!bms_overlap(rel2->relids, rel1->direct_lateral_relids))
     598                 :           0 :                                 return false;   /* only indirect refs, so reject */
     599                 :         186 :                 }
     600                 :             : 
     601                 :             :                 /*
     602                 :             :                  * LATERAL references could also cause problems later on if we accept
     603                 :             :                  * this join: if the join's minimum parameterization includes any rels
     604                 :             :                  * that would have to be on the inside of an outer join with this join
     605                 :             :                  * rel, then it's never going to be possible to build the complete
     606                 :             :                  * query using this join.  We should reject this join not only because
     607                 :             :                  * it'll save work, but because if we don't, the clauseless-join
     608                 :             :                  * heuristics might think that legality of this join means that some
     609                 :             :                  * other join rel need not be formed, and that could lead to failure
     610                 :             :                  * to find any plan at all.  We have to consider not only rels that
     611                 :             :                  * are directly on the inner side of an OJ with the joinrel, but also
     612                 :             :                  * ones that are indirectly so, so search to find all such rels.
     613                 :             :                  */
     614                 :        2848 :                 join_lateral_rels = min_join_parameterization(root, joinrelids,
     615                 :        1424 :                                                                                                           rel1, rel2);
     616         [ +  + ]:        1424 :                 if (join_lateral_rels)
     617                 :             :                 {
     618                 :         295 :                         Relids          join_plus_rhs = bms_copy(joinrelids);
     619                 :         295 :                         bool            more;
     620                 :             : 
     621                 :         295 :                         do
     622                 :             :                         {
     623                 :         369 :                                 more = false;
     624   [ +  +  +  +  :         706 :                                 foreach(l, root->join_info_list)
                   +  + ]
     625                 :             :                                 {
     626                 :         337 :                                         SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(l);
     627                 :             : 
     628                 :             :                                         /* ignore full joins --- their ordering is predetermined */
     629         [ +  + ]:         337 :                                         if (sjinfo->jointype == JOIN_FULL)
     630                 :           3 :                                                 continue;
     631                 :             : 
     632   [ +  +  +  + ]:         334 :                                         if (bms_overlap(sjinfo->min_lefthand, join_plus_rhs) &&
     633                 :         283 :                                                 !bms_is_subset(sjinfo->min_righthand, join_plus_rhs))
     634                 :             :                                         {
     635                 :         198 :                                                 join_plus_rhs = bms_add_members(join_plus_rhs,
     636                 :          99 :                                                                                                                 sjinfo->min_righthand);
     637                 :          99 :                                                 more = true;
     638                 :          99 :                                         }
     639      [ -  +  + ]:         337 :                                 }
     640         [ +  + ]:         369 :                         } while (more);
     641         [ +  + ]:         295 :                         if (bms_overlap(join_plus_rhs, join_lateral_rels))
     642                 :          60 :                                 return false;   /* will not be able to join to some RHS rel */
     643         [ +  + ]:         295 :                 }
     644         [ +  + ]:        1437 :         }
     645                 :             : 
     646                 :             :         /* Otherwise, it's a valid join */
     647                 :       26629 :         *sjinfo_p = match_sjinfo;
     648                 :       26629 :         *reversed_p = reversed;
     649                 :       26629 :         return true;
     650                 :       28407 : }
     651                 :             : 
     652                 :             : /*
     653                 :             :  * init_dummy_sjinfo
     654                 :             :  *    Populate the given SpecialJoinInfo for a plain inner join between the
     655                 :             :  *    left and right relations specified by left_relids and right_relids
     656                 :             :  *    respectively.
     657                 :             :  *
     658                 :             :  * Normally, an inner join does not have a SpecialJoinInfo node associated with
     659                 :             :  * it. But some functions involved in join planning require one containing at
     660                 :             :  * least the information of which relations are being joined.  So we initialize
     661                 :             :  * that information here.
     662                 :             :  */
     663                 :             : void
     664                 :      132234 : init_dummy_sjinfo(SpecialJoinInfo *sjinfo, Relids left_relids,
     665                 :             :                                   Relids right_relids)
     666                 :             : {
     667                 :      132234 :         sjinfo->type = T_SpecialJoinInfo;
     668                 :      132234 :         sjinfo->min_lefthand = left_relids;
     669                 :      132234 :         sjinfo->min_righthand = right_relids;
     670                 :      132234 :         sjinfo->syn_lefthand = left_relids;
     671                 :      132234 :         sjinfo->syn_righthand = right_relids;
     672                 :      132234 :         sjinfo->jointype = JOIN_INNER;
     673                 :      132234 :         sjinfo->ojrelid = 0;
     674                 :      132234 :         sjinfo->commute_above_l = NULL;
     675                 :      132234 :         sjinfo->commute_above_r = NULL;
     676                 :      132234 :         sjinfo->commute_below_l = NULL;
     677                 :      132234 :         sjinfo->commute_below_r = NULL;
     678                 :             :         /* we don't bother trying to make the remaining fields valid */
     679                 :      132234 :         sjinfo->lhs_strict = false;
     680                 :      132234 :         sjinfo->semi_can_btree = false;
     681                 :      132234 :         sjinfo->semi_can_hash = false;
     682                 :      132234 :         sjinfo->semi_operators = NIL;
     683                 :      132234 :         sjinfo->semi_rhs_exprs = NIL;
     684                 :      132234 : }
     685                 :             : 
     686                 :             : /*
     687                 :             :  * make_join_rel
     688                 :             :  *         Find or create a join RelOptInfo that represents the join of
     689                 :             :  *         the two given rels, and add to it path information for paths
     690                 :             :  *         created with the two rels as outer and inner rel.
     691                 :             :  *         (The join rel may already contain paths generated from other
     692                 :             :  *         pairs of rels that add up to the same set of base rels.)
     693                 :             :  *
     694                 :             :  * NB: will return NULL if attempted join is not valid.  This can happen
     695                 :             :  * when working with outer joins, or with IN or EXISTS clauses that have been
     696                 :             :  * turned into joins.
     697                 :             :  */
     698                 :             : RelOptInfo *
     699                 :       28331 : make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
     700                 :             : {
     701                 :       28331 :         Relids          joinrelids;
     702                 :       28331 :         SpecialJoinInfo *sjinfo;
     703                 :       28331 :         bool            reversed;
     704                 :       28331 :         List       *pushed_down_joins = NIL;
     705                 :       28331 :         SpecialJoinInfo sjinfo_data;
     706                 :       28331 :         RelOptInfo *joinrel;
     707                 :       28331 :         List       *restrictlist;
     708                 :             : 
     709                 :             :         /* We should never try to join two overlapping sets of rels. */
     710         [ +  - ]:       28331 :         Assert(!bms_overlap(rel1->relids, rel2->relids));
     711                 :             : 
     712                 :             :         /* Construct Relids set that identifies the joinrel (without OJ as yet). */
     713                 :       28331 :         joinrelids = bms_union(rel1->relids, rel2->relids);
     714                 :             : 
     715                 :             :         /* Check validity and determine join type. */
     716         [ +  + ]:       28331 :         if (!join_is_legal(root, rel1, rel2, joinrelids,
     717                 :             :                                            &sjinfo, &reversed))
     718                 :             :         {
     719                 :             :                 /* invalid join path */
     720                 :        1744 :                 bms_free(joinrelids);
     721                 :        1744 :                 return NULL;
     722                 :             :         }
     723                 :             : 
     724                 :             :         /*
     725                 :             :          * Add outer join relid(s) to form the canonical relids.  Any added outer
     726                 :             :          * joins besides sjinfo itself are appended to pushed_down_joins.
     727                 :             :          */
     728                 :       26587 :         joinrelids = add_outer_joins_to_relids(root, joinrelids, sjinfo,
     729                 :             :                                                                                    &pushed_down_joins);
     730                 :             : 
     731                 :             :         /* Swap rels if needed to match the join info. */
     732         [ +  + ]:       26587 :         if (reversed)
     733                 :             :         {
     734                 :         567 :                 RelOptInfo *trel = rel1;
     735                 :             : 
     736                 :         567 :                 rel1 = rel2;
     737                 :         567 :                 rel2 = trel;
     738                 :         567 :         }
     739                 :             : 
     740                 :             :         /*
     741                 :             :          * If it's a plain inner join, then we won't have found anything in
     742                 :             :          * join_info_list.  Make up a SpecialJoinInfo so that selectivity
     743                 :             :          * estimation functions will know what's being joined.
     744                 :             :          */
     745         [ +  + ]:       26587 :         if (sjinfo == NULL)
     746                 :             :         {
     747                 :       19629 :                 sjinfo = &sjinfo_data;
     748                 :       19629 :                 init_dummy_sjinfo(sjinfo, rel1->relids, rel2->relids);
     749                 :       19629 :         }
     750                 :             : 
     751                 :             :         /*
     752                 :             :          * Find or build the join RelOptInfo, and compute the restrictlist that
     753                 :             :          * goes with this particular joining.
     754                 :             :          */
     755                 :       53174 :         joinrel = build_join_rel(root, joinrelids, rel1, rel2,
     756                 :       26587 :                                                          sjinfo, pushed_down_joins,
     757                 :             :                                                          &restrictlist);
     758                 :             : 
     759                 :             :         /*
     760                 :             :          * If we've already proven this join is empty, we needn't consider any
     761                 :             :          * more paths for it.
     762                 :             :          */
     763         [ +  + ]:       26587 :         if (is_dummy_rel(joinrel))
     764                 :             :         {
     765                 :          84 :                 bms_free(joinrelids);
     766                 :          84 :                 return joinrel;
     767                 :             :         }
     768                 :             : 
     769                 :             :         /* Build a grouped join relation for 'joinrel' if possible. */
     770                 :       53006 :         make_grouped_join_rel(root, rel1, rel2, joinrel, sjinfo,
     771                 :       26503 :                                                   restrictlist);
     772                 :             : 
     773                 :             :         /* Add paths to the join relation. */
     774                 :       53006 :         populate_joinrel_with_paths(root, rel1, rel2, joinrel, sjinfo,
     775                 :       26503 :                                                                 restrictlist);
     776                 :             : 
     777                 :       26503 :         bms_free(joinrelids);
     778                 :             : 
     779                 :       26503 :         return joinrel;
     780                 :       28331 : }
     781                 :             : 
     782                 :             : /*
     783                 :             :  * add_outer_joins_to_relids
     784                 :             :  *        Add relids to input_relids to represent any outer joins that will be
     785                 :             :  *        calculated at this join.
     786                 :             :  *
     787                 :             :  * input_relids is the union of the relid sets of the two input relations.
     788                 :             :  * Note that we modify this in-place and return it; caller must bms_copy()
     789                 :             :  * it first, if a separate value is desired.
     790                 :             :  *
     791                 :             :  * sjinfo represents the join being performed.
     792                 :             :  *
     793                 :             :  * If the current join completes the calculation of any outer joins that
     794                 :             :  * have been pushed down per outer-join identity 3, those relids will be
     795                 :             :  * added to the result along with sjinfo's own relid.  If pushed_down_joins
     796                 :             :  * is not NULL, then also the SpecialJoinInfos for such added outer joins will
     797                 :             :  * be appended to *pushed_down_joins (so caller must initialize it to NIL).
     798                 :             :  */
     799                 :             : Relids
     800                 :       27900 : add_outer_joins_to_relids(PlannerInfo *root, Relids input_relids,
     801                 :             :                                                   SpecialJoinInfo *sjinfo,
     802                 :             :                                                   List **pushed_down_joins)
     803                 :             : {
     804                 :             :         /* Nothing to do if this isn't an outer join with an assigned relid. */
     805   [ +  +  +  + ]:       27900 :         if (sjinfo == NULL || sjinfo->ojrelid == 0)
     806                 :       22268 :                 return input_relids;
     807                 :             : 
     808                 :             :         /*
     809                 :             :          * If it's not a left join, we have no rules that would permit executing
     810                 :             :          * it in non-syntactic order, so just form the syntactic relid set.  (This
     811                 :             :          * is just a quick-exit test; we'd come to the same conclusion anyway,
     812                 :             :          * since its commute_below_l and commute_above_l sets must be empty.)
     813                 :             :          */
     814         [ +  + ]:        5632 :         if (sjinfo->jointype != JOIN_LEFT)
     815                 :         269 :                 return bms_add_member(input_relids, sjinfo->ojrelid);
     816                 :             : 
     817                 :             :         /*
     818                 :             :          * We cannot add the OJ relid if this join has been pushed into the RHS of
     819                 :             :          * a syntactically-lower left join per OJ identity 3.  (If it has, then we
     820                 :             :          * cannot claim that its outputs represent the final state of its RHS.)
     821                 :             :          * There will not be any other OJs that can be added either, so we're
     822                 :             :          * done.
     823                 :             :          */
     824         [ +  + ]:        5363 :         if (!bms_is_subset(sjinfo->commute_below_l, input_relids))
     825                 :         105 :                 return input_relids;
     826                 :             : 
     827                 :             :         /* OK to add OJ's own relid */
     828                 :        5258 :         input_relids = bms_add_member(input_relids, sjinfo->ojrelid);
     829                 :             : 
     830                 :             :         /*
     831                 :             :          * Contrariwise, if we are now forming the final result of such a commuted
     832                 :             :          * pair of OJs, it's time to add the relid(s) of the pushed-down join(s).
     833                 :             :          * We can skip this if this join was never a candidate to be pushed up.
     834                 :             :          */
     835         [ +  + ]:        5258 :         if (sjinfo->commute_above_l)
     836                 :             :         {
     837                 :         266 :                 Relids          commute_above_rels = bms_copy(sjinfo->commute_above_l);
     838                 :         266 :                 ListCell   *lc;
     839                 :             : 
     840                 :             :                 /*
     841                 :             :                  * The current join could complete the nulling of more than one
     842                 :             :                  * pushed-down join, so we have to examine all the SpecialJoinInfos.
     843                 :             :                  * Because join_info_list was built in bottom-up order, it's
     844                 :             :                  * sufficient to traverse it once: an ojrelid we add in one loop
     845                 :             :                  * iteration would not have affected decisions of earlier iterations.
     846                 :             :                  */
     847   [ +  -  +  +  :        1178 :                 foreach(lc, root->join_info_list)
                   +  + ]
     848                 :             :                 {
     849                 :         912 :                         SpecialJoinInfo *othersj = (SpecialJoinInfo *) lfirst(lc);
     850                 :             : 
     851         [ +  + ]:         912 :                         if (othersj == sjinfo ||
     852   [ +  +  -  + ]:         646 :                                 othersj->ojrelid == 0 || othersj->jointype != JOIN_LEFT)
     853                 :         268 :                                 continue;               /* definitely not interesting */
     854                 :             : 
     855         [ +  + ]:         644 :                         if (!bms_is_member(othersj->ojrelid, commute_above_rels))
     856                 :         364 :                                 continue;
     857                 :             : 
     858                 :             :                         /* Add it if not already present but conditions now satisfied */
     859         [ +  - ]:         280 :                         if (!bms_is_member(othersj->ojrelid, input_relids) &&
     860         [ +  + ]:         280 :                                 bms_is_subset(othersj->min_lefthand, input_relids) &&
     861   [ +  +  +  + ]:         276 :                                 bms_is_subset(othersj->min_righthand, input_relids) &&
     862                 :         150 :                                 bms_is_subset(othersj->commute_below_l, input_relids))
     863                 :             :                         {
     864                 :         144 :                                 input_relids = bms_add_member(input_relids, othersj->ojrelid);
     865                 :             :                                 /* report such pushed down outer joins, if asked */
     866         [ -  + ]:         144 :                                 if (pushed_down_joins != NULL)
     867                 :         144 :                                         *pushed_down_joins = lappend(*pushed_down_joins, othersj);
     868                 :             : 
     869                 :             :                                 /*
     870                 :             :                                  * We must also check any joins that othersj potentially
     871                 :             :                                  * commutes with.  They likewise must appear later in
     872                 :             :                                  * join_info_list than othersj itself, so we can visit them
     873                 :             :                                  * later in this loop.
     874                 :             :                                  */
     875                 :         288 :                                 commute_above_rels = bms_add_members(commute_above_rels,
     876                 :         144 :                                                                                                          othersj->commute_above_l);
     877                 :         144 :                         }
     878      [ -  +  + ]:         912 :                 }
     879                 :         266 :         }
     880                 :             : 
     881                 :        5258 :         return input_relids;
     882                 :       27900 : }
     883                 :             : 
     884                 :             : /*
     885                 :             :  * make_grouped_join_rel
     886                 :             :  *        Build a grouped join relation for the given "joinrel" if eager
     887                 :             :  *        aggregation is applicable and the resulting grouped paths are considered
     888                 :             :  *        useful.
     889                 :             :  *
     890                 :             :  * There are two strategies for generating grouped paths for a join relation:
     891                 :             :  *
     892                 :             :  * 1. Join a grouped (partially aggregated) input relation with a non-grouped
     893                 :             :  * input (e.g., AGG(B) JOIN A).
     894                 :             :  *
     895                 :             :  * 2. Apply partial aggregation (sorted or hashed) on top of existing
     896                 :             :  * non-grouped join paths (e.g., AGG(A JOIN B)).
     897                 :             :  *
     898                 :             :  * To limit planning effort and avoid an explosion of alternatives, we adopt a
     899                 :             :  * strategy where partial aggregation is only pushed to the lowest possible
     900                 :             :  * level in the join tree that is deemed useful.  That is, if grouped paths can
     901                 :             :  * be built using the first strategy, we skip consideration of the second
     902                 :             :  * strategy for the same join level.
     903                 :             :  *
     904                 :             :  * Additionally, if there are multiple lowest useful levels where partial
     905                 :             :  * aggregation could be applied, such as in a join tree with relations A, B,
     906                 :             :  * and C where both "AGG(A JOIN B) JOIN C" and "A JOIN AGG(B JOIN C)" are valid
     907                 :             :  * placements, we choose only the first one encountered during join search.
     908                 :             :  * This avoids generating multiple versions of the same grouped relation based
     909                 :             :  * on different aggregation placements.
     910                 :             :  *
     911                 :             :  * These heuristics also ensure that all grouped paths for the same grouped
     912                 :             :  * relation produce the same set of rows, which is a basic assumption in the
     913                 :             :  * planner.
     914                 :             :  */
     915                 :             : static void
     916                 :       29828 : make_grouped_join_rel(PlannerInfo *root, RelOptInfo *rel1,
     917                 :             :                                           RelOptInfo *rel2, RelOptInfo *joinrel,
     918                 :             :                                           SpecialJoinInfo *sjinfo, List *restrictlist)
     919                 :             : {
     920                 :       29828 :         RelOptInfo *grouped_rel;
     921                 :       29828 :         RelOptInfo *grouped_rel1;
     922                 :       29828 :         RelOptInfo *grouped_rel2;
     923                 :       29828 :         bool            rel1_empty;
     924                 :       29828 :         bool            rel2_empty;
     925                 :       29828 :         Relids          apply_agg_at;
     926                 :             : 
     927                 :             :         /*
     928                 :             :          * If there are no aggregate expressions or grouping expressions, eager
     929                 :             :          * aggregation is not possible.
     930                 :             :          */
     931   [ +  +  +  + ]:       29828 :         if (root->agg_clause_list == NIL ||
     932                 :        3099 :                 root->group_expr_list == NIL)
     933                 :       26744 :                 return;
     934                 :             : 
     935                 :             :         /* Retrieve the grouped relations for the two input rels */
     936                 :        3084 :         grouped_rel1 = rel1->grouped_rel;
     937                 :        3084 :         grouped_rel2 = rel2->grouped_rel;
     938                 :             : 
     939         [ +  + ]:        3084 :         rel1_empty = (grouped_rel1 == NULL || IS_DUMMY_REL(grouped_rel1));
     940         [ +  + ]:        3084 :         rel2_empty = (grouped_rel2 == NULL || IS_DUMMY_REL(grouped_rel2));
     941                 :             : 
     942                 :             :         /* Find or construct a grouped joinrel for this joinrel */
     943                 :        3084 :         grouped_rel = joinrel->grouped_rel;
     944         [ +  + ]:        3084 :         if (grouped_rel == NULL)
     945                 :             :         {
     946                 :        2988 :                 RelAggInfo *agg_info = NULL;
     947                 :             : 
     948                 :             :                 /*
     949                 :             :                  * Prepare the information needed to create grouped paths for this
     950                 :             :                  * join relation.
     951                 :             :                  */
     952                 :        2988 :                 agg_info = create_rel_agg_info(root, joinrel, rel1_empty == rel2_empty);
     953         [ +  + ]:        2988 :                 if (agg_info == NULL)
     954                 :         140 :                         return;
     955                 :             : 
     956                 :             :                 /*
     957                 :             :                  * If grouped paths for the given join relation are not considered
     958                 :             :                  * useful, and no grouped paths can be built by joining grouped input
     959                 :             :                  * relations, skip building the grouped join relation.
     960                 :             :                  */
     961   [ +  +  +  + ]:        2848 :                 if (!agg_info->agg_useful &&
     962                 :        2738 :                         (rel1_empty == rel2_empty))
     963                 :          37 :                         return;
     964                 :             : 
     965                 :             :                 /* build the grouped relation */
     966                 :        2811 :                 grouped_rel = build_grouped_rel(root, joinrel);
     967                 :        2811 :                 grouped_rel->reltarget = agg_info->target;
     968                 :             : 
     969         [ +  + ]:        2811 :                 if (rel1_empty != rel2_empty)
     970                 :             :                 {
     971                 :             :                         /*
     972                 :             :                          * If there is exactly one grouped input relation, then we can
     973                 :             :                          * build grouped paths by joining the input relations.  Set size
     974                 :             :                          * estimates for the grouped join relation based on the input
     975                 :             :                          * relations, and update the set of relids where partial
     976                 :             :                          * aggregation is applied to that of the grouped input relation.
     977                 :             :                          */
     978                 :        5402 :                         set_joinrel_size_estimates(root, grouped_rel,
     979         [ +  + ]:        2701 :                                                                            rel1_empty ? rel1 : grouped_rel1,
     980         [ +  + ]:        2701 :                                                                            rel2_empty ? rel2 : grouped_rel2,
     981                 :        2701 :                                                                            sjinfo, restrictlist);
     982         [ +  + ]:        2701 :                         agg_info->apply_agg_at = rel1_empty ?
     983                 :        1363 :                                 grouped_rel2->agg_info->apply_agg_at :
     984                 :        1338 :                                 grouped_rel1->agg_info->apply_agg_at;
     985                 :        2701 :                 }
     986                 :             :                 else
     987                 :             :                 {
     988                 :             :                         /*
     989                 :             :                          * Otherwise, grouped paths can be built by applying partial
     990                 :             :                          * aggregation on top of existing non-grouped join paths.  Set
     991                 :             :                          * size estimates for the grouped join relation based on the
     992                 :             :                          * estimated number of groups, and track the set of relids where
     993                 :             :                          * partial aggregation is applied.  Note that these values may be
     994                 :             :                          * updated later if it is determined that grouped paths can be
     995                 :             :                          * constructed by joining other input relations.
     996                 :             :                          */
     997                 :         110 :                         grouped_rel->rows = agg_info->grouped_rows;
     998                 :         110 :                         agg_info->apply_agg_at = bms_copy(joinrel->relids);
     999                 :             :                 }
    1000                 :             : 
    1001                 :        2811 :                 grouped_rel->agg_info = agg_info;
    1002                 :        2811 :                 joinrel->grouped_rel = grouped_rel;
    1003         [ +  + ]:        2988 :         }
    1004                 :             : 
    1005         [ +  - ]:        2907 :         Assert(IS_GROUPED_REL(grouped_rel));
    1006                 :             : 
    1007                 :             :         /* We may have already proven this grouped join relation to be dummy. */
    1008         [ -  + ]:        2907 :         if (IS_DUMMY_REL(grouped_rel))
    1009                 :           0 :                 return;
    1010                 :             : 
    1011                 :             :         /*
    1012                 :             :          * Nothing to do if there's no grouped input relation.  Also, joining two
    1013                 :             :          * grouped relations is not currently supported.
    1014                 :             :          */
    1015         [ +  + ]:        2907 :         if (rel1_empty == rel2_empty)
    1016                 :         158 :                 return;
    1017                 :             : 
    1018                 :             :         /*
    1019                 :             :          * Get the set of relids where partial aggregation is applied among the
    1020                 :             :          * given input relations.
    1021                 :             :          */
    1022         [ +  + ]:        2749 :         apply_agg_at = rel1_empty ?
    1023                 :        1363 :                 grouped_rel2->agg_info->apply_agg_at :
    1024                 :        1386 :                 grouped_rel1->agg_info->apply_agg_at;
    1025                 :             : 
    1026                 :             :         /*
    1027                 :             :          * If it's not the designated level, skip building grouped paths.
    1028                 :             :          *
    1029                 :             :          * One exception is when it is a subset of the previously recorded level.
    1030                 :             :          * In that case, we need to update the designated level to this one, and
    1031                 :             :          * adjust the size estimates for the grouped join relation accordingly.
    1032                 :             :          * For example, suppose partial aggregation can be applied on top of (B
    1033                 :             :          * JOIN C).  If we first construct the join as ((A JOIN B) JOIN C), we'd
    1034                 :             :          * record the designated level as including all three relations (A B C).
    1035                 :             :          * Later, when we consider (A JOIN (B JOIN C)), we encounter the smaller
    1036                 :             :          * (B C) join level directly.  Since this is a subset of the previous
    1037                 :             :          * level and still valid for partial aggregation, we update the designated
    1038                 :             :          * level to (B C), and adjust the size estimates accordingly.
    1039                 :             :          */
    1040         [ +  + ]:        2749 :         if (!bms_equal(apply_agg_at, grouped_rel->agg_info->apply_agg_at))
    1041                 :             :         {
    1042         [ +  - ]:          48 :                 if (bms_is_subset(apply_agg_at, grouped_rel->agg_info->apply_agg_at))
    1043                 :             :                 {
    1044                 :             :                         /* Adjust the size estimates for the grouped join relation. */
    1045                 :          96 :                         set_joinrel_size_estimates(root, grouped_rel,
    1046         [ -  + ]:          48 :                                                                            rel1_empty ? rel1 : grouped_rel1,
    1047         [ +  - ]:          48 :                                                                            rel2_empty ? rel2 : grouped_rel2,
    1048                 :          48 :                                                                            sjinfo, restrictlist);
    1049                 :          48 :                         grouped_rel->agg_info->apply_agg_at = apply_agg_at;
    1050                 :          48 :                 }
    1051                 :             :                 else
    1052                 :           0 :                         return;
    1053                 :          48 :         }
    1054                 :             : 
    1055                 :             :         /* Make paths for the grouped join relation. */
    1056                 :        5498 :         populate_joinrel_with_paths(root,
    1057         [ +  + ]:        2749 :                                                                 rel1_empty ? rel1 : grouped_rel1,
    1058         [ +  + ]:        2749 :                                                                 rel2_empty ? rel2 : grouped_rel2,
    1059                 :        2749 :                                                                 grouped_rel,
    1060                 :        2749 :                                                                 sjinfo,
    1061                 :        2749 :                                                                 restrictlist);
    1062         [ -  + ]:       29828 : }
    1063                 :             : 
    1064                 :             : /*
    1065                 :             :  * populate_joinrel_with_paths
    1066                 :             :  *        Add paths to the given joinrel for given pair of joining relations. The
    1067                 :             :  *        SpecialJoinInfo provides details about the join and the restrictlist
    1068                 :             :  *        contains the join clauses and the other clauses applicable for given pair
    1069                 :             :  *        of the joining relations.
    1070                 :             :  */
    1071                 :             : static void
    1072                 :       32577 : populate_joinrel_with_paths(PlannerInfo *root, RelOptInfo *rel1,
    1073                 :             :                                                         RelOptInfo *rel2, RelOptInfo *joinrel,
    1074                 :             :                                                         SpecialJoinInfo *sjinfo, List *restrictlist)
    1075                 :             : {
    1076                 :       32577 :         RelOptInfo *unique_rel2;
    1077                 :             : 
    1078                 :             :         /*
    1079                 :             :          * Consider paths using each rel as both outer and inner.  Depending on
    1080                 :             :          * the join type, a provably empty outer or inner rel might mean the join
    1081                 :             :          * is provably empty too; in which case throw away any previously computed
    1082                 :             :          * paths and mark the join as dummy.  (We do it this way since it's
    1083                 :             :          * conceivable that dummy-ness of a multi-element join might only be
    1084                 :             :          * noticeable for certain construction paths.)
    1085                 :             :          *
    1086                 :             :          * Also, a provably constant-false join restriction typically means that
    1087                 :             :          * we can skip evaluating one or both sides of the join.  We do this by
    1088                 :             :          * marking the appropriate rel as dummy.  For outer joins, a
    1089                 :             :          * constant-false restriction that is pushed down still means the whole
    1090                 :             :          * join is dummy, while a non-pushed-down one means that no inner rows
    1091                 :             :          * will join so we can treat the inner rel as dummy.
    1092                 :             :          *
    1093                 :             :          * We need only consider the jointypes that appear in join_info_list, plus
    1094                 :             :          * JOIN_INNER.
    1095                 :             :          */
    1096   [ +  +  +  +  :       32577 :         switch (sjinfo->jointype)
                   +  - ]
    1097                 :             :         {
    1098                 :             :                 case JOIN_INNER:
    1099   [ +  +  +  +  :       25093 :                         if (is_dummy_rel(rel1) || is_dummy_rel(rel2) ||
                   +  + ]
    1100                 :       25088 :                                 restriction_is_constant_false(restrictlist, joinrel, false))
    1101                 :             :                         {
    1102                 :          36 :                                 mark_dummy_rel(joinrel);
    1103                 :          36 :                                 break;
    1104                 :             :                         }
    1105                 :       50114 :                         add_paths_to_joinrel(root, joinrel, rel1, rel2,
    1106                 :       25057 :                                                                  JOIN_INNER, sjinfo,
    1107                 :       25057 :                                                                  restrictlist);
    1108                 :       50114 :                         add_paths_to_joinrel(root, joinrel, rel2, rel1,
    1109                 :       25057 :                                                                  JOIN_INNER, sjinfo,
    1110                 :       25057 :                                                                  restrictlist);
    1111                 :       25057 :                         break;
    1112                 :             :                 case JOIN_LEFT:
    1113   [ +  +  +  + ]:        5644 :                         if (is_dummy_rel(rel1) ||
    1114                 :        5635 :                                 restriction_is_constant_false(restrictlist, joinrel, true))
    1115                 :             :                         {
    1116                 :          13 :                                 mark_dummy_rel(joinrel);
    1117                 :          13 :                                 break;
    1118                 :             :                         }
    1119   [ +  +  +  + ]:        5631 :                         if (restriction_is_constant_false(restrictlist, joinrel, false) &&
    1120                 :          29 :                                 bms_is_subset(rel2->relids, sjinfo->syn_righthand))
    1121                 :          25 :                                 mark_dummy_rel(rel2);
    1122                 :       11262 :                         add_paths_to_joinrel(root, joinrel, rel1, rel2,
    1123                 :        5631 :                                                                  JOIN_LEFT, sjinfo,
    1124                 :        5631 :                                                                  restrictlist);
    1125                 :       11262 :                         add_paths_to_joinrel(root, joinrel, rel2, rel1,
    1126                 :        5631 :                                                                  JOIN_RIGHT, sjinfo,
    1127                 :        5631 :                                                                  restrictlist);
    1128                 :        5631 :                         break;
    1129                 :             :                 case JOIN_FULL:
    1130   [ -  +  +  + ]:         256 :                         if ((is_dummy_rel(rel1) && is_dummy_rel(rel2)) ||
    1131                 :         256 :                                 restriction_is_constant_false(restrictlist, joinrel, true))
    1132                 :             :                         {
    1133                 :           2 :                                 mark_dummy_rel(joinrel);
    1134                 :           2 :                                 break;
    1135                 :             :                         }
    1136                 :         508 :                         add_paths_to_joinrel(root, joinrel, rel1, rel2,
    1137                 :         254 :                                                                  JOIN_FULL, sjinfo,
    1138                 :         254 :                                                                  restrictlist);
    1139                 :         508 :                         add_paths_to_joinrel(root, joinrel, rel2, rel1,
    1140                 :         254 :                                                                  JOIN_FULL, sjinfo,
    1141                 :         254 :                                                                  restrictlist);
    1142                 :             : 
    1143                 :             :                         /*
    1144                 :             :                          * If there are join quals that aren't mergeable or hashable, we
    1145                 :             :                          * may not be able to build any valid plan.  Complain here so that
    1146                 :             :                          * we can give a somewhat-useful error message.  (Since we have no
    1147                 :             :                          * flexibility of planning for a full join, there's no chance of
    1148                 :             :                          * succeeding later with another pair of input rels.)
    1149                 :             :                          */
    1150         [ +  - ]:         254 :                         if (joinrel->pathlist == NIL)
    1151   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
    1152                 :             :                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1153                 :             :                                                  errmsg("FULL JOIN is only supported with merge-joinable or hash-joinable join conditions")));
    1154                 :         254 :                         break;
    1155                 :             :                 case JOIN_SEMI:
    1156                 :             : 
    1157                 :             :                         /*
    1158                 :             :                          * We might have a normal semijoin, or a case where we don't have
    1159                 :             :                          * enough rels to do the semijoin but can unique-ify the RHS and
    1160                 :             :                          * then do an innerjoin (see comments in join_is_legal).  In the
    1161                 :             :                          * latter case we can't apply JOIN_SEMI joining.
    1162                 :             :                          */
    1163   [ +  +  -  + ]:        1091 :                         if (bms_is_subset(sjinfo->min_lefthand, rel1->relids) &&
    1164                 :        1044 :                                 bms_is_subset(sjinfo->min_righthand, rel2->relids))
    1165                 :             :                         {
    1166   [ +  +  +  -  :        1044 :                                 if (is_dummy_rel(rel1) || is_dummy_rel(rel2) ||
                   +  + ]
    1167                 :        1043 :                                         restriction_is_constant_false(restrictlist, joinrel, false))
    1168                 :             :                                 {
    1169                 :           2 :                                         mark_dummy_rel(joinrel);
    1170                 :           2 :                                         break;
    1171                 :             :                                 }
    1172                 :        2084 :                                 add_paths_to_joinrel(root, joinrel, rel1, rel2,
    1173                 :        1042 :                                                                          JOIN_SEMI, sjinfo,
    1174                 :        1042 :                                                                          restrictlist);
    1175                 :        2084 :                                 add_paths_to_joinrel(root, joinrel, rel2, rel1,
    1176                 :        1042 :                                                                          JOIN_RIGHT_SEMI, sjinfo,
    1177                 :        1042 :                                                                          restrictlist);
    1178                 :        1042 :                         }
    1179                 :             : 
    1180                 :             :                         /*
    1181                 :             :                          * If we know how to unique-ify the RHS and one input rel is
    1182                 :             :                          * exactly the RHS (not a superset) we can consider unique-ifying
    1183                 :             :                          * it and then doing a regular join.  (The create_unique_paths
    1184                 :             :                          * check here is probably redundant with what join_is_legal did,
    1185                 :             :                          * but if so the check is cheap because it's cached.  So test
    1186                 :             :                          * anyway to be sure.)
    1187                 :             :                          */
    1188   [ +  -  +  + ]:        1089 :                         if (bms_equal(sjinfo->syn_righthand, rel2->relids) &&
    1189                 :        1089 :                                 (unique_rel2 = create_unique_paths(root, rel2, sjinfo)) != NULL)
    1190                 :             :                         {
    1191   [ +  -  +  -  :         801 :                                 if (is_dummy_rel(rel1) || is_dummy_rel(rel2) ||
                   -  + ]
    1192                 :         801 :                                         restriction_is_constant_false(restrictlist, joinrel, false))
    1193                 :             :                                 {
    1194                 :           0 :                                         mark_dummy_rel(joinrel);
    1195                 :           0 :                                         break;
    1196                 :             :                                 }
    1197                 :        1602 :                                 add_paths_to_joinrel(root, joinrel, rel1, unique_rel2,
    1198                 :         801 :                                                                          JOIN_UNIQUE_INNER, sjinfo,
    1199                 :         801 :                                                                          restrictlist);
    1200                 :        1602 :                                 add_paths_to_joinrel(root, joinrel, unique_rel2, rel1,
    1201                 :         801 :                                                                          JOIN_UNIQUE_OUTER, sjinfo,
    1202                 :         801 :                                                                          restrictlist);
    1203                 :         801 :                         }
    1204                 :        1089 :                         break;
    1205                 :             :                 case JOIN_ANTI:
    1206   [ +  -  -  + ]:         493 :                         if (is_dummy_rel(rel1) ||
    1207                 :         493 :                                 restriction_is_constant_false(restrictlist, joinrel, true))
    1208                 :             :                         {
    1209                 :           0 :                                 mark_dummy_rel(joinrel);
    1210                 :           0 :                                 break;
    1211                 :             :                         }
    1212   [ -  +  #  # ]:         493 :                         if (restriction_is_constant_false(restrictlist, joinrel, false) &&
    1213                 :           0 :                                 bms_is_subset(rel2->relids, sjinfo->syn_righthand))
    1214                 :           0 :                                 mark_dummy_rel(rel2);
    1215                 :         986 :                         add_paths_to_joinrel(root, joinrel, rel1, rel2,
    1216                 :         493 :                                                                  JOIN_ANTI, sjinfo,
    1217                 :         493 :                                                                  restrictlist);
    1218                 :         986 :                         add_paths_to_joinrel(root, joinrel, rel2, rel1,
    1219                 :         493 :                                                                  JOIN_RIGHT_ANTI, sjinfo,
    1220                 :         493 :                                                                  restrictlist);
    1221                 :         493 :                         break;
    1222                 :             :                 default:
    1223                 :             :                         /* other values not expected here */
    1224   [ #  #  #  # ]:           0 :                         elog(ERROR, "unrecognized join type: %d", (int) sjinfo->jointype);
    1225                 :           0 :                         break;
    1226                 :             :         }
    1227                 :             : 
    1228                 :             :         /* Apply partitionwise join technique, if possible. */
    1229                 :       32577 :         try_partitionwise_join(root, rel1, rel2, joinrel, sjinfo, restrictlist);
    1230                 :       32577 : }
    1231                 :             : 
    1232                 :             : 
    1233                 :             : /*
    1234                 :             :  * have_join_order_restriction
    1235                 :             :  *              Detect whether the two relations should be joined to satisfy
    1236                 :             :  *              a join-order restriction arising from special or lateral joins.
    1237                 :             :  *
    1238                 :             :  * In practice this is always used with have_relevant_joinclause(), and so
    1239                 :             :  * could be merged with that function, but it seems clearer to separate the
    1240                 :             :  * two concerns.  We need this test because there are degenerate cases where
    1241                 :             :  * a clauseless join must be performed to satisfy join-order restrictions.
    1242                 :             :  * Also, if one rel has a lateral reference to the other, or both are needed
    1243                 :             :  * to compute some PHV, we should consider joining them even if the join would
    1244                 :             :  * be clauseless.
    1245                 :             :  *
    1246                 :             :  * Note: this is only a problem if one side of a degenerate outer join
    1247                 :             :  * contains multiple rels, or a clauseless join is required within an
    1248                 :             :  * IN/EXISTS RHS; else we will find a join path via the "last ditch" case in
    1249                 :             :  * join_search_one_level().  We could dispense with this test if we were
    1250                 :             :  * willing to try bushy plans in the "last ditch" case, but that seems much
    1251                 :             :  * less efficient.
    1252                 :             :  */
    1253                 :             : bool
    1254                 :        5676 : have_join_order_restriction(PlannerInfo *root,
    1255                 :             :                                                         RelOptInfo *rel1, RelOptInfo *rel2)
    1256                 :             : {
    1257                 :        5676 :         bool            result = false;
    1258                 :        5676 :         ListCell   *l;
    1259                 :             : 
    1260                 :             :         /*
    1261                 :             :          * If either side has a direct lateral reference to the other, attempt the
    1262                 :             :          * join regardless of outer-join considerations.
    1263                 :             :          */
    1264   [ +  +  +  + ]:        5676 :         if (bms_overlap(rel1->relids, rel2->direct_lateral_relids) ||
    1265                 :        5336 :                 bms_overlap(rel2->relids, rel1->direct_lateral_relids))
    1266                 :         435 :                 return true;
    1267                 :             : 
    1268                 :             :         /*
    1269                 :             :          * Likewise, if both rels are needed to compute some PlaceHolderVar,
    1270                 :             :          * attempt the join regardless of outer-join considerations.  (This is not
    1271                 :             :          * very desirable, because a PHV with a large eval_at set will cause a lot
    1272                 :             :          * of probably-useless joins to be considered, but failing to do this can
    1273                 :             :          * cause us to fail to construct a plan at all.)
    1274                 :             :          */
    1275   [ +  +  +  +  :        5562 :         foreach(l, root->placeholder_list)
             +  +  +  + ]
    1276                 :             :         {
    1277                 :         321 :                 PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(l);
    1278                 :             : 
    1279   [ +  +  +  + ]:         321 :                 if (bms_is_subset(rel1->relids, phinfo->ph_eval_at) &&
    1280                 :          65 :                         bms_is_subset(rel2->relids, phinfo->ph_eval_at))
    1281                 :          10 :                         return true;
    1282         [ +  + ]:         321 :         }
    1283                 :             : 
    1284                 :             :         /*
    1285                 :             :          * It's possible that the rels correspond to the left and right sides of a
    1286                 :             :          * degenerate outer join, that is, one with no joinclause mentioning the
    1287                 :             :          * non-nullable side; in which case we should force the join to occur.
    1288                 :             :          *
    1289                 :             :          * Also, the two rels could represent a clauseless join that has to be
    1290                 :             :          * completed to build up the LHS or RHS of an outer join.
    1291                 :             :          */
    1292   [ +  +  +  +  :       13137 :         foreach(l, root->join_info_list)
                   +  + ]
    1293                 :             :         {
    1294                 :        7906 :                 SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(l);
    1295                 :             : 
    1296                 :             :                 /* ignore full joins --- other mechanisms handle them */
    1297         [ +  + ]:        7906 :                 if (sjinfo->jointype == JOIN_FULL)
    1298                 :           7 :                         continue;
    1299                 :             : 
    1300                 :             :                 /* Can we perform the SJ with these rels? */
    1301   [ +  +  +  + ]:        7899 :                 if (bms_is_subset(sjinfo->min_lefthand, rel1->relids) &&
    1302                 :        1863 :                         bms_is_subset(sjinfo->min_righthand, rel2->relids))
    1303                 :             :                 {
    1304                 :         101 :                         result = true;
    1305                 :         101 :                         break;
    1306                 :             :                 }
    1307   [ +  +  +  + ]:        7798 :                 if (bms_is_subset(sjinfo->min_lefthand, rel2->relids) &&
    1308                 :         580 :                         bms_is_subset(sjinfo->min_righthand, rel1->relids))
    1309                 :             :                 {
    1310                 :          35 :                         result = true;
    1311                 :          35 :                         break;
    1312                 :             :                 }
    1313                 :             : 
    1314                 :             :                 /*
    1315                 :             :                  * Might we need to join these rels to complete the RHS?  We have to
    1316                 :             :                  * use "overlap" tests since either rel might include a lower SJ that
    1317                 :             :                  * has been proven to commute with this one.
    1318                 :             :                  */
    1319   [ +  +  +  + ]:        7763 :                 if (bms_overlap(sjinfo->min_righthand, rel1->relids) &&
    1320                 :        1764 :                         bms_overlap(sjinfo->min_righthand, rel2->relids))
    1321                 :             :                 {
    1322                 :          20 :                         result = true;
    1323                 :          20 :                         break;
    1324                 :             :                 }
    1325                 :             : 
    1326                 :             :                 /* Likewise for the LHS. */
    1327   [ +  +  +  + ]:        7743 :                 if (bms_overlap(sjinfo->min_lefthand, rel1->relids) &&
    1328                 :        2246 :                         bms_overlap(sjinfo->min_lefthand, rel2->relids))
    1329                 :             :                 {
    1330                 :          12 :                         result = true;
    1331                 :          12 :                         break;
    1332                 :             :                 }
    1333      [ +  +  + ]:        7906 :         }
    1334                 :             : 
    1335                 :             :         /*
    1336                 :             :          * We do not force the join to occur if either input rel can legally be
    1337                 :             :          * joined to anything else using joinclauses.  This essentially means that
    1338                 :             :          * clauseless bushy joins are put off as long as possible. The reason is
    1339                 :             :          * that when there is a join order restriction high up in the join tree
    1340                 :             :          * (that is, with many rels inside the LHS or RHS), we would otherwise
    1341                 :             :          * expend lots of effort considering very stupid join combinations within
    1342                 :             :          * its LHS or RHS.
    1343                 :             :          */
    1344         [ +  + ]:        5231 :         if (result)
    1345                 :             :         {
    1346   [ +  +  +  + ]:         168 :                 if (has_legal_joinclause(root, rel1) ||
    1347                 :         145 :                         has_legal_joinclause(root, rel2))
    1348                 :          42 :                         result = false;
    1349                 :         168 :         }
    1350                 :             : 
    1351                 :        5231 :         return result;
    1352                 :        5676 : }
    1353                 :             : 
    1354                 :             : 
    1355                 :             : /*
    1356                 :             :  * has_join_restriction
    1357                 :             :  *              Detect whether the specified relation has join-order restrictions,
    1358                 :             :  *              due to being inside an outer join or an IN (sub-SELECT),
    1359                 :             :  *              or participating in any LATERAL references or multi-rel PHVs.
    1360                 :             :  *
    1361                 :             :  * Essentially, this tests whether have_join_order_restriction() could
    1362                 :             :  * succeed with this rel and some other one.  It's OK if we sometimes
    1363                 :             :  * say "true" incorrectly.  (Therefore, we don't bother with the relatively
    1364                 :             :  * expensive has_legal_joinclause test.)
    1365                 :             :  */
    1366                 :             : static bool
    1367                 :        2442 : has_join_restriction(PlannerInfo *root, RelOptInfo *rel)
    1368                 :             : {
    1369                 :        2442 :         ListCell   *l;
    1370                 :             : 
    1371   [ +  +  +  + ]:        2442 :         if (rel->lateral_relids != NULL || rel->lateral_referencers != NULL)
    1372                 :         464 :                 return true;
    1373                 :             : 
    1374   [ +  +  +  +  :        2126 :         foreach(l, root->placeholder_list)
             +  +  +  + ]
    1375                 :             :         {
    1376                 :         148 :                 PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(l);
    1377                 :             : 
    1378   [ +  +  +  + ]:         148 :                 if (bms_is_subset(rel->relids, phinfo->ph_eval_at) &&
    1379                 :          38 :                         !bms_equal(rel->relids, phinfo->ph_eval_at))
    1380                 :           8 :                         return true;
    1381         [ +  + ]:         148 :         }
    1382                 :             : 
    1383   [ +  +  +  +  :        2302 :         foreach(l, root->join_info_list)
             +  +  +  + ]
    1384                 :             :         {
    1385                 :         332 :                 SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(l);
    1386                 :             : 
    1387                 :             :                 /* ignore full joins --- other mechanisms preserve their ordering */
    1388         [ +  + ]:         332 :                 if (sjinfo->jointype == JOIN_FULL)
    1389                 :          11 :                         continue;
    1390                 :             : 
    1391                 :             :                 /* ignore if SJ is already contained in rel */
    1392   [ +  +  +  + ]:         321 :                 if (bms_is_subset(sjinfo->min_lefthand, rel->relids) &&
    1393                 :         181 :                         bms_is_subset(sjinfo->min_righthand, rel->relids))
    1394                 :          63 :                         continue;
    1395                 :             : 
    1396                 :             :                 /* restricted if it overlaps LHS or RHS, but doesn't contain SJ */
    1397   [ +  +  +  + ]:         258 :                 if (bms_overlap(sjinfo->min_lefthand, rel->relids) ||
    1398                 :         136 :                         bms_overlap(sjinfo->min_righthand, rel->relids))
    1399                 :         203 :                         return true;
    1400      [ +  +  + ]:         332 :         }
    1401                 :             : 
    1402                 :        1767 :         return false;
    1403                 :        2442 : }
    1404                 :             : 
    1405                 :             : 
    1406                 :             : /*
    1407                 :             :  * has_legal_joinclause
    1408                 :             :  *              Detect whether the specified relation can legally be joined
    1409                 :             :  *              to any other rels using join clauses.
    1410                 :             :  *
    1411                 :             :  * We consider only joins to single other relations in the current
    1412                 :             :  * initial_rels list.  This is sufficient to get a "true" result in most real
    1413                 :             :  * queries, and an occasional erroneous "false" will only cost a bit more
    1414                 :             :  * planning time.  The reason for this limitation is that considering joins to
    1415                 :             :  * other joins would require proving that the other join rel can legally be
    1416                 :             :  * formed, which seems like too much trouble for something that's only a
    1417                 :             :  * heuristic to save planning time.  (Note: we must look at initial_rels
    1418                 :             :  * and not all of the query, since when we are planning a sub-joinlist we
    1419                 :             :  * may be forced to make clauseless joins within initial_rels even though
    1420                 :             :  * there are join clauses linking to other parts of the query.)
    1421                 :             :  */
    1422                 :             : static bool
    1423                 :         313 : has_legal_joinclause(PlannerInfo *root, RelOptInfo *rel)
    1424                 :             : {
    1425                 :         313 :         ListCell   *lc;
    1426                 :             : 
    1427   [ +  -  +  +  :        1311 :         foreach(lc, root->initial_rels)
             +  +  +  + ]
    1428                 :             :         {
    1429                 :         998 :                 RelOptInfo *rel2 = (RelOptInfo *) lfirst(lc);
    1430                 :             : 
    1431                 :             :                 /* ignore rels that are already in "rel" */
    1432         [ +  + ]:         998 :                 if (bms_overlap(rel->relids, rel2->relids))
    1433                 :         396 :                         continue;
    1434                 :             : 
    1435         [ +  + ]:         602 :                 if (have_relevant_joinclause(root, rel, rel2))
    1436                 :             :                 {
    1437                 :          76 :                         Relids          joinrelids;
    1438                 :          76 :                         SpecialJoinInfo *sjinfo;
    1439                 :          76 :                         bool            reversed;
    1440                 :             : 
    1441                 :             :                         /* join_is_legal needs relids of the union */
    1442                 :          76 :                         joinrelids = bms_union(rel->relids, rel2->relids);
    1443                 :             : 
    1444         [ +  + ]:          76 :                         if (join_is_legal(root, rel, rel2, joinrelids,
    1445                 :             :                                                           &sjinfo, &reversed))
    1446                 :             :                         {
    1447                 :             :                                 /* Yes, this will work */
    1448                 :          42 :                                 bms_free(joinrelids);
    1449                 :          42 :                                 return true;
    1450                 :             :                         }
    1451                 :             : 
    1452                 :          34 :                         bms_free(joinrelids);
    1453         [ +  + ]:          76 :                 }
    1454      [ +  +  + ]:         998 :         }
    1455                 :             : 
    1456                 :         271 :         return false;
    1457                 :         313 : }
    1458                 :             : 
    1459                 :             : 
    1460                 :             : /*
    1461                 :             :  * is_dummy_rel --- has relation been proven empty?
    1462                 :             :  */
    1463                 :             : bool
    1464                 :      303373 : is_dummy_rel(RelOptInfo *rel)
    1465                 :             : {
    1466                 :      303373 :         Path       *path;
    1467                 :             : 
    1468                 :             :         /*
    1469                 :             :          * A rel that is known dummy will have just one path that is a childless
    1470                 :             :          * Append.  (Even if somehow it has more paths, a childless Append will
    1471                 :             :          * have cost zero and hence should be at the front of the pathlist.)
    1472                 :             :          */
    1473         [ +  + ]:      303373 :         if (rel->pathlist == NIL)
    1474                 :      152967 :                 return false;
    1475                 :      150406 :         path = (Path *) linitial(rel->pathlist);
    1476                 :             : 
    1477                 :             :         /*
    1478                 :             :          * Initially, a dummy path will just be a childless Append.  But in later
    1479                 :             :          * planning stages we might stick a ProjectSetPath and/or ProjectionPath
    1480                 :             :          * on top, since Append can't project.  Rather than make assumptions about
    1481                 :             :          * which combinations can occur, just descend through whatever we find.
    1482                 :             :          */
    1483                 :      159836 :         for (;;)
    1484                 :             :         {
    1485         [ +  + ]:      159836 :                 if (IsA(path, ProjectionPath))
    1486                 :        8242 :                         path = ((ProjectionPath *) path)->subpath;
    1487         [ +  + ]:      151594 :                 else if (IsA(path, ProjectSetPath))
    1488                 :        1188 :                         path = ((ProjectSetPath *) path)->subpath;
    1489                 :             :                 else
    1490                 :      150406 :                         break;
    1491                 :             :         }
    1492   [ +  +  +  + ]:      150406 :         if (IS_DUMMY_APPEND(path))
    1493                 :         931 :                 return true;
    1494                 :      149475 :         return false;
    1495                 :      303373 : }
    1496                 :             : 
    1497                 :             : /*
    1498                 :             :  * Mark a relation as proven empty.
    1499                 :             :  *
    1500                 :             :  * During GEQO planning, this can get invoked more than once on the same
    1501                 :             :  * baserel struct, so it's worth checking to see if the rel is already marked
    1502                 :             :  * dummy.
    1503                 :             :  *
    1504                 :             :  * Also, when called during GEQO join planning, we are in a short-lived
    1505                 :             :  * memory context.  We must make sure that the dummy path attached to a
    1506                 :             :  * baserel survives the GEQO cycle, else the baserel is trashed for future
    1507                 :             :  * GEQO cycles.  On the other hand, when we are marking a joinrel during GEQO,
    1508                 :             :  * we don't want the dummy path to clutter the main planning context.  Upshot
    1509                 :             :  * is that the best solution is to explicitly make the dummy path in the same
    1510                 :             :  * context the given RelOptInfo is in.
    1511                 :             :  */
    1512                 :             : void
    1513                 :         110 : mark_dummy_rel(RelOptInfo *rel)
    1514                 :             : {
    1515                 :         110 :         MemoryContext oldcontext;
    1516                 :         110 :         AppendPathInput in = {0};
    1517                 :             : 
    1518                 :             :         /* Already marked? */
    1519         [ +  + ]:         110 :         if (is_dummy_rel(rel))
    1520                 :           3 :                 return;
    1521                 :             : 
    1522                 :             :         /* No, so choose correct context to make the dummy path in */
    1523                 :         107 :         oldcontext = MemoryContextSwitchTo(GetMemoryChunkContext(rel));
    1524                 :             : 
    1525                 :             :         /* Set dummy size estimate */
    1526                 :         107 :         rel->rows = 0;
    1527                 :             : 
    1528                 :             :         /* Evict any previously chosen paths */
    1529                 :         107 :         rel->pathlist = NIL;
    1530                 :         107 :         rel->partial_pathlist = NIL;
    1531                 :             : 
    1532                 :             :         /* Set up the dummy path */
    1533                 :         214 :         add_path(rel, (Path *) create_append_path(NULL, rel, in,
    1534                 :         107 :                                                                                           NIL, rel->lateral_relids,
    1535                 :             :                                                                                           0, false, -1));
    1536                 :             : 
    1537                 :             :         /* Set or update cheapest_total_path and related fields */
    1538                 :         107 :         set_cheapest(rel);
    1539                 :             : 
    1540                 :         107 :         MemoryContextSwitchTo(oldcontext);
    1541         [ -  + ]:         110 : }
    1542                 :             : 
    1543                 :             : 
    1544                 :             : /*
    1545                 :             :  * restriction_is_constant_false --- is a restrictlist just FALSE?
    1546                 :             :  *
    1547                 :             :  * In cases where a qual is provably constant FALSE, eval_const_expressions
    1548                 :             :  * will generally have thrown away anything that's ANDed with it.  In outer
    1549                 :             :  * join situations this will leave us computing cartesian products only to
    1550                 :             :  * decide there's no match for an outer row, which is pretty stupid.  So,
    1551                 :             :  * we need to detect the case.
    1552                 :             :  *
    1553                 :             :  * If only_pushed_down is true, then consider only quals that are pushed-down
    1554                 :             :  * from the point of view of the joinrel.
    1555                 :             :  */
    1556                 :             : static bool
    1557                 :       39440 : restriction_is_constant_false(List *restrictlist,
    1558                 :             :                                                           RelOptInfo *joinrel,
    1559                 :             :                                                           bool only_pushed_down)
    1560                 :             : {
    1561                 :       39440 :         ListCell   *lc;
    1562                 :             : 
    1563                 :             :         /*
    1564                 :             :          * Despite the above comment, the restriction list we see here might
    1565                 :             :          * possibly have other members besides the FALSE constant, since other
    1566                 :             :          * quals could get "pushed down" to the outer join level.  So we check
    1567                 :             :          * each member of the list.
    1568                 :             :          */
    1569   [ +  +  +  +  :       80520 :         foreach(lc, restrictlist)
             +  +  +  + ]
    1570                 :             :         {
    1571                 :       41080 :                 RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
    1572                 :             : 
    1573   [ +  +  +  +  :       41080 :                 if (only_pushed_down && !RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids))
                   -  + ]
    1574                 :        7721 :                         continue;
    1575                 :             : 
    1576   [ +  -  +  + ]:       33359 :                 if (rinfo->clause && IsA(rinfo->clause, Const))
    1577                 :             :                 {
    1578                 :         767 :                         Const      *con = (Const *) rinfo->clause;
    1579                 :             : 
    1580                 :             :                         /* constant NULL is as good as constant FALSE for our purposes */
    1581         [ +  + ]:         767 :                         if (con->constisnull)
    1582                 :          18 :                                 return true;
    1583         [ +  + ]:         749 :                         if (!DatumGetBool(con->constvalue))
    1584                 :          49 :                                 return true;
    1585         [ +  + ]:         767 :                 }
    1586      [ +  +  + ]:       41080 :         }
    1587                 :       39373 :         return false;
    1588                 :       39440 : }
    1589                 :             : 
    1590                 :             : /*
    1591                 :             :  * Assess whether join between given two partitioned relations can be broken
    1592                 :             :  * down into joins between matching partitions; a technique called
    1593                 :             :  * "partitionwise join"
    1594                 :             :  *
    1595                 :             :  * Partitionwise join is possible when a. Joining relations have same
    1596                 :             :  * partitioning scheme b. There exists an equi-join between the partition keys
    1597                 :             :  * of the two relations.
    1598                 :             :  *
    1599                 :             :  * Partitionwise join is planned as follows (details: optimizer/README.)
    1600                 :             :  *
    1601                 :             :  * 1. Create the RelOptInfos for joins between matching partitions i.e
    1602                 :             :  * child-joins and add paths to them.
    1603                 :             :  *
    1604                 :             :  * 2. Construct Append or MergeAppend paths across the set of child joins.
    1605                 :             :  * This second phase is implemented by generate_partitionwise_join_paths().
    1606                 :             :  *
    1607                 :             :  * The RelOptInfo, SpecialJoinInfo and restrictlist for each child join are
    1608                 :             :  * obtained by translating the respective parent join structures.
    1609                 :             :  */
    1610                 :             : static void
    1611                 :       32577 : try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
    1612                 :             :                                            RelOptInfo *joinrel, SpecialJoinInfo *parent_sjinfo,
    1613                 :             :                                            List *parent_restrictlist)
    1614                 :             : {
    1615         [ +  + ]:       32577 :         bool            rel1_is_simple = IS_SIMPLE_REL(rel1);
    1616         [ +  + ]:       32577 :         bool            rel2_is_simple = IS_SIMPLE_REL(rel2);
    1617                 :       32577 :         List       *parts1 = NIL;
    1618                 :       32577 :         List       *parts2 = NIL;
    1619                 :       32577 :         ListCell   *lcr1 = NULL;
    1620                 :       32577 :         ListCell   *lcr2 = NULL;
    1621                 :       32577 :         int                     cnt_parts;
    1622                 :             : 
    1623                 :             :         /* Guard against stack overflow due to overly deep partition hierarchy. */
    1624                 :       32577 :         check_stack_depth();
    1625                 :             : 
    1626                 :             :         /* Nothing to do, if the join relation is not partitioned. */
    1627   [ +  +  +  + ]:       32577 :         if (joinrel->part_scheme == NULL || joinrel->nparts == 0)
    1628                 :       31250 :                 return;
    1629                 :             : 
    1630                 :             :         /* The join relation should have consider_partitionwise_join set. */
    1631         [ +  - ]:        1327 :         Assert(joinrel->consider_partitionwise_join);
    1632                 :             : 
    1633                 :             :         /*
    1634                 :             :          * We can not perform partitionwise join if either of the joining
    1635                 :             :          * relations is not partitioned.
    1636                 :             :          */
    1637   [ +  -  +  +  :        1327 :         if (!IS_PARTITIONED_REL(rel1) || !IS_PARTITIONED_REL(rel2))
          +  +  +  -  +  
          -  +  -  +  -  
          +  -  +  -  -  
                      + ]
    1638                 :           3 :                 return;
    1639                 :             : 
    1640         [ +  - ]:        1324 :         Assert(REL_HAS_ALL_PART_PROPS(rel1) && REL_HAS_ALL_PART_PROPS(rel2));
    1641                 :             : 
    1642                 :             :         /* The joining relations should have consider_partitionwise_join set. */
    1643         [ +  - ]:        1324 :         Assert(rel1->consider_partitionwise_join &&
    1644                 :             :                    rel2->consider_partitionwise_join);
    1645                 :             : 
    1646                 :             :         /*
    1647                 :             :          * The partition scheme of the join relation should match that of the
    1648                 :             :          * joining relations.
    1649                 :             :          */
    1650         [ +  - ]:        1324 :         Assert(joinrel->part_scheme == rel1->part_scheme &&
    1651                 :             :                    joinrel->part_scheme == rel2->part_scheme);
    1652                 :             : 
    1653   [ +  +  +  - ]:        1324 :         Assert(!(joinrel->partbounds_merged && (joinrel->nparts <= 0)));
    1654                 :             : 
    1655                 :        1324 :         compute_partition_bounds(root, rel1, rel2, joinrel, parent_sjinfo,
    1656                 :             :                                                          &parts1, &parts2);
    1657                 :             : 
    1658         [ +  + ]:        1324 :         if (joinrel->partbounds_merged)
    1659                 :             :         {
    1660                 :         128 :                 lcr1 = list_head(parts1);
    1661                 :         128 :                 lcr2 = list_head(parts2);
    1662                 :         128 :         }
    1663                 :             : 
    1664                 :             :         /*
    1665                 :             :          * Create child-join relations for this partitioned join, if those don't
    1666                 :             :          * exist. Add paths to child-joins for a pair of child relations
    1667                 :             :          * corresponding to the given pair of parent relations.
    1668                 :             :          */
    1669         [ +  + ]:        4661 :         for (cnt_parts = 0; cnt_parts < joinrel->nparts; cnt_parts++)
    1670                 :             :         {
    1671                 :        3357 :                 RelOptInfo *child_rel1;
    1672                 :        3357 :                 RelOptInfo *child_rel2;
    1673                 :        3357 :                 bool            rel1_empty;
    1674                 :        3357 :                 bool            rel2_empty;
    1675                 :        3357 :                 SpecialJoinInfo *child_sjinfo;
    1676                 :        3357 :                 List       *child_restrictlist;
    1677                 :        3357 :                 RelOptInfo *child_joinrel;
    1678                 :        3357 :                 AppendRelInfo **appinfos;
    1679                 :        3357 :                 int                     nappinfos;
    1680                 :        3357 :                 Relids          child_relids;
    1681                 :             : 
    1682         [ +  + ]:        3357 :                 if (joinrel->partbounds_merged)
    1683                 :             :                 {
    1684                 :         335 :                         child_rel1 = lfirst_node(RelOptInfo, lcr1);
    1685                 :         335 :                         child_rel2 = lfirst_node(RelOptInfo, lcr2);
    1686                 :         335 :                         lcr1 = lnext(parts1, lcr1);
    1687                 :         335 :                         lcr2 = lnext(parts2, lcr2);
    1688                 :         335 :                 }
    1689                 :             :                 else
    1690                 :             :                 {
    1691                 :        3022 :                         child_rel1 = rel1->part_rels[cnt_parts];
    1692                 :        3022 :                         child_rel2 = rel2->part_rels[cnt_parts];
    1693                 :             :                 }
    1694                 :             : 
    1695         [ +  + ]:        3357 :                 rel1_empty = (child_rel1 == NULL || IS_DUMMY_REL(child_rel1));
    1696         [ +  + ]:        3357 :                 rel2_empty = (child_rel2 == NULL || IS_DUMMY_REL(child_rel2));
    1697                 :             : 
    1698                 :             :                 /*
    1699                 :             :                  * Check for cases where we can prove that this segment of the join
    1700                 :             :                  * returns no rows, due to one or both inputs being empty (including
    1701                 :             :                  * inputs that have been pruned away entirely).  If so just ignore it.
    1702                 :             :                  * These rules are equivalent to populate_joinrel_with_paths's rules
    1703                 :             :                  * for dummy input relations.
    1704                 :             :                  */
    1705   [ +  +  +  - ]:        3357 :                 switch (parent_sjinfo->jointype)
    1706                 :             :                 {
    1707                 :             :                         case JOIN_INNER:
    1708                 :             :                         case JOIN_SEMI:
    1709   [ +  +  +  + ]:        2890 :                                 if (rel1_empty || rel2_empty)
    1710                 :           8 :                                         continue;       /* ignore this join segment */
    1711                 :        2882 :                                 break;
    1712                 :             :                         case JOIN_LEFT:
    1713                 :             :                         case JOIN_ANTI:
    1714         [ +  + ]:         348 :                                 if (rel1_empty)
    1715                 :           4 :                                         continue;       /* ignore this join segment */
    1716                 :         344 :                                 break;
    1717                 :             :                         case JOIN_FULL:
    1718   [ +  +  +  - ]:         119 :                                 if (rel1_empty && rel2_empty)
    1719                 :           0 :                                         continue;       /* ignore this join segment */
    1720                 :         119 :                                 break;
    1721                 :             :                         default:
    1722                 :             :                                 /* other values not expected here */
    1723   [ #  #  #  # ]:           0 :                                 elog(ERROR, "unrecognized join type: %d",
    1724                 :             :                                          (int) parent_sjinfo->jointype);
    1725                 :           0 :                                 break;
    1726                 :             :                 }
    1727                 :             : 
    1728                 :             :                 /*
    1729                 :             :                  * If a child has been pruned entirely then we can't generate paths
    1730                 :             :                  * for it, so we have to reject partitionwise joining unless we were
    1731                 :             :                  * able to eliminate this partition above.
    1732                 :             :                  */
    1733   [ +  +  +  + ]:        3345 :                 if (child_rel1 == NULL || child_rel2 == NULL)
    1734                 :             :                 {
    1735                 :             :                         /*
    1736                 :             :                          * Mark the joinrel as unpartitioned so that later functions treat
    1737                 :             :                          * it correctly.
    1738                 :             :                          */
    1739                 :          20 :                         joinrel->nparts = 0;
    1740                 :          20 :                         return;
    1741                 :             :                 }
    1742                 :             : 
    1743                 :             :                 /*
    1744                 :             :                  * If a leaf relation has consider_partitionwise_join=false, it means
    1745                 :             :                  * that it's a dummy relation for which we skipped setting up tlist
    1746                 :             :                  * expressions and adding EC members in set_append_rel_size(), so
    1747                 :             :                  * again we have to fail here.
    1748                 :             :                  */
    1749   [ +  +  +  - ]:        3325 :                 if (rel1_is_simple && !child_rel1->consider_partitionwise_join)
    1750                 :             :                 {
    1751         [ #  # ]:           0 :                         Assert(child_rel1->reloptkind == RELOPT_OTHER_MEMBER_REL);
    1752         [ #  # ]:           0 :                         Assert(IS_DUMMY_REL(child_rel1));
    1753                 :           0 :                         joinrel->nparts = 0;
    1754                 :           0 :                         return;
    1755                 :             :                 }
    1756   [ +  +  +  - ]:        3325 :                 if (rel2_is_simple && !child_rel2->consider_partitionwise_join)
    1757                 :             :                 {
    1758         [ #  # ]:           0 :                         Assert(child_rel2->reloptkind == RELOPT_OTHER_MEMBER_REL);
    1759         [ #  # ]:           0 :                         Assert(IS_DUMMY_REL(child_rel2));
    1760                 :           0 :                         joinrel->nparts = 0;
    1761                 :           0 :                         return;
    1762                 :             :                 }
    1763                 :             : 
    1764                 :             :                 /* We should never try to join two overlapping sets of rels. */
    1765         [ -  + ]:        3325 :                 Assert(!bms_overlap(child_rel1->relids, child_rel2->relids));
    1766                 :             : 
    1767                 :             :                 /*
    1768                 :             :                  * Construct SpecialJoinInfo from parent join relations's
    1769                 :             :                  * SpecialJoinInfo.
    1770                 :             :                  */
    1771                 :        6650 :                 child_sjinfo = build_child_join_sjinfo(root, parent_sjinfo,
    1772                 :        3325 :                                                                                            child_rel1->relids,
    1773                 :        3325 :                                                                                            child_rel2->relids);
    1774                 :             : 
    1775                 :             :                 /* Find the AppendRelInfo structures */
    1776                 :        3325 :                 child_relids = bms_union(child_rel1->relids, child_rel2->relids);
    1777                 :        3325 :                 appinfos = find_appinfos_by_relids(root, child_relids,
    1778                 :             :                                                                                    &nappinfos);
    1779                 :             : 
    1780                 :             :                 /*
    1781                 :             :                  * Construct restrictions applicable to the child join from those
    1782                 :             :                  * applicable to the parent join.
    1783                 :             :                  */
    1784                 :        3325 :                 child_restrictlist =
    1785                 :        6650 :                         (List *) adjust_appendrel_attrs(root,
    1786                 :        3325 :                                                                                         (Node *) parent_restrictlist,
    1787                 :        3325 :                                                                                         nappinfos, appinfos);
    1788                 :             : 
    1789                 :             :                 /* Find or construct the child join's RelOptInfo */
    1790                 :        3325 :                 child_joinrel = joinrel->part_rels[cnt_parts];
    1791         [ +  + ]:        3325 :                 if (!child_joinrel)
    1792                 :             :                 {
    1793                 :        6242 :                         child_joinrel = build_child_join_rel(root, child_rel1, child_rel2,
    1794                 :        3121 :                                                                                                  joinrel, child_restrictlist,
    1795                 :        3121 :                                                                                                  child_sjinfo, nappinfos, appinfos);
    1796                 :        3121 :                         joinrel->part_rels[cnt_parts] = child_joinrel;
    1797                 :        3121 :                         joinrel->live_parts = bms_add_member(joinrel->live_parts, cnt_parts);
    1798                 :        6242 :                         joinrel->all_partrels = bms_add_members(joinrel->all_partrels,
    1799                 :        3121 :                                                                                                         child_joinrel->relids);
    1800                 :        3121 :                 }
    1801                 :             : 
    1802                 :             :                 /* Assert we got the right one */
    1803         [ -  + ]:        3325 :                 Assert(bms_equal(child_joinrel->relids,
    1804                 :             :                                                  adjust_child_relids(joinrel->relids,
    1805                 :             :                                                                                          nappinfos, appinfos)));
    1806                 :             : 
    1807                 :             :                 /* Build a grouped join relation for 'child_joinrel' if possible */
    1808                 :        6650 :                 make_grouped_join_rel(root, child_rel1, child_rel2,
    1809                 :        3325 :                                                           child_joinrel, child_sjinfo,
    1810                 :        3325 :                                                           child_restrictlist);
    1811                 :             : 
    1812                 :             :                 /* And make paths for the child join */
    1813                 :        6650 :                 populate_joinrel_with_paths(root, child_rel1, child_rel2,
    1814                 :        3325 :                                                                         child_joinrel, child_sjinfo,
    1815                 :        3325 :                                                                         child_restrictlist);
    1816                 :             : 
    1817                 :             :                 /*
    1818                 :             :                  * When there are thousands of partitions involved, this loop will
    1819                 :             :                  * accumulate a significant amount of memory usage from objects that
    1820                 :             :                  * are only needed within the loop.  Free these local objects eagerly
    1821                 :             :                  * at the end of each iteration.
    1822                 :             :                  */
    1823                 :        3325 :                 pfree(appinfos);
    1824                 :        3325 :                 bms_free(child_relids);
    1825                 :        3325 :                 free_child_join_sjinfo(child_sjinfo, parent_sjinfo);
    1826      [ +  +  + ]:        3357 :         }
    1827         [ -  + ]:       32577 : }
    1828                 :             : 
    1829                 :             : /*
    1830                 :             :  * Construct the SpecialJoinInfo for a child-join by translating
    1831                 :             :  * SpecialJoinInfo for the join between parents. left_relids and right_relids
    1832                 :             :  * are the relids of left and right side of the join respectively.
    1833                 :             :  *
    1834                 :             :  * If translations are added to or removed from this function, consider
    1835                 :             :  * updating free_child_join_sjinfo() accordingly.
    1836                 :             :  */
    1837                 :             : static SpecialJoinInfo *
    1838                 :        3325 : build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo,
    1839                 :             :                                                 Relids left_relids, Relids right_relids)
    1840                 :             : {
    1841                 :        3325 :         SpecialJoinInfo *sjinfo = makeNode(SpecialJoinInfo);
    1842                 :        3325 :         AppendRelInfo **left_appinfos;
    1843                 :        3325 :         int                     left_nappinfos;
    1844                 :        3325 :         AppendRelInfo **right_appinfos;
    1845                 :        3325 :         int                     right_nappinfos;
    1846                 :             : 
    1847                 :             :         /* Dummy SpecialJoinInfos can be created without any translation. */
    1848         [ +  + ]:        3325 :         if (parent_sjinfo->jointype == JOIN_INNER)
    1849                 :             :         {
    1850         [ +  - ]:        2796 :                 Assert(parent_sjinfo->ojrelid == 0);
    1851                 :        2796 :                 init_dummy_sjinfo(sjinfo, left_relids, right_relids);
    1852                 :        2796 :                 return sjinfo;
    1853                 :             :         }
    1854                 :             : 
    1855                 :         529 :         memcpy(sjinfo, parent_sjinfo, sizeof(SpecialJoinInfo));
    1856                 :         529 :         left_appinfos = find_appinfos_by_relids(root, left_relids,
    1857                 :             :                                                                                         &left_nappinfos);
    1858                 :         529 :         right_appinfos = find_appinfos_by_relids(root, right_relids,
    1859                 :             :                                                                                          &right_nappinfos);
    1860                 :             : 
    1861                 :        1058 :         sjinfo->min_lefthand = adjust_child_relids(sjinfo->min_lefthand,
    1862                 :         529 :                                                                                            left_nappinfos, left_appinfos);
    1863                 :        1058 :         sjinfo->min_righthand = adjust_child_relids(sjinfo->min_righthand,
    1864                 :         529 :                                                                                                 right_nappinfos,
    1865                 :         529 :                                                                                                 right_appinfos);
    1866                 :        1058 :         sjinfo->syn_lefthand = adjust_child_relids(sjinfo->syn_lefthand,
    1867                 :         529 :                                                                                            left_nappinfos, left_appinfos);
    1868                 :        1058 :         sjinfo->syn_righthand = adjust_child_relids(sjinfo->syn_righthand,
    1869                 :         529 :                                                                                                 right_nappinfos,
    1870                 :         529 :                                                                                                 right_appinfos);
    1871                 :             :         /* outer-join relids need no adjustment */
    1872                 :        1058 :         sjinfo->semi_rhs_exprs = (List *) adjust_appendrel_attrs(root,
    1873                 :         529 :                                                                                                                          (Node *) sjinfo->semi_rhs_exprs,
    1874                 :         529 :                                                                                                                          right_nappinfos,
    1875                 :         529 :                                                                                                                          right_appinfos);
    1876                 :             : 
    1877                 :         529 :         pfree(left_appinfos);
    1878                 :         529 :         pfree(right_appinfos);
    1879                 :             : 
    1880                 :         529 :         return sjinfo;
    1881                 :        3325 : }
    1882                 :             : 
    1883                 :             : /*
    1884                 :             :  * free_child_join_sjinfo
    1885                 :             :  *              Free memory consumed by a SpecialJoinInfo created by
    1886                 :             :  *              build_child_join_sjinfo()
    1887                 :             :  *
    1888                 :             :  * Only members that are translated copies of their counterpart in the parent
    1889                 :             :  * SpecialJoinInfo are freed here.
    1890                 :             :  */
    1891                 :             : static void
    1892                 :        3325 : free_child_join_sjinfo(SpecialJoinInfo *child_sjinfo,
    1893                 :             :                                            SpecialJoinInfo *parent_sjinfo)
    1894                 :             : {
    1895                 :             :         /*
    1896                 :             :          * Dummy SpecialJoinInfos of inner joins do not have any translated fields
    1897                 :             :          * and hence no fields that to be freed.
    1898                 :             :          */
    1899         [ +  + ]:        3325 :         if (child_sjinfo->jointype != JOIN_INNER)
    1900                 :             :         {
    1901         [ +  + ]:         529 :                 if (child_sjinfo->min_lefthand != parent_sjinfo->min_lefthand)
    1902                 :         526 :                         bms_free(child_sjinfo->min_lefthand);
    1903                 :             : 
    1904         [ -  + ]:         529 :                 if (child_sjinfo->min_righthand != parent_sjinfo->min_righthand)
    1905                 :         529 :                         bms_free(child_sjinfo->min_righthand);
    1906                 :             : 
    1907         [ -  + ]:         529 :                 if (child_sjinfo->syn_lefthand != parent_sjinfo->syn_lefthand)
    1908                 :         529 :                         bms_free(child_sjinfo->syn_lefthand);
    1909                 :             : 
    1910         [ -  + ]:         529 :                 if (child_sjinfo->syn_righthand != parent_sjinfo->syn_righthand)
    1911                 :         529 :                         bms_free(child_sjinfo->syn_righthand);
    1912                 :             : 
    1913         [ +  - ]:         529 :                 Assert(child_sjinfo->commute_above_l == parent_sjinfo->commute_above_l);
    1914         [ +  - ]:         529 :                 Assert(child_sjinfo->commute_above_r == parent_sjinfo->commute_above_r);
    1915         [ +  - ]:         529 :                 Assert(child_sjinfo->commute_below_l == parent_sjinfo->commute_below_l);
    1916         [ +  - ]:         529 :                 Assert(child_sjinfo->commute_below_r == parent_sjinfo->commute_below_r);
    1917                 :             : 
    1918         [ +  - ]:         529 :                 Assert(child_sjinfo->semi_operators == parent_sjinfo->semi_operators);
    1919                 :             : 
    1920                 :             :                 /*
    1921                 :             :                  * semi_rhs_exprs may in principle be freed, but a simple pfree() does
    1922                 :             :                  * not suffice, so we leave it alone.
    1923                 :             :                  */
    1924                 :         529 :         }
    1925                 :             : 
    1926                 :        3325 :         pfree(child_sjinfo);
    1927                 :        3325 : }
    1928                 :             : 
    1929                 :             : /*
    1930                 :             :  * compute_partition_bounds
    1931                 :             :  *              Compute the partition bounds for a join rel from those for inputs
    1932                 :             :  */
    1933                 :             : static void
    1934                 :        1324 : compute_partition_bounds(PlannerInfo *root, RelOptInfo *rel1,
    1935                 :             :                                                  RelOptInfo *rel2, RelOptInfo *joinrel,
    1936                 :             :                                                  SpecialJoinInfo *parent_sjinfo,
    1937                 :             :                                                  List **parts1, List **parts2)
    1938                 :             : {
    1939                 :             :         /*
    1940                 :             :          * If we don't have the partition bounds for the join rel yet, try to
    1941                 :             :          * compute those along with pairs of partitions to be joined.
    1942                 :             :          */
    1943         [ +  + ]:        1324 :         if (joinrel->nparts == -1)
    1944                 :             :         {
    1945                 :        1250 :                 PartitionScheme part_scheme = joinrel->part_scheme;
    1946                 :        1250 :                 PartitionBoundInfo boundinfo = NULL;
    1947                 :        1250 :                 int                     nparts = 0;
    1948                 :             : 
    1949         [ +  - ]:        1250 :                 Assert(joinrel->boundinfo == NULL);
    1950         [ +  - ]:        1250 :                 Assert(joinrel->part_rels == NULL);
    1951                 :             : 
    1952                 :             :                 /*
    1953                 :             :                  * See if the partition bounds for inputs are exactly the same, in
    1954                 :             :                  * which case we don't need to work hard: the join rel will have the
    1955                 :             :                  * same partition bounds as inputs, and the partitions with the same
    1956                 :             :                  * cardinal positions will form the pairs.
    1957                 :             :                  *
    1958                 :             :                  * Note: even in cases where one or both inputs have merged bounds, it
    1959                 :             :                  * would be possible for both the bounds to be exactly the same, but
    1960                 :             :                  * it seems unlikely to be worth the cycles to check.
    1961                 :             :                  */
    1962         [ +  + ]:        1250 :                 if (!rel1->partbounds_merged &&
    1963         [ +  - ]:        1240 :                         !rel2->partbounds_merged &&
    1964   [ +  +  +  + ]:        1240 :                         rel1->nparts == rel2->nparts &&
    1965                 :        2392 :                         partition_bounds_equal(part_scheme->partnatts,
    1966                 :        1196 :                                                                    part_scheme->parttyplen,
    1967                 :        1196 :                                                                    part_scheme->parttypbyval,
    1968                 :        1196 :                                                                    rel1->boundinfo, rel2->boundinfo))
    1969                 :             :                 {
    1970                 :        1108 :                         boundinfo = rel1->boundinfo;
    1971                 :        1108 :                         nparts = rel1->nparts;
    1972                 :        1108 :                 }
    1973                 :             :                 else
    1974                 :             :                 {
    1975                 :             :                         /* Try merging the partition bounds for inputs. */
    1976                 :         284 :                         boundinfo = partition_bounds_merge(part_scheme->partnatts,
    1977                 :         142 :                                                                                            part_scheme->partsupfunc,
    1978                 :         142 :                                                                                            part_scheme->partcollation,
    1979                 :         142 :                                                                                            rel1, rel2,
    1980                 :         142 :                                                                                            parent_sjinfo->jointype,
    1981                 :         142 :                                                                                            parts1, parts2);
    1982         [ +  + ]:         142 :                         if (boundinfo == NULL)
    1983                 :             :                         {
    1984                 :          20 :                                 joinrel->nparts = 0;
    1985                 :          20 :                                 return;
    1986                 :             :                         }
    1987                 :         122 :                         nparts = list_length(*parts1);
    1988                 :         122 :                         joinrel->partbounds_merged = true;
    1989                 :             :                 }
    1990                 :             : 
    1991         [ +  - ]:        1230 :                 Assert(nparts > 0);
    1992                 :        1230 :                 joinrel->boundinfo = boundinfo;
    1993                 :        1230 :                 joinrel->nparts = nparts;
    1994                 :        1230 :                 joinrel->part_rels = palloc0_array(RelOptInfo *, nparts);
    1995      [ -  +  + ]:        1250 :         }
    1996                 :             :         else
    1997                 :             :         {
    1998         [ +  - ]:          74 :                 Assert(joinrel->nparts > 0);
    1999         [ +  - ]:          74 :                 Assert(joinrel->boundinfo);
    2000         [ +  - ]:          74 :                 Assert(joinrel->part_rels);
    2001                 :             : 
    2002                 :             :                 /*
    2003                 :             :                  * If the join rel's partbounds_merged flag is true, it means inputs
    2004                 :             :                  * are not guaranteed to have the same partition bounds, therefore we
    2005                 :             :                  * can't assume that the partitions at the same cardinal positions
    2006                 :             :                  * form the pairs; let get_matching_part_pairs() generate the pairs.
    2007                 :             :                  * Otherwise, nothing to do since we can assume that.
    2008                 :             :                  */
    2009         [ +  + ]:          74 :                 if (joinrel->partbounds_merged)
    2010                 :             :                 {
    2011                 :          12 :                         get_matching_part_pairs(root, joinrel, rel1, rel2,
    2012                 :           6 :                                                                         parts1, parts2);
    2013         [ +  - ]:           6 :                         Assert(list_length(*parts1) == joinrel->nparts);
    2014         [ +  - ]:           6 :                         Assert(list_length(*parts2) == joinrel->nparts);
    2015                 :           6 :                 }
    2016                 :             :         }
    2017                 :        1324 : }
    2018                 :             : 
    2019                 :             : /*
    2020                 :             :  * get_matching_part_pairs
    2021                 :             :  *              Generate pairs of partitions to be joined from inputs
    2022                 :             :  */
    2023                 :             : static void
    2024                 :           6 : get_matching_part_pairs(PlannerInfo *root, RelOptInfo *joinrel,
    2025                 :             :                                                 RelOptInfo *rel1, RelOptInfo *rel2,
    2026                 :             :                                                 List **parts1, List **parts2)
    2027                 :             : {
    2028         [ -  + ]:           6 :         bool            rel1_is_simple = IS_SIMPLE_REL(rel1);
    2029         [ +  - ]:           6 :         bool            rel2_is_simple = IS_SIMPLE_REL(rel2);
    2030                 :           6 :         int                     cnt_parts;
    2031                 :             : 
    2032                 :           6 :         *parts1 = NIL;
    2033                 :           6 :         *parts2 = NIL;
    2034                 :             : 
    2035         [ +  + ]:          22 :         for (cnt_parts = 0; cnt_parts < joinrel->nparts; cnt_parts++)
    2036                 :             :         {
    2037                 :          16 :                 RelOptInfo *child_joinrel = joinrel->part_rels[cnt_parts];
    2038                 :          16 :                 RelOptInfo *child_rel1;
    2039                 :          16 :                 RelOptInfo *child_rel2;
    2040                 :          16 :                 Relids          child_relids1;
    2041                 :          16 :                 Relids          child_relids2;
    2042                 :             : 
    2043                 :             :                 /*
    2044                 :             :                  * If this segment of the join is empty, it means that this segment
    2045                 :             :                  * was ignored when previously creating child-join paths for it in
    2046                 :             :                  * try_partitionwise_join() as it would not contribute to the join
    2047                 :             :                  * result, due to one or both inputs being empty; add NULL to each of
    2048                 :             :                  * the given lists so that this segment will be ignored again in that
    2049                 :             :                  * function.
    2050                 :             :                  */
    2051         [ +  - ]:          16 :                 if (!child_joinrel)
    2052                 :             :                 {
    2053                 :           0 :                         *parts1 = lappend(*parts1, NULL);
    2054                 :           0 :                         *parts2 = lappend(*parts2, NULL);
    2055                 :           0 :                         continue;
    2056                 :             :                 }
    2057                 :             : 
    2058                 :             :                 /*
    2059                 :             :                  * Get a relids set of partition(s) involved in this join segment that
    2060                 :             :                  * are from the rel1 side.
    2061                 :             :                  */
    2062                 :          32 :                 child_relids1 = bms_intersect(child_joinrel->relids,
    2063                 :          16 :                                                                           rel1->all_partrels);
    2064         [ +  - ]:          16 :                 Assert(bms_num_members(child_relids1) == bms_num_members(rel1->relids));
    2065                 :             : 
    2066                 :             :                 /*
    2067                 :             :                  * Get a child rel for rel1 with the relids.  Note that we should have
    2068                 :             :                  * the child rel even if rel1 is a join rel, because in that case the
    2069                 :             :                  * partitions specified in the relids would have matching/overlapping
    2070                 :             :                  * boundaries, so the specified partitions should be considered as
    2071                 :             :                  * ones to be joined when planning partitionwise joins of rel1,
    2072                 :             :                  * meaning that the child rel would have been built by the time we get
    2073                 :             :                  * here.
    2074                 :             :                  */
    2075         [ -  + ]:          16 :                 if (rel1_is_simple)
    2076                 :             :                 {
    2077                 :           0 :                         int                     varno = bms_singleton_member(child_relids1);
    2078                 :             : 
    2079                 :           0 :                         child_rel1 = find_base_rel(root, varno);
    2080                 :           0 :                 }
    2081                 :             :                 else
    2082                 :          16 :                         child_rel1 = find_join_rel(root, child_relids1);
    2083         [ +  - ]:          16 :                 Assert(child_rel1);
    2084                 :             : 
    2085                 :             :                 /*
    2086                 :             :                  * Get a relids set of partition(s) involved in this join segment that
    2087                 :             :                  * are from the rel2 side.
    2088                 :             :                  */
    2089                 :          32 :                 child_relids2 = bms_intersect(child_joinrel->relids,
    2090                 :          16 :                                                                           rel2->all_partrels);
    2091         [ -  + ]:          16 :                 Assert(bms_num_members(child_relids2) == bms_num_members(rel2->relids));
    2092                 :             : 
    2093                 :             :                 /*
    2094                 :             :                  * Get a child rel for rel2 with the relids.  See above comments.
    2095                 :             :                  */
    2096         [ +  - ]:          16 :                 if (rel2_is_simple)
    2097                 :             :                 {
    2098                 :          16 :                         int                     varno = bms_singleton_member(child_relids2);
    2099                 :             : 
    2100                 :          16 :                         child_rel2 = find_base_rel(root, varno);
    2101                 :          16 :                 }
    2102                 :             :                 else
    2103                 :           0 :                         child_rel2 = find_join_rel(root, child_relids2);
    2104         [ -  + ]:          16 :                 Assert(child_rel2);
    2105                 :             : 
    2106                 :             :                 /*
    2107                 :             :                  * The join of rel1 and rel2 is legal, so is the join of the child
    2108                 :             :                  * rels obtained above; add them to the given lists as a join pair
    2109                 :             :                  * producing this join segment.
    2110                 :             :                  */
    2111                 :          16 :                 *parts1 = lappend(*parts1, child_rel1);
    2112                 :          16 :                 *parts2 = lappend(*parts2, child_rel2);
    2113      [ -  -  + ]:          16 :         }
    2114                 :           6 : }
        

Generated by: LCOV version 2.3.2-1