LCOV - code coverage report
Current view: top level - src/backend/optimizer/util - relnode.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 550 561 98.0 %
Date: 2019-09-19 16:06:56 Functions: 24 24 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * relnode.c
       4             :  *    Relation-node lookup/construction routines
       5             :  *
       6             :  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/optimizer/util/relnode.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #include "postgres.h"
      16             : 
      17             : #include <limits.h>
      18             : 
      19             : #include "miscadmin.h"
      20             : #include "optimizer/appendinfo.h"
      21             : #include "optimizer/clauses.h"
      22             : #include "optimizer/cost.h"
      23             : #include "optimizer/inherit.h"
      24             : #include "optimizer/pathnode.h"
      25             : #include "optimizer/paths.h"
      26             : #include "optimizer/placeholder.h"
      27             : #include "optimizer/plancat.h"
      28             : #include "optimizer/restrictinfo.h"
      29             : #include "optimizer/tlist.h"
      30             : #include "partitioning/partbounds.h"
      31             : #include "utils/hsearch.h"
      32             : 
      33             : 
      34             : typedef struct JoinHashEntry
      35             : {
      36             :     Relids      join_relids;    /* hash key --- MUST BE FIRST */
      37             :     RelOptInfo *join_rel;
      38             : } JoinHashEntry;
      39             : 
      40             : static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
      41             :                                 RelOptInfo *input_rel);
      42             : static List *build_joinrel_restrictlist(PlannerInfo *root,
      43             :                                         RelOptInfo *joinrel,
      44             :                                         RelOptInfo *outer_rel,
      45             :                                         RelOptInfo *inner_rel);
      46             : static void build_joinrel_joinlist(RelOptInfo *joinrel,
      47             :                                    RelOptInfo *outer_rel,
      48             :                                    RelOptInfo *inner_rel);
      49             : static List *subbuild_joinrel_restrictlist(RelOptInfo *joinrel,
      50             :                                            List *joininfo_list,
      51             :                                            List *new_restrictlist);
      52             : static List *subbuild_joinrel_joinlist(RelOptInfo *joinrel,
      53             :                                        List *joininfo_list,
      54             :                                        List *new_joininfo);
      55             : static void set_foreign_rel_properties(RelOptInfo *joinrel,
      56             :                                        RelOptInfo *outer_rel, RelOptInfo *inner_rel);
      57             : static void add_join_rel(PlannerInfo *root, RelOptInfo *joinrel);
      58             : static void build_joinrel_partition_info(RelOptInfo *joinrel,
      59             :                                          RelOptInfo *outer_rel, RelOptInfo *inner_rel,
      60             :                                          List *restrictlist, JoinType jointype);
      61             : static void build_child_join_reltarget(PlannerInfo *root,
      62             :                                        RelOptInfo *parentrel,
      63             :                                        RelOptInfo *childrel,
      64             :                                        int nappinfos,
      65             :                                        AppendRelInfo **appinfos);
      66             : 
      67             : 
      68             : /*
      69             :  * setup_simple_rel_arrays
      70             :  *    Prepare the arrays we use for quickly accessing base relations
      71             :  *    and AppendRelInfos.
      72             :  */
      73             : void
      74      322158 : setup_simple_rel_arrays(PlannerInfo *root)
      75             : {
      76             :     int         size;
      77             :     Index       rti;
      78             :     ListCell   *lc;
      79             : 
      80             :     /* Arrays are accessed using RT indexes (1..N) */
      81      322158 :     size = list_length(root->parse->rtable) + 1;
      82      322158 :     root->simple_rel_array_size = size;
      83             : 
      84             :     /*
      85             :      * simple_rel_array is initialized to all NULLs, since no RelOptInfos
      86             :      * exist yet.  It'll be filled by later calls to build_simple_rel().
      87             :      */
      88      322158 :     root->simple_rel_array = (RelOptInfo **)
      89      322158 :         palloc0(size * sizeof(RelOptInfo *));
      90             : 
      91             :     /* simple_rte_array is an array equivalent of the rtable list */
      92      322158 :     root->simple_rte_array = (RangeTblEntry **)
      93      322158 :         palloc0(size * sizeof(RangeTblEntry *));
      94      322158 :     rti = 1;
      95      909010 :     foreach(lc, root->parse->rtable)
      96             :     {
      97      586852 :         RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
      98             : 
      99      586852 :         root->simple_rte_array[rti++] = rte;
     100             :     }
     101             : 
     102             :     /* append_rel_array is not needed if there are no AppendRelInfos */
     103      322158 :     if (root->append_rel_list == NIL)
     104             :     {
     105      320298 :         root->append_rel_array = NULL;
     106      320298 :         return;
     107             :     }
     108             : 
     109        1860 :     root->append_rel_array = (AppendRelInfo **)
     110        1860 :         palloc0(size * sizeof(AppendRelInfo *));
     111             : 
     112             :     /*
     113             :      * append_rel_array is filled with any already-existing AppendRelInfos,
     114             :      * which currently could only come from UNION ALL flattening.  We might
     115             :      * add more later during inheritance expansion, but it's the
     116             :      * responsibility of the expansion code to update the array properly.
     117             :      */
     118        5900 :     foreach(lc, root->append_rel_list)
     119             :     {
     120        4040 :         AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
     121        4040 :         int         child_relid = appinfo->child_relid;
     122             : 
     123             :         /* Sanity check */
     124             :         Assert(child_relid < size);
     125             : 
     126        4040 :         if (root->append_rel_array[child_relid])
     127           0 :             elog(ERROR, "child relation already exists");
     128             : 
     129        4040 :         root->append_rel_array[child_relid] = appinfo;
     130             :     }
     131             : }
     132             : 
     133             : /*
     134             :  * expand_planner_arrays
     135             :  *      Expand the PlannerInfo's per-RTE arrays by add_size members
     136             :  *      and initialize the newly added entries to NULLs
     137             :  *
     138             :  * Note: this causes the append_rel_array to become allocated even if
     139             :  * it was not before.  This is okay for current uses, because we only call
     140             :  * this when adding child relations, which always have AppendRelInfos.
     141             :  */
     142             : void
     143        7698 : expand_planner_arrays(PlannerInfo *root, int add_size)
     144             : {
     145             :     int         new_size;
     146             : 
     147             :     Assert(add_size > 0);
     148             : 
     149        7698 :     new_size = root->simple_rel_array_size + add_size;
     150             : 
     151        7698 :     root->simple_rel_array = (RelOptInfo **)
     152        7698 :         repalloc(root->simple_rel_array,
     153             :                  sizeof(RelOptInfo *) * new_size);
     154        7698 :     MemSet(root->simple_rel_array + root->simple_rel_array_size,
     155             :            0, sizeof(RelOptInfo *) * add_size);
     156             : 
     157        7698 :     root->simple_rte_array = (RangeTblEntry **)
     158        7698 :         repalloc(root->simple_rte_array,
     159             :                  sizeof(RangeTblEntry *) * new_size);
     160        7698 :     MemSet(root->simple_rte_array + root->simple_rel_array_size,
     161             :            0, sizeof(RangeTblEntry *) * add_size);
     162             : 
     163        7698 :     if (root->append_rel_array)
     164             :     {
     165        2908 :         root->append_rel_array = (AppendRelInfo **)
     166        2908 :             repalloc(root->append_rel_array,
     167             :                      sizeof(AppendRelInfo *) * new_size);
     168        2908 :         MemSet(root->append_rel_array + root->simple_rel_array_size,
     169             :                0, sizeof(AppendRelInfo *) * add_size);
     170             :     }
     171             :     else
     172             :     {
     173        4790 :         root->append_rel_array = (AppendRelInfo **)
     174        4790 :             palloc0(sizeof(AppendRelInfo *) * new_size);
     175             :     }
     176             : 
     177        7698 :     root->simple_rel_array_size = new_size;
     178        7698 : }
     179             : 
     180             : /*
     181             :  * build_simple_rel
     182             :  *    Construct a new RelOptInfo for a base relation or 'other' relation.
     183             :  */
     184             : RelOptInfo *
     185      417452 : build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
     186             : {
     187             :     RelOptInfo *rel;
     188             :     RangeTblEntry *rte;
     189             : 
     190             :     /* Rel should not exist already */
     191             :     Assert(relid > 0 && relid < root->simple_rel_array_size);
     192      417452 :     if (root->simple_rel_array[relid] != NULL)
     193           0 :         elog(ERROR, "rel %d already exists", relid);
     194             : 
     195             :     /* Fetch RTE for relation */
     196      417452 :     rte = root->simple_rte_array[relid];
     197             :     Assert(rte != NULL);
     198             : 
     199      417452 :     rel = makeNode(RelOptInfo);
     200      417452 :     rel->reloptkind = parent ? RELOPT_OTHER_MEMBER_REL : RELOPT_BASEREL;
     201      417452 :     rel->relids = bms_make_singleton(relid);
     202      417452 :     rel->rows = 0;
     203             :     /* cheap startup cost is interesting iff not all tuples to be retrieved */
     204      417452 :     rel->consider_startup = (root->tuple_fraction > 0);
     205      417452 :     rel->consider_param_startup = false; /* might get changed later */
     206      417452 :     rel->consider_parallel = false; /* might get changed later */
     207      417452 :     rel->reltarget = create_empty_pathtarget();
     208      417452 :     rel->pathlist = NIL;
     209      417452 :     rel->ppilist = NIL;
     210      417452 :     rel->partial_pathlist = NIL;
     211      417452 :     rel->cheapest_startup_path = NULL;
     212      417452 :     rel->cheapest_total_path = NULL;
     213      417452 :     rel->cheapest_unique_path = NULL;
     214      417452 :     rel->cheapest_parameterized_paths = NIL;
     215      417452 :     rel->relid = relid;
     216      417452 :     rel->rtekind = rte->rtekind;
     217             :     /* min_attr, max_attr, attr_needed, attr_widths are set below */
     218      417452 :     rel->lateral_vars = NIL;
     219      417452 :     rel->indexlist = NIL;
     220      417452 :     rel->statlist = NIL;
     221      417452 :     rel->pages = 0;
     222      417452 :     rel->tuples = 0;
     223      417452 :     rel->allvisfrac = 0;
     224      417452 :     rel->eclass_indexes = NULL;
     225      417452 :     rel->subroot = NULL;
     226      417452 :     rel->subplan_params = NIL;
     227      417452 :     rel->rel_parallel_workers = -1; /* set up in get_relation_info */
     228      417452 :     rel->serverid = InvalidOid;
     229      417452 :     rel->userid = rte->checkAsUser;
     230      417452 :     rel->useridiscurrent = false;
     231      417452 :     rel->fdwroutine = NULL;
     232      417452 :     rel->fdw_private = NULL;
     233      417452 :     rel->unique_for_rels = NIL;
     234      417452 :     rel->non_unique_for_rels = NIL;
     235      417452 :     rel->baserestrictinfo = NIL;
     236      417452 :     rel->baserestrictcost.startup = 0;
     237      417452 :     rel->baserestrictcost.per_tuple = 0;
     238      417452 :     rel->baserestrict_min_security = UINT_MAX;
     239      417452 :     rel->joininfo = NIL;
     240      417452 :     rel->has_eclass_joins = false;
     241      417452 :     rel->consider_partitionwise_join = false;    /* might get changed later */
     242      417452 :     rel->part_scheme = NULL;
     243      417452 :     rel->nparts = 0;
     244      417452 :     rel->boundinfo = NULL;
     245      417452 :     rel->partition_qual = NIL;
     246      417452 :     rel->part_rels = NULL;
     247      417452 :     rel->partexprs = NULL;
     248      417452 :     rel->nullable_partexprs = NULL;
     249      417452 :     rel->partitioned_child_rels = NIL;
     250             : 
     251             :     /*
     252             :      * Pass assorted information down the inheritance hierarchy.
     253             :      */
     254      417452 :     if (parent)
     255             :     {
     256             :         /*
     257             :          * Each direct or indirect child wants to know the relids of its
     258             :          * topmost parent.
     259             :          */
     260       22500 :         if (parent->top_parent_relids)
     261        4828 :             rel->top_parent_relids = parent->top_parent_relids;
     262             :         else
     263       17672 :             rel->top_parent_relids = bms_copy(parent->relids);
     264             : 
     265             :         /*
     266             :          * Also propagate lateral-reference information from appendrel parent
     267             :          * rels to their child rels.  We intentionally give each child rel the
     268             :          * same minimum parameterization, even though it's quite possible that
     269             :          * some don't reference all the lateral rels.  This is because any
     270             :          * append path for the parent will have to have the same
     271             :          * parameterization for every child anyway, and there's no value in
     272             :          * forcing extra reparameterize_path() calls.  Similarly, a lateral
     273             :          * reference to the parent prevents use of otherwise-movable join rels
     274             :          * for each child.
     275             :          *
     276             :          * It's possible for child rels to have their own children, in which
     277             :          * case the topmost parent's lateral info propagates all the way down.
     278             :          */
     279       22500 :         rel->direct_lateral_relids = parent->direct_lateral_relids;
     280       22500 :         rel->lateral_relids = parent->lateral_relids;
     281       22500 :         rel->lateral_referencers = parent->lateral_referencers;
     282             :     }
     283             :     else
     284             :     {
     285      394952 :         rel->top_parent_relids = NULL;
     286      394952 :         rel->direct_lateral_relids = NULL;
     287      394952 :         rel->lateral_relids = NULL;
     288      394952 :         rel->lateral_referencers = NULL;
     289             :     }
     290             : 
     291             :     /* Check type of rtable entry */
     292      417452 :     switch (rte->rtekind)
     293             :     {
     294             :         case RTE_RELATION:
     295             :             /* Table --- retrieve statistics from the system catalogs */
     296      261868 :             get_relation_info(root, rte->relid, rte->inh, rel);
     297      261860 :             break;
     298             :         case RTE_SUBQUERY:
     299             :         case RTE_FUNCTION:
     300             :         case RTE_TABLEFUNC:
     301             :         case RTE_VALUES:
     302             :         case RTE_CTE:
     303             :         case RTE_NAMEDTUPLESTORE:
     304             : 
     305             :             /*
     306             :              * Subquery, function, tablefunc, values list, CTE, or ENR --- set
     307             :              * up attr range and arrays
     308             :              *
     309             :              * Note: 0 is included in range to support whole-row Vars
     310             :              */
     311       44138 :             rel->min_attr = 0;
     312       44138 :             rel->max_attr = list_length(rte->eref->colnames);
     313       44138 :             rel->attr_needed = (Relids *)
     314       44138 :                 palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids));
     315       44138 :             rel->attr_widths = (int32 *)
     316       44138 :                 palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32));
     317       44138 :             break;
     318             :         case RTE_RESULT:
     319             :             /* RTE_RESULT has no columns, nor could it have whole-row Var */
     320      111446 :             rel->min_attr = 0;
     321      111446 :             rel->max_attr = -1;
     322      111446 :             rel->attr_needed = NULL;
     323      111446 :             rel->attr_widths = NULL;
     324      111446 :             break;
     325             :         default:
     326           0 :             elog(ERROR, "unrecognized RTE kind: %d",
     327             :                  (int) rte->rtekind);
     328             :             break;
     329             :     }
     330             : 
     331             :     /*
     332             :      * Copy the parent's quals to the child, with appropriate substitution of
     333             :      * variables.  If any constant false or NULL clauses turn up, we can mark
     334             :      * the child as dummy right away.  (We must do this immediately so that
     335             :      * pruning works correctly when recursing in expand_partitioned_rtentry.)
     336             :      */
     337      417444 :     if (parent)
     338             :     {
     339       22500 :         AppendRelInfo *appinfo = root->append_rel_array[relid];
     340             : 
     341             :         Assert(appinfo != NULL);
     342       22500 :         if (!apply_child_basequals(root, parent, rel, rte, appinfo))
     343             :         {
     344             :             /*
     345             :              * Some restriction clause reduced to constant FALSE or NULL after
     346             :              * substitution, so this child need not be scanned.
     347             :              */
     348          52 :             mark_dummy_rel(rel);
     349             :         }
     350             :     }
     351             : 
     352             :     /* Save the finished struct in the query's simple_rel_array */
     353      417444 :     root->simple_rel_array[relid] = rel;
     354             : 
     355      417444 :     return rel;
     356             : }
     357             : 
     358             : /*
     359             :  * find_base_rel
     360             :  *    Find a base or other relation entry, which must already exist.
     361             :  */
     362             : RelOptInfo *
     363     3842668 : find_base_rel(PlannerInfo *root, int relid)
     364             : {
     365             :     RelOptInfo *rel;
     366             : 
     367             :     Assert(relid > 0);
     368             : 
     369     3842668 :     if (relid < root->simple_rel_array_size)
     370             :     {
     371     3842668 :         rel = root->simple_rel_array[relid];
     372     3842668 :         if (rel)
     373     3842668 :             return rel;
     374             :     }
     375             : 
     376           0 :     elog(ERROR, "no relation entry for relid %d", relid);
     377             : 
     378             :     return NULL;                /* keep compiler quiet */
     379             : }
     380             : 
     381             : /*
     382             :  * build_join_rel_hash
     383             :  *    Construct the auxiliary hash table for join relations.
     384             :  */
     385             : static void
     386          20 : build_join_rel_hash(PlannerInfo *root)
     387             : {
     388             :     HTAB       *hashtab;
     389             :     HASHCTL     hash_ctl;
     390             :     ListCell   *l;
     391             : 
     392             :     /* Create the hash table */
     393          20 :     MemSet(&hash_ctl, 0, sizeof(hash_ctl));
     394          20 :     hash_ctl.keysize = sizeof(Relids);
     395          20 :     hash_ctl.entrysize = sizeof(JoinHashEntry);
     396          20 :     hash_ctl.hash = bitmap_hash;
     397          20 :     hash_ctl.match = bitmap_match;
     398          20 :     hash_ctl.hcxt = CurrentMemoryContext;
     399          20 :     hashtab = hash_create("JoinRelHashTable",
     400             :                           256L,
     401             :                           &hash_ctl,
     402             :                           HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT);
     403             : 
     404             :     /* Insert all the already-existing joinrels */
     405         680 :     foreach(l, root->join_rel_list)
     406             :     {
     407         660 :         RelOptInfo *rel = (RelOptInfo *) lfirst(l);
     408             :         JoinHashEntry *hentry;
     409             :         bool        found;
     410             : 
     411         660 :         hentry = (JoinHashEntry *) hash_search(hashtab,
     412         660 :                                                &(rel->relids),
     413             :                                                HASH_ENTER,
     414             :                                                &found);
     415             :         Assert(!found);
     416         660 :         hentry->join_rel = rel;
     417             :     }
     418             : 
     419          20 :     root->join_rel_hash = hashtab;
     420          20 : }
     421             : 
     422             : /*
     423             :  * find_join_rel
     424             :  *    Returns relation entry corresponding to 'relids' (a set of RT indexes),
     425             :  *    or NULL if none exists.  This is for join relations.
     426             :  */
     427             : RelOptInfo *
     428      147340 : find_join_rel(PlannerInfo *root, Relids relids)
     429             : {
     430             :     /*
     431             :      * Switch to using hash lookup when list grows "too long".  The threshold
     432             :      * is arbitrary and is known only here.
     433             :      */
     434      147340 :     if (!root->join_rel_hash && list_length(root->join_rel_list) > 32)
     435          20 :         build_join_rel_hash(root);
     436             : 
     437             :     /*
     438             :      * Use either hashtable lookup or linear search, as appropriate.
     439             :      *
     440             :      * Note: the seemingly redundant hashkey variable is used to avoid taking
     441             :      * the address of relids; unless the compiler is exceedingly smart, doing
     442             :      * so would force relids out of a register and thus probably slow down the
     443             :      * list-search case.
     444             :      */
     445      147340 :     if (root->join_rel_hash)
     446             :     {
     447        2312 :         Relids      hashkey = relids;
     448             :         JoinHashEntry *hentry;
     449             : 
     450        2312 :         hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
     451             :                                                &hashkey,
     452             :                                                HASH_FIND,
     453             :                                                NULL);
     454        2312 :         if (hentry)
     455        2052 :             return hentry->join_rel;
     456             :     }
     457             :     else
     458             :     {
     459             :         ListCell   *l;
     460             : 
     461      871050 :         foreach(l, root->join_rel_list)
     462             :         {
     463      776672 :             RelOptInfo *rel = (RelOptInfo *) lfirst(l);
     464             : 
     465      776672 :             if (bms_equal(rel->relids, relids))
     466       50650 :                 return rel;
     467             :         }
     468             :     }
     469             : 
     470       94638 :     return NULL;
     471             : }
     472             : 
     473             : /*
     474             :  * set_foreign_rel_properties
     475             :  *      Set up foreign-join fields if outer and inner relation are foreign
     476             :  *      tables (or joins) belonging to the same server and assigned to the same
     477             :  *      user to check access permissions as.
     478             :  *
     479             :  * In addition to an exact match of userid, we allow the case where one side
     480             :  * has zero userid (implying current user) and the other side has explicit
     481             :  * userid that happens to equal the current user; but in that case, pushdown of
     482             :  * the join is only valid for the current user.  The useridiscurrent field
     483             :  * records whether we had to make such an assumption for this join or any
     484             :  * sub-join.
     485             :  *
     486             :  * Otherwise these fields are left invalid, so GetForeignJoinPaths will not be
     487             :  * called for the join relation.
     488             :  *
     489             :  */
     490             : static void
     491       94562 : set_foreign_rel_properties(RelOptInfo *joinrel, RelOptInfo *outer_rel,
     492             :                            RelOptInfo *inner_rel)
     493             : {
     494       95142 :     if (OidIsValid(outer_rel->serverid) &&
     495         580 :         inner_rel->serverid == outer_rel->serverid)
     496             :     {
     497         496 :         if (inner_rel->userid == outer_rel->userid)
     498             :         {
     499         484 :             joinrel->serverid = outer_rel->serverid;
     500         484 :             joinrel->userid = outer_rel->userid;
     501         484 :             joinrel->useridiscurrent = outer_rel->useridiscurrent || inner_rel->useridiscurrent;
     502         484 :             joinrel->fdwroutine = outer_rel->fdwroutine;
     503             :         }
     504          20 :         else if (!OidIsValid(inner_rel->userid) &&
     505           8 :                  outer_rel->userid == GetUserId())
     506             :         {
     507           4 :             joinrel->serverid = outer_rel->serverid;
     508           4 :             joinrel->userid = outer_rel->userid;
     509           4 :             joinrel->useridiscurrent = true;
     510           4 :             joinrel->fdwroutine = outer_rel->fdwroutine;
     511             :         }
     512           8 :         else if (!OidIsValid(outer_rel->userid) &&
     513           0 :                  inner_rel->userid == GetUserId())
     514             :         {
     515           0 :             joinrel->serverid = outer_rel->serverid;
     516           0 :             joinrel->userid = inner_rel->userid;
     517           0 :             joinrel->useridiscurrent = true;
     518           0 :             joinrel->fdwroutine = outer_rel->fdwroutine;
     519             :         }
     520             :     }
     521       94562 : }
     522             : 
     523             : /*
     524             :  * add_join_rel
     525             :  *      Add given join relation to the list of join relations in the given
     526             :  *      PlannerInfo. Also add it to the auxiliary hashtable if there is one.
     527             :  */
     528             : static void
     529       94562 : add_join_rel(PlannerInfo *root, RelOptInfo *joinrel)
     530             : {
     531             :     /* GEQO requires us to append the new joinrel to the end of the list! */
     532       94562 :     root->join_rel_list = lappend(root->join_rel_list, joinrel);
     533             : 
     534             :     /* store it into the auxiliary hashtable if there is one. */
     535       94562 :     if (root->join_rel_hash)
     536             :     {
     537             :         JoinHashEntry *hentry;
     538             :         bool        found;
     539             : 
     540         260 :         hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
     541         260 :                                                &(joinrel->relids),
     542             :                                                HASH_ENTER,
     543             :                                                &found);
     544             :         Assert(!found);
     545         260 :         hentry->join_rel = joinrel;
     546             :     }
     547       94562 : }
     548             : 
     549             : /*
     550             :  * build_join_rel
     551             :  *    Returns relation entry corresponding to the union of two given rels,
     552             :  *    creating a new relation entry if none already exists.
     553             :  *
     554             :  * 'joinrelids' is the Relids set that uniquely identifies the join
     555             :  * 'outer_rel' and 'inner_rel' are relation nodes for the relations to be
     556             :  *      joined
     557             :  * 'sjinfo': join context info
     558             :  * 'restrictlist_ptr': result variable.  If not NULL, *restrictlist_ptr
     559             :  *      receives the list of RestrictInfo nodes that apply to this
     560             :  *      particular pair of joinable relations.
     561             :  *
     562             :  * restrictlist_ptr makes the routine's API a little grotty, but it saves
     563             :  * duplicated calculation of the restrictlist...
     564             :  */
     565             : RelOptInfo *
     566      144472 : build_join_rel(PlannerInfo *root,
     567             :                Relids joinrelids,
     568             :                RelOptInfo *outer_rel,
     569             :                RelOptInfo *inner_rel,
     570             :                SpecialJoinInfo *sjinfo,
     571             :                List **restrictlist_ptr)
     572             : {
     573             :     RelOptInfo *joinrel;
     574             :     List       *restrictlist;
     575             : 
     576             :     /* This function should be used only for join between parents. */
     577             :     Assert(!IS_OTHER_REL(outer_rel) && !IS_OTHER_REL(inner_rel));
     578             : 
     579             :     /*
     580             :      * See if we already have a joinrel for this set of base rels.
     581             :      */
     582      144472 :     joinrel = find_join_rel(root, joinrelids);
     583             : 
     584      144472 :     if (joinrel)
     585             :     {
     586             :         /*
     587             :          * Yes, so we only need to figure the restrictlist for this particular
     588             :          * pair of component relations.
     589             :          */
     590       51310 :         if (restrictlist_ptr)
     591       51310 :             *restrictlist_ptr = build_joinrel_restrictlist(root,
     592             :                                                            joinrel,
     593             :                                                            outer_rel,
     594             :                                                            inner_rel);
     595       51310 :         return joinrel;
     596             :     }
     597             : 
     598             :     /*
     599             :      * Nope, so make one.
     600             :      */
     601       93162 :     joinrel = makeNode(RelOptInfo);
     602       93162 :     joinrel->reloptkind = RELOPT_JOINREL;
     603       93162 :     joinrel->relids = bms_copy(joinrelids);
     604       93162 :     joinrel->rows = 0;
     605             :     /* cheap startup cost is interesting iff not all tuples to be retrieved */
     606       93162 :     joinrel->consider_startup = (root->tuple_fraction > 0);
     607       93162 :     joinrel->consider_param_startup = false;
     608       93162 :     joinrel->consider_parallel = false;
     609       93162 :     joinrel->reltarget = create_empty_pathtarget();
     610       93162 :     joinrel->pathlist = NIL;
     611       93162 :     joinrel->ppilist = NIL;
     612       93162 :     joinrel->partial_pathlist = NIL;
     613       93162 :     joinrel->cheapest_startup_path = NULL;
     614       93162 :     joinrel->cheapest_total_path = NULL;
     615       93162 :     joinrel->cheapest_unique_path = NULL;
     616       93162 :     joinrel->cheapest_parameterized_paths = NIL;
     617             :     /* init direct_lateral_relids from children; we'll finish it up below */
     618       93162 :     joinrel->direct_lateral_relids =
     619       93162 :         bms_union(outer_rel->direct_lateral_relids,
     620       93162 :                   inner_rel->direct_lateral_relids);
     621       93162 :     joinrel->lateral_relids = min_join_parameterization(root, joinrel->relids,
     622             :                                                         outer_rel, inner_rel);
     623       93162 :     joinrel->relid = 0;          /* indicates not a baserel */
     624       93162 :     joinrel->rtekind = RTE_JOIN;
     625       93162 :     joinrel->min_attr = 0;
     626       93162 :     joinrel->max_attr = 0;
     627       93162 :     joinrel->attr_needed = NULL;
     628       93162 :     joinrel->attr_widths = NULL;
     629       93162 :     joinrel->lateral_vars = NIL;
     630       93162 :     joinrel->lateral_referencers = NULL;
     631       93162 :     joinrel->indexlist = NIL;
     632       93162 :     joinrel->statlist = NIL;
     633       93162 :     joinrel->pages = 0;
     634       93162 :     joinrel->tuples = 0;
     635       93162 :     joinrel->allvisfrac = 0;
     636       93162 :     joinrel->eclass_indexes = NULL;
     637       93162 :     joinrel->subroot = NULL;
     638       93162 :     joinrel->subplan_params = NIL;
     639       93162 :     joinrel->rel_parallel_workers = -1;
     640       93162 :     joinrel->serverid = InvalidOid;
     641       93162 :     joinrel->userid = InvalidOid;
     642       93162 :     joinrel->useridiscurrent = false;
     643       93162 :     joinrel->fdwroutine = NULL;
     644       93162 :     joinrel->fdw_private = NULL;
     645       93162 :     joinrel->unique_for_rels = NIL;
     646       93162 :     joinrel->non_unique_for_rels = NIL;
     647       93162 :     joinrel->baserestrictinfo = NIL;
     648       93162 :     joinrel->baserestrictcost.startup = 0;
     649       93162 :     joinrel->baserestrictcost.per_tuple = 0;
     650       93162 :     joinrel->baserestrict_min_security = UINT_MAX;
     651       93162 :     joinrel->joininfo = NIL;
     652       93162 :     joinrel->has_eclass_joins = false;
     653       93162 :     joinrel->consider_partitionwise_join = false;    /* might get changed later */
     654       93162 :     joinrel->top_parent_relids = NULL;
     655       93162 :     joinrel->part_scheme = NULL;
     656       93162 :     joinrel->nparts = 0;
     657       93162 :     joinrel->boundinfo = NULL;
     658       93162 :     joinrel->partition_qual = NIL;
     659       93162 :     joinrel->part_rels = NULL;
     660       93162 :     joinrel->partexprs = NULL;
     661       93162 :     joinrel->nullable_partexprs = NULL;
     662       93162 :     joinrel->partitioned_child_rels = NIL;
     663             : 
     664             :     /* Compute information relevant to the foreign relations. */
     665       93162 :     set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
     666             : 
     667             :     /*
     668             :      * Create a new tlist containing just the vars that need to be output from
     669             :      * this join (ie, are needed for higher joinclauses or final output).
     670             :      *
     671             :      * NOTE: the tlist order for a join rel will depend on which pair of outer
     672             :      * and inner rels we first try to build it from.  But the contents should
     673             :      * be the same regardless.
     674             :      */
     675       93162 :     build_joinrel_tlist(root, joinrel, outer_rel);
     676       93162 :     build_joinrel_tlist(root, joinrel, inner_rel);
     677       93162 :     add_placeholders_to_joinrel(root, joinrel, outer_rel, inner_rel);
     678             : 
     679             :     /*
     680             :      * add_placeholders_to_joinrel also took care of adding the ph_lateral
     681             :      * sets of any PlaceHolderVars computed here to direct_lateral_relids, so
     682             :      * now we can finish computing that.  This is much like the computation of
     683             :      * the transitively-closed lateral_relids in min_join_parameterization,
     684             :      * except that here we *do* have to consider the added PHVs.
     685             :      */
     686       93162 :     joinrel->direct_lateral_relids =
     687       93162 :         bms_del_members(joinrel->direct_lateral_relids, joinrel->relids);
     688       93162 :     if (bms_is_empty(joinrel->direct_lateral_relids))
     689       92860 :         joinrel->direct_lateral_relids = NULL;
     690             : 
     691             :     /*
     692             :      * Construct restrict and join clause lists for the new joinrel. (The
     693             :      * caller might or might not need the restrictlist, but I need it anyway
     694             :      * for set_joinrel_size_estimates().)
     695             :      */
     696       93162 :     restrictlist = build_joinrel_restrictlist(root, joinrel,
     697             :                                               outer_rel, inner_rel);
     698       93162 :     if (restrictlist_ptr)
     699       93162 :         *restrictlist_ptr = restrictlist;
     700       93162 :     build_joinrel_joinlist(joinrel, outer_rel, inner_rel);
     701             : 
     702             :     /*
     703             :      * This is also the right place to check whether the joinrel has any
     704             :      * pending EquivalenceClass joins.
     705             :      */
     706       93162 :     joinrel->has_eclass_joins = has_relevant_eclass_joinclause(root, joinrel);
     707             : 
     708             :     /* Store the partition information. */
     709       93162 :     build_joinrel_partition_info(joinrel, outer_rel, inner_rel, restrictlist,
     710             :                                  sjinfo->jointype);
     711             : 
     712             :     /*
     713             :      * Set estimates of the joinrel's size.
     714             :      */
     715       93162 :     set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
     716             :                                sjinfo, restrictlist);
     717             : 
     718             :     /*
     719             :      * Set the consider_parallel flag if this joinrel could potentially be
     720             :      * scanned within a parallel worker.  If this flag is false for either
     721             :      * inner_rel or outer_rel, then it must be false for the joinrel also.
     722             :      * Even if both are true, there might be parallel-restricted expressions
     723             :      * in the targetlist or quals.
     724             :      *
     725             :      * Note that if there are more than two rels in this relation, they could
     726             :      * be divided between inner_rel and outer_rel in any arbitrary way.  We
     727             :      * assume this doesn't matter, because we should hit all the same baserels
     728             :      * and joinclauses while building up to this joinrel no matter which we
     729             :      * take; therefore, we should make the same decision here however we get
     730             :      * here.
     731             :      */
     732      167658 :     if (inner_rel->consider_parallel && outer_rel->consider_parallel &&
     733      148344 :         is_parallel_safe(root, (Node *) restrictlist) &&
     734       73848 :         is_parallel_safe(root, (Node *) joinrel->reltarget->exprs))
     735       73844 :         joinrel->consider_parallel = true;
     736             : 
     737             :     /* Add the joinrel to the PlannerInfo. */
     738       93162 :     add_join_rel(root, joinrel);
     739             : 
     740             :     /*
     741             :      * Also, if dynamic-programming join search is active, add the new joinrel
     742             :      * to the appropriate sublist.  Note: you might think the Assert on number
     743             :      * of members should be for equality, but some of the level 1 rels might
     744             :      * have been joinrels already, so we can only assert <=.
     745             :      */
     746       93162 :     if (root->join_rel_level)
     747             :     {
     748             :         Assert(root->join_cur_level > 0);
     749             :         Assert(root->join_cur_level <= bms_num_members(joinrel->relids));
     750      182196 :         root->join_rel_level[root->join_cur_level] =
     751       91098 :             lappend(root->join_rel_level[root->join_cur_level], joinrel);
     752             :     }
     753             : 
     754       93162 :     return joinrel;
     755             : }
     756             : 
     757             : /*
     758             :  * build_child_join_rel
     759             :  *    Builds RelOptInfo representing join between given two child relations.
     760             :  *
     761             :  * 'outer_rel' and 'inner_rel' are the RelOptInfos of child relations being
     762             :  *      joined
     763             :  * 'parent_joinrel' is the RelOptInfo representing the join between parent
     764             :  *      relations. Some of the members of new RelOptInfo are produced by
     765             :  *      translating corresponding members of this RelOptInfo
     766             :  * 'sjinfo': child-join context info
     767             :  * 'restrictlist': list of RestrictInfo nodes that apply to this particular
     768             :  *      pair of joinable relations
     769             :  * 'jointype' is the join type (inner, left, full, etc)
     770             :  */
     771             : RelOptInfo *
     772        1400 : build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
     773             :                      RelOptInfo *inner_rel, RelOptInfo *parent_joinrel,
     774             :                      List *restrictlist, SpecialJoinInfo *sjinfo,
     775             :                      JoinType jointype)
     776             : {
     777        1400 :     RelOptInfo *joinrel = makeNode(RelOptInfo);
     778             :     AppendRelInfo **appinfos;
     779             :     int         nappinfos;
     780             : 
     781             :     /* Only joins between "other" relations land here. */
     782             :     Assert(IS_OTHER_REL(outer_rel) && IS_OTHER_REL(inner_rel));
     783             : 
     784             :     /* The parent joinrel should have consider_partitionwise_join set. */
     785             :     Assert(parent_joinrel->consider_partitionwise_join);
     786             : 
     787        1400 :     joinrel->reloptkind = RELOPT_OTHER_JOINREL;
     788        1400 :     joinrel->relids = bms_union(outer_rel->relids, inner_rel->relids);
     789        1400 :     joinrel->rows = 0;
     790             :     /* cheap startup cost is interesting iff not all tuples to be retrieved */
     791        1400 :     joinrel->consider_startup = (root->tuple_fraction > 0);
     792        1400 :     joinrel->consider_param_startup = false;
     793        1400 :     joinrel->consider_parallel = false;
     794        1400 :     joinrel->reltarget = create_empty_pathtarget();
     795        1400 :     joinrel->pathlist = NIL;
     796        1400 :     joinrel->ppilist = NIL;
     797        1400 :     joinrel->partial_pathlist = NIL;
     798        1400 :     joinrel->cheapest_startup_path = NULL;
     799        1400 :     joinrel->cheapest_total_path = NULL;
     800        1400 :     joinrel->cheapest_unique_path = NULL;
     801        1400 :     joinrel->cheapest_parameterized_paths = NIL;
     802        1400 :     joinrel->direct_lateral_relids = NULL;
     803        1400 :     joinrel->lateral_relids = NULL;
     804        1400 :     joinrel->relid = 0;          /* indicates not a baserel */
     805        1400 :     joinrel->rtekind = RTE_JOIN;
     806        1400 :     joinrel->min_attr = 0;
     807        1400 :     joinrel->max_attr = 0;
     808        1400 :     joinrel->attr_needed = NULL;
     809        1400 :     joinrel->attr_widths = NULL;
     810        1400 :     joinrel->lateral_vars = NIL;
     811        1400 :     joinrel->lateral_referencers = NULL;
     812        1400 :     joinrel->indexlist = NIL;
     813        1400 :     joinrel->pages = 0;
     814        1400 :     joinrel->tuples = 0;
     815        1400 :     joinrel->allvisfrac = 0;
     816        1400 :     joinrel->eclass_indexes = NULL;
     817        1400 :     joinrel->subroot = NULL;
     818        1400 :     joinrel->subplan_params = NIL;
     819        1400 :     joinrel->serverid = InvalidOid;
     820        1400 :     joinrel->userid = InvalidOid;
     821        1400 :     joinrel->useridiscurrent = false;
     822        1400 :     joinrel->fdwroutine = NULL;
     823        1400 :     joinrel->fdw_private = NULL;
     824        1400 :     joinrel->baserestrictinfo = NIL;
     825        1400 :     joinrel->baserestrictcost.startup = 0;
     826        1400 :     joinrel->baserestrictcost.per_tuple = 0;
     827        1400 :     joinrel->joininfo = NIL;
     828        1400 :     joinrel->has_eclass_joins = false;
     829        1400 :     joinrel->consider_partitionwise_join = false;    /* might get changed later */
     830        1400 :     joinrel->top_parent_relids = NULL;
     831        1400 :     joinrel->part_scheme = NULL;
     832        1400 :     joinrel->nparts = 0;
     833        1400 :     joinrel->boundinfo = NULL;
     834        1400 :     joinrel->partition_qual = NIL;
     835        1400 :     joinrel->part_rels = NULL;
     836        1400 :     joinrel->partexprs = NULL;
     837        1400 :     joinrel->nullable_partexprs = NULL;
     838        1400 :     joinrel->partitioned_child_rels = NIL;
     839             : 
     840        1400 :     joinrel->top_parent_relids = bms_union(outer_rel->top_parent_relids,
     841        1400 :                                            inner_rel->top_parent_relids);
     842             : 
     843             :     /* Compute information relevant to foreign relations. */
     844        1400 :     set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
     845             : 
     846        1400 :     appinfos = find_appinfos_by_relids(root, joinrel->relids, &nappinfos);
     847             : 
     848             :     /* Set up reltarget struct */
     849        1400 :     build_child_join_reltarget(root, parent_joinrel, joinrel,
     850             :                                nappinfos, appinfos);
     851             : 
     852             :     /* Construct joininfo list. */
     853        2800 :     joinrel->joininfo = (List *) adjust_appendrel_attrs(root,
     854        1400 :                                                         (Node *) parent_joinrel->joininfo,
     855             :                                                         nappinfos,
     856             :                                                         appinfos);
     857        1400 :     pfree(appinfos);
     858             : 
     859             :     /*
     860             :      * Lateral relids referred in child join will be same as that referred in
     861             :      * the parent relation.
     862             :      */
     863        1400 :     joinrel->direct_lateral_relids = (Relids) bms_copy(parent_joinrel->direct_lateral_relids);
     864        1400 :     joinrel->lateral_relids = (Relids) bms_copy(parent_joinrel->lateral_relids);
     865             : 
     866             :     /*
     867             :      * If the parent joinrel has pending equivalence classes, so does the
     868             :      * child.
     869             :      */
     870        1400 :     joinrel->has_eclass_joins = parent_joinrel->has_eclass_joins;
     871             : 
     872             :     /* Is the join between partitions itself partitioned? */
     873        1400 :     build_joinrel_partition_info(joinrel, outer_rel, inner_rel, restrictlist,
     874             :                                  jointype);
     875             : 
     876             :     /* Child joinrel is parallel safe if parent is parallel safe. */
     877        1400 :     joinrel->consider_parallel = parent_joinrel->consider_parallel;
     878             : 
     879             :     /* Set estimates of the child-joinrel's size. */
     880        1400 :     set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
     881             :                                sjinfo, restrictlist);
     882             : 
     883             :     /* We build the join only once. */
     884             :     Assert(!find_join_rel(root, joinrel->relids));
     885             : 
     886             :     /* Add the relation to the PlannerInfo. */
     887        1400 :     add_join_rel(root, joinrel);
     888             : 
     889        1400 :     return joinrel;
     890             : }
     891             : 
     892             : /*
     893             :  * min_join_parameterization
     894             :  *
     895             :  * Determine the minimum possible parameterization of a joinrel, that is, the
     896             :  * set of other rels it contains LATERAL references to.  We save this value in
     897             :  * the join's RelOptInfo.  This function is split out of build_join_rel()
     898             :  * because join_is_legal() needs the value to check a prospective join.
     899             :  */
     900             : Relids
     901       96112 : min_join_parameterization(PlannerInfo *root,
     902             :                           Relids joinrelids,
     903             :                           RelOptInfo *outer_rel,
     904             :                           RelOptInfo *inner_rel)
     905             : {
     906             :     Relids      result;
     907             : 
     908             :     /*
     909             :      * Basically we just need the union of the inputs' lateral_relids, less
     910             :      * whatever is already in the join.
     911             :      *
     912             :      * It's not immediately obvious that this is a valid way to compute the
     913             :      * result, because it might seem that we're ignoring possible lateral refs
     914             :      * of PlaceHolderVars that are due to be computed at the join but not in
     915             :      * either input.  However, because create_lateral_join_info() already
     916             :      * charged all such PHV refs to each member baserel of the join, they'll
     917             :      * be accounted for already in the inputs' lateral_relids.  Likewise, we
     918             :      * do not need to worry about doing transitive closure here, because that
     919             :      * was already accounted for in the original baserel lateral_relids.
     920             :      */
     921       96112 :     result = bms_union(outer_rel->lateral_relids, inner_rel->lateral_relids);
     922       96112 :     result = bms_del_members(result, joinrelids);
     923             : 
     924             :     /* Maintain invariant that result is exactly NULL if empty */
     925       96112 :     if (bms_is_empty(result))
     926       95248 :         result = NULL;
     927             : 
     928       96112 :     return result;
     929             : }
     930             : 
     931             : /*
     932             :  * build_joinrel_tlist
     933             :  *    Builds a join relation's target list from an input relation.
     934             :  *    (This is invoked twice to handle the two input relations.)
     935             :  *
     936             :  * The join's targetlist includes all Vars of its member relations that
     937             :  * will still be needed above the join.  This subroutine adds all such
     938             :  * Vars from the specified input rel's tlist to the join rel's tlist.
     939             :  *
     940             :  * We also compute the expected width of the join's output, making use
     941             :  * of data that was cached at the baserel level by set_rel_width().
     942             :  */
     943             : static void
     944      186324 : build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
     945             :                     RelOptInfo *input_rel)
     946             : {
     947      186324 :     Relids      relids = joinrel->relids;
     948             :     ListCell   *vars;
     949             : 
     950     1066592 :     foreach(vars, input_rel->reltarget->exprs)
     951             :     {
     952      880268 :         Var        *var = (Var *) lfirst(vars);
     953             :         RelOptInfo *baserel;
     954             :         int         ndx;
     955             : 
     956             :         /*
     957             :          * Ignore PlaceHolderVars in the input tlists; we'll make our own
     958             :          * decisions about whether to copy them.
     959             :          */
     960      880268 :         if (IsA(var, PlaceHolderVar))
     961         772 :             continue;
     962             : 
     963             :         /*
     964             :          * Otherwise, anything in a baserel or joinrel targetlist ought to be
     965             :          * a Var.  (More general cases can only appear in appendrel child
     966             :          * rels, which will never be seen here.)
     967             :          */
     968      879496 :         if (!IsA(var, Var))
     969           0 :             elog(ERROR, "unexpected node type in rel targetlist: %d",
     970             :                  (int) nodeTag(var));
     971             : 
     972             :         /* Get the Var's original base rel */
     973      879496 :         baserel = find_base_rel(root, var->varno);
     974             : 
     975             :         /* Is it still needed above this joinrel? */
     976      879496 :         ndx = var->varattno - baserel->min_attr;
     977      879496 :         if (bms_nonempty_difference(baserel->attr_needed[ndx], relids))
     978             :         {
     979             :             /* Yup, add it to the output */
     980      742030 :             joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs, var);
     981             :             /* Vars have cost zero, so no need to adjust reltarget->cost */
     982      742030 :             joinrel->reltarget->width += baserel->attr_widths[ndx];
     983             :         }
     984             :     }
     985      186324 : }
     986             : 
     987             : /*
     988             :  * build_joinrel_restrictlist
     989             :  * build_joinrel_joinlist
     990             :  *    These routines build lists of restriction and join clauses for a
     991             :  *    join relation from the joininfo lists of the relations it joins.
     992             :  *
     993             :  *    These routines are separate because the restriction list must be
     994             :  *    built afresh for each pair of input sub-relations we consider, whereas
     995             :  *    the join list need only be computed once for any join RelOptInfo.
     996             :  *    The join list is fully determined by the set of rels making up the
     997             :  *    joinrel, so we should get the same results (up to ordering) from any
     998             :  *    candidate pair of sub-relations.  But the restriction list is whatever
     999             :  *    is not handled in the sub-relations, so it depends on which
    1000             :  *    sub-relations are considered.
    1001             :  *
    1002             :  *    If a join clause from an input relation refers to base rels still not
    1003             :  *    present in the joinrel, then it is still a join clause for the joinrel;
    1004             :  *    we put it into the joininfo list for the joinrel.  Otherwise,
    1005             :  *    the clause is now a restrict clause for the joined relation, and we
    1006             :  *    return it to the caller of build_joinrel_restrictlist() to be stored in
    1007             :  *    join paths made from this pair of sub-relations.  (It will not need to
    1008             :  *    be considered further up the join tree.)
    1009             :  *
    1010             :  *    In many case we will find the same RestrictInfos in both input
    1011             :  *    relations' joinlists, so be careful to eliminate duplicates.
    1012             :  *    Pointer equality should be a sufficient test for dups, since all
    1013             :  *    the various joinlist entries ultimately refer to RestrictInfos
    1014             :  *    pushed into them by distribute_restrictinfo_to_rels().
    1015             :  *
    1016             :  * 'joinrel' is a join relation node
    1017             :  * 'outer_rel' and 'inner_rel' are a pair of relations that can be joined
    1018             :  *      to form joinrel.
    1019             :  *
    1020             :  * build_joinrel_restrictlist() returns a list of relevant restrictinfos,
    1021             :  * whereas build_joinrel_joinlist() stores its results in the joinrel's
    1022             :  * joininfo list.  One or the other must accept each given clause!
    1023             :  *
    1024             :  * NB: Formerly, we made deep(!) copies of each input RestrictInfo to pass
    1025             :  * up to the join relation.  I believe this is no longer necessary, because
    1026             :  * RestrictInfo nodes are no longer context-dependent.  Instead, just include
    1027             :  * the original nodes in the lists made for the join relation.
    1028             :  */
    1029             : static List *
    1030      144472 : build_joinrel_restrictlist(PlannerInfo *root,
    1031             :                            RelOptInfo *joinrel,
    1032             :                            RelOptInfo *outer_rel,
    1033             :                            RelOptInfo *inner_rel)
    1034             : {
    1035             :     List       *result;
    1036             : 
    1037             :     /*
    1038             :      * Collect all the clauses that syntactically belong at this level,
    1039             :      * eliminating any duplicates (important since we will see many of the
    1040             :      * same clauses arriving from both input relations).
    1041             :      */
    1042      144472 :     result = subbuild_joinrel_restrictlist(joinrel, outer_rel->joininfo, NIL);
    1043      144472 :     result = subbuild_joinrel_restrictlist(joinrel, inner_rel->joininfo, result);
    1044             : 
    1045             :     /*
    1046             :      * Add on any clauses derived from EquivalenceClasses.  These cannot be
    1047             :      * redundant with the clauses in the joininfo lists, so don't bother
    1048             :      * checking.
    1049             :      */
    1050      144472 :     result = list_concat(result,
    1051      144472 :                          generate_join_implied_equalities(root,
    1052             :                                                           joinrel->relids,
    1053             :                                                           outer_rel->relids,
    1054             :                                                           inner_rel));
    1055             : 
    1056      144472 :     return result;
    1057             : }
    1058             : 
    1059             : static void
    1060       93162 : build_joinrel_joinlist(RelOptInfo *joinrel,
    1061             :                        RelOptInfo *outer_rel,
    1062             :                        RelOptInfo *inner_rel)
    1063             : {
    1064             :     List       *result;
    1065             : 
    1066             :     /*
    1067             :      * Collect all the clauses that syntactically belong above this level,
    1068             :      * eliminating any duplicates (important since we will see many of the
    1069             :      * same clauses arriving from both input relations).
    1070             :      */
    1071       93162 :     result = subbuild_joinrel_joinlist(joinrel, outer_rel->joininfo, NIL);
    1072       93162 :     result = subbuild_joinrel_joinlist(joinrel, inner_rel->joininfo, result);
    1073             : 
    1074       93162 :     joinrel->joininfo = result;
    1075       93162 : }
    1076             : 
    1077             : static List *
    1078      288944 : subbuild_joinrel_restrictlist(RelOptInfo *joinrel,
    1079             :                               List *joininfo_list,
    1080             :                               List *new_restrictlist)
    1081             : {
    1082             :     ListCell   *l;
    1083             : 
    1084      627414 :     foreach(l, joininfo_list)
    1085             :     {
    1086      338470 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
    1087             : 
    1088      338470 :         if (bms_is_subset(rinfo->required_relids, joinrel->relids))
    1089             :         {
    1090             :             /*
    1091             :              * This clause becomes a restriction clause for the joinrel, since
    1092             :              * it refers to no outside rels.  Add it to the list, being
    1093             :              * careful to eliminate duplicates. (Since RestrictInfo nodes in
    1094             :              * different joinlists will have been multiply-linked rather than
    1095             :              * copied, pointer equality should be a sufficient test.)
    1096             :              */
    1097      210212 :             new_restrictlist = list_append_unique_ptr(new_restrictlist, rinfo);
    1098             :         }
    1099             :         else
    1100             :         {
    1101             :             /*
    1102             :              * This clause is still a join clause at this level, so we ignore
    1103             :              * it in this routine.
    1104             :              */
    1105             :         }
    1106             :     }
    1107             : 
    1108      288944 :     return new_restrictlist;
    1109             : }
    1110             : 
    1111             : static List *
    1112      186324 : subbuild_joinrel_joinlist(RelOptInfo *joinrel,
    1113             :                           List *joininfo_list,
    1114             :                           List *new_joininfo)
    1115             : {
    1116             :     ListCell   *l;
    1117             : 
    1118             :     /* Expected to be called only for join between parent relations. */
    1119             :     Assert(joinrel->reloptkind == RELOPT_JOINREL);
    1120             : 
    1121      399318 :     foreach(l, joininfo_list)
    1122             :     {
    1123      212994 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
    1124             : 
    1125      212994 :         if (bms_is_subset(rinfo->required_relids, joinrel->relids))
    1126             :         {
    1127             :             /*
    1128             :              * This clause becomes a restriction clause for the joinrel, since
    1129             :              * it refers to no outside rels.  So we can ignore it in this
    1130             :              * routine.
    1131             :              */
    1132             :         }
    1133             :         else
    1134             :         {
    1135             :             /*
    1136             :              * This clause is still a join clause at this level, so add it to
    1137             :              * the new joininfo list, being careful to eliminate duplicates.
    1138             :              * (Since RestrictInfo nodes in different joinlists will have been
    1139             :              * multiply-linked rather than copied, pointer equality should be
    1140             :              * a sufficient test.)
    1141             :              */
    1142       74502 :             new_joininfo = list_append_unique_ptr(new_joininfo, rinfo);
    1143             :         }
    1144             :     }
    1145             : 
    1146      186324 :     return new_joininfo;
    1147             : }
    1148             : 
    1149             : 
    1150             : /*
    1151             :  * fetch_upper_rel
    1152             :  *      Build a RelOptInfo describing some post-scan/join query processing,
    1153             :  *      or return a pre-existing one if somebody already built it.
    1154             :  *
    1155             :  * An "upper" relation is identified by an UpperRelationKind and a Relids set.
    1156             :  * The meaning of the Relids set is not specified here, and very likely will
    1157             :  * vary for different relation kinds.
    1158             :  *
    1159             :  * Most of the fields in an upper-level RelOptInfo are not used and are not
    1160             :  * set here (though makeNode should ensure they're zeroes).  We basically only
    1161             :  * care about fields that are of interest to add_path() and set_cheapest().
    1162             :  */
    1163             : RelOptInfo *
    1164      975644 : fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
    1165             : {
    1166             :     RelOptInfo *upperrel;
    1167             :     ListCell   *lc;
    1168             : 
    1169             :     /*
    1170             :      * For the moment, our indexing data structure is just a List for each
    1171             :      * relation kind.  If we ever get so many of one kind that this stops
    1172             :      * working well, we can improve it.  No code outside this function should
    1173             :      * assume anything about how to find a particular upperrel.
    1174             :      */
    1175             : 
    1176             :     /* If we already made this upperrel for the query, return it */
    1177      980566 :     foreach(lc, root->upper_rels[kind])
    1178             :     {
    1179      616398 :         upperrel = (RelOptInfo *) lfirst(lc);
    1180             : 
    1181      616398 :         if (bms_equal(upperrel->relids, relids))
    1182      611476 :             return upperrel;
    1183             :     }
    1184             : 
    1185      364168 :     upperrel = makeNode(RelOptInfo);
    1186      364168 :     upperrel->reloptkind = RELOPT_UPPER_REL;
    1187      364168 :     upperrel->relids = bms_copy(relids);
    1188             : 
    1189             :     /* cheap startup cost is interesting iff not all tuples to be retrieved */
    1190      364168 :     upperrel->consider_startup = (root->tuple_fraction > 0);
    1191      364168 :     upperrel->consider_param_startup = false;
    1192      364168 :     upperrel->consider_parallel = false; /* might get changed later */
    1193      364168 :     upperrel->reltarget = create_empty_pathtarget();
    1194      364168 :     upperrel->pathlist = NIL;
    1195      364168 :     upperrel->cheapest_startup_path = NULL;
    1196      364168 :     upperrel->cheapest_total_path = NULL;
    1197      364168 :     upperrel->cheapest_unique_path = NULL;
    1198      364168 :     upperrel->cheapest_parameterized_paths = NIL;
    1199             : 
    1200      364168 :     root->upper_rels[kind] = lappend(root->upper_rels[kind], upperrel);
    1201             : 
    1202      364168 :     return upperrel;
    1203             : }
    1204             : 
    1205             : 
    1206             : /*
    1207             :  * find_childrel_parents
    1208             :  *      Compute the set of parent relids of an appendrel child rel.
    1209             :  *
    1210             :  * Since appendrels can be nested, a child could have multiple levels of
    1211             :  * appendrel ancestors.  This function computes a Relids set of all the
    1212             :  * parent relation IDs.
    1213             :  */
    1214             : Relids
    1215        5080 : find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
    1216             : {
    1217        5080 :     Relids      result = NULL;
    1218             : 
    1219             :     Assert(rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
    1220             :     Assert(rel->relid > 0 && rel->relid < root->simple_rel_array_size);
    1221             : 
    1222             :     do
    1223             :     {
    1224        6272 :         AppendRelInfo *appinfo = root->append_rel_array[rel->relid];
    1225        6272 :         Index       prelid = appinfo->parent_relid;
    1226             : 
    1227        6272 :         result = bms_add_member(result, prelid);
    1228             : 
    1229             :         /* traverse up to the parent rel, loop if it's also a child rel */
    1230        6272 :         rel = find_base_rel(root, prelid);
    1231        6272 :     } while (rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
    1232             : 
    1233             :     Assert(rel->reloptkind == RELOPT_BASEREL);
    1234             : 
    1235        5080 :     return result;
    1236             : }
    1237             : 
    1238             : 
    1239             : /*
    1240             :  * get_baserel_parampathinfo
    1241             :  *      Get the ParamPathInfo for a parameterized path for a base relation,
    1242             :  *      constructing one if we don't have one already.
    1243             :  *
    1244             :  * This centralizes estimating the rowcounts for parameterized paths.
    1245             :  * We need to cache those to be sure we use the same rowcount for all paths
    1246             :  * of the same parameterization for a given rel.  This is also a convenient
    1247             :  * place to determine which movable join clauses the parameterized path will
    1248             :  * be responsible for evaluating.
    1249             :  */
    1250             : ParamPathInfo *
    1251      915086 : get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel,
    1252             :                           Relids required_outer)
    1253             : {
    1254             :     ParamPathInfo *ppi;
    1255             :     Relids      joinrelids;
    1256             :     List       *pclauses;
    1257             :     double      rows;
    1258             :     ListCell   *lc;
    1259             : 
    1260             :     /* If rel has LATERAL refs, every path for it should account for them */
    1261             :     Assert(bms_is_subset(baserel->lateral_relids, required_outer));
    1262             : 
    1263             :     /* Unparameterized paths have no ParamPathInfo */
    1264      915086 :     if (bms_is_empty(required_outer))
    1265      766238 :         return NULL;
    1266             : 
    1267             :     Assert(!bms_overlap(baserel->relids, required_outer));
    1268             : 
    1269             :     /* If we already have a PPI for this parameterization, just return it */
    1270      148848 :     if ((ppi = find_param_path_info(baserel, required_outer)))
    1271       87264 :         return ppi;
    1272             : 
    1273             :     /*
    1274             :      * Identify all joinclauses that are movable to this base rel given this
    1275             :      * parameterization.
    1276             :      */
    1277       61584 :     joinrelids = bms_union(baserel->relids, required_outer);
    1278       61584 :     pclauses = NIL;
    1279      105646 :     foreach(lc, baserel->joininfo)
    1280             :     {
    1281       44062 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    1282             : 
    1283       44062 :         if (join_clause_is_movable_into(rinfo,
    1284             :                                         baserel->relids,
    1285             :                                         joinrelids))
    1286       27722 :             pclauses = lappend(pclauses, rinfo);
    1287             :     }
    1288             : 
    1289             :     /*
    1290             :      * Add in joinclauses generated by EquivalenceClasses, too.  (These
    1291             :      * necessarily satisfy join_clause_is_movable_into.)
    1292             :      */
    1293       61584 :     pclauses = list_concat(pclauses,
    1294       61584 :                            generate_join_implied_equalities(root,
    1295             :                                                             joinrelids,
    1296             :                                                             required_outer,
    1297             :                                                             baserel));
    1298             : 
    1299             :     /* Estimate the number of rows returned by the parameterized scan */
    1300       61584 :     rows = get_parameterized_baserel_size(root, baserel, pclauses);
    1301             : 
    1302             :     /* And now we can build the ParamPathInfo */
    1303       61584 :     ppi = makeNode(ParamPathInfo);
    1304       61584 :     ppi->ppi_req_outer = required_outer;
    1305       61584 :     ppi->ppi_rows = rows;
    1306       61584 :     ppi->ppi_clauses = pclauses;
    1307       61584 :     baserel->ppilist = lappend(baserel->ppilist, ppi);
    1308             : 
    1309       61584 :     return ppi;
    1310             : }
    1311             : 
    1312             : /*
    1313             :  * get_joinrel_parampathinfo
    1314             :  *      Get the ParamPathInfo for a parameterized path for a join relation,
    1315             :  *      constructing one if we don't have one already.
    1316             :  *
    1317             :  * This centralizes estimating the rowcounts for parameterized paths.
    1318             :  * We need to cache those to be sure we use the same rowcount for all paths
    1319             :  * of the same parameterization for a given rel.  This is also a convenient
    1320             :  * place to determine which movable join clauses the parameterized path will
    1321             :  * be responsible for evaluating.
    1322             :  *
    1323             :  * outer_path and inner_path are a pair of input paths that can be used to
    1324             :  * construct the join, and restrict_clauses is the list of regular join
    1325             :  * clauses (including clauses derived from EquivalenceClasses) that must be
    1326             :  * applied at the join node when using these inputs.
    1327             :  *
    1328             :  * Unlike the situation for base rels, the set of movable join clauses to be
    1329             :  * enforced at a join varies with the selected pair of input paths, so we
    1330             :  * must calculate that and pass it back, even if we already have a matching
    1331             :  * ParamPathInfo.  We handle this by adding any clauses moved down to this
    1332             :  * join to *restrict_clauses, which is an in/out parameter.  (The addition
    1333             :  * is done in such a way as to not modify the passed-in List structure.)
    1334             :  *
    1335             :  * Note: when considering a nestloop join, the caller must have removed from
    1336             :  * restrict_clauses any movable clauses that are themselves scheduled to be
    1337             :  * pushed into the right-hand path.  We do not do that here since it's
    1338             :  * unnecessary for other join types.
    1339             :  */
    1340             : ParamPathInfo *
    1341      818876 : get_joinrel_parampathinfo(PlannerInfo *root, RelOptInfo *joinrel,
    1342             :                           Path *outer_path,
    1343             :                           Path *inner_path,
    1344             :                           SpecialJoinInfo *sjinfo,
    1345             :                           Relids required_outer,
    1346             :                           List **restrict_clauses)
    1347             : {
    1348             :     ParamPathInfo *ppi;
    1349             :     Relids      join_and_req;
    1350             :     Relids      outer_and_req;
    1351             :     Relids      inner_and_req;
    1352             :     List       *pclauses;
    1353             :     List       *eclauses;
    1354             :     List       *dropped_ecs;
    1355             :     double      rows;
    1356             :     ListCell   *lc;
    1357             : 
    1358             :     /* If rel has LATERAL refs, every path for it should account for them */
    1359             :     Assert(bms_is_subset(joinrel->lateral_relids, required_outer));
    1360             : 
    1361             :     /* Unparameterized paths have no ParamPathInfo or extra join clauses */
    1362      818876 :     if (bms_is_empty(required_outer))
    1363      812658 :         return NULL;
    1364             : 
    1365             :     Assert(!bms_overlap(joinrel->relids, required_outer));
    1366             : 
    1367             :     /*
    1368             :      * Identify all joinclauses that are movable to this join rel given this
    1369             :      * parameterization.  These are the clauses that are movable into this
    1370             :      * join, but not movable into either input path.  Treat an unparameterized
    1371             :      * input path as not accepting parameterized clauses (because it won't,
    1372             :      * per the shortcut exit above), even though the joinclause movement rules
    1373             :      * might allow the same clauses to be moved into a parameterized path for
    1374             :      * that rel.
    1375             :      */
    1376        6218 :     join_and_req = bms_union(joinrel->relids, required_outer);
    1377        6218 :     if (outer_path->param_info)
    1378       10012 :         outer_and_req = bms_union(outer_path->parent->relids,
    1379       10012 :                                   PATH_REQ_OUTER(outer_path));
    1380             :     else
    1381        1212 :         outer_and_req = NULL;   /* outer path does not accept parameters */
    1382        6218 :     if (inner_path->param_info)
    1383        6284 :         inner_and_req = bms_union(inner_path->parent->relids,
    1384        6284 :                                   PATH_REQ_OUTER(inner_path));
    1385             :     else
    1386        3076 :         inner_and_req = NULL;   /* inner path does not accept parameters */
    1387             : 
    1388        6218 :     pclauses = NIL;
    1389       12522 :     foreach(lc, joinrel->joininfo)
    1390             :     {
    1391        6304 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    1392             : 
    1393        6304 :         if (join_clause_is_movable_into(rinfo,
    1394             :                                         joinrel->relids,
    1395        4408 :                                         join_and_req) &&
    1396        4408 :             !join_clause_is_movable_into(rinfo,
    1397        4408 :                                          outer_path->parent->relids,
    1398         546 :                                          outer_and_req) &&
    1399         546 :             !join_clause_is_movable_into(rinfo,
    1400         546 :                                          inner_path->parent->relids,
    1401             :                                          inner_and_req))
    1402          48 :             pclauses = lappend(pclauses, rinfo);
    1403             :     }
    1404             : 
    1405             :     /* Consider joinclauses generated by EquivalenceClasses, too */
    1406        6218 :     eclauses = generate_join_implied_equalities(root,
    1407             :                                                 join_and_req,
    1408             :                                                 required_outer,
    1409             :                                                 joinrel);
    1410             :     /* We only want ones that aren't movable to lower levels */
    1411        6218 :     dropped_ecs = NIL;
    1412        7990 :     foreach(lc, eclauses)
    1413             :     {
    1414        1772 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    1415             : 
    1416             :         /*
    1417             :          * In principle, join_clause_is_movable_into() should accept anything
    1418             :          * returned by generate_join_implied_equalities(); but because its
    1419             :          * analysis is only approximate, sometimes it doesn't.  So we
    1420             :          * currently cannot use this Assert; instead just assume it's okay to
    1421             :          * apply the joinclause at this level.
    1422             :          */
    1423             : #ifdef NOT_USED
    1424             :         Assert(join_clause_is_movable_into(rinfo,
    1425             :                                            joinrel->relids,
    1426             :                                            join_and_req));
    1427             : #endif
    1428        1772 :         if (join_clause_is_movable_into(rinfo,
    1429        1772 :                                         outer_path->parent->relids,
    1430             :                                         outer_and_req))
    1431         624 :             continue;           /* drop if movable into LHS */
    1432        1148 :         if (join_clause_is_movable_into(rinfo,
    1433        1148 :                                         inner_path->parent->relids,
    1434             :                                         inner_and_req))
    1435             :         {
    1436             :             /* drop if movable into RHS, but remember EC for use below */
    1437             :             Assert(rinfo->left_ec == rinfo->right_ec);
    1438         812 :             dropped_ecs = lappend(dropped_ecs, rinfo->left_ec);
    1439         812 :             continue;
    1440             :         }
    1441         336 :         pclauses = lappend(pclauses, rinfo);
    1442             :     }
    1443             : 
    1444             :     /*
    1445             :      * EquivalenceClasses are harder to deal with than we could wish, because
    1446             :      * of the fact that a given EC can generate different clauses depending on
    1447             :      * context.  Suppose we have an EC {X.X, Y.Y, Z.Z} where X and Y are the
    1448             :      * LHS and RHS of the current join and Z is in required_outer, and further
    1449             :      * suppose that the inner_path is parameterized by both X and Z.  The code
    1450             :      * above will have produced either Z.Z = X.X or Z.Z = Y.Y from that EC,
    1451             :      * and in the latter case will have discarded it as being movable into the
    1452             :      * RHS.  However, the EC machinery might have produced either Y.Y = X.X or
    1453             :      * Y.Y = Z.Z as the EC enforcement clause within the inner_path; it will
    1454             :      * not have produced both, and we can't readily tell from here which one
    1455             :      * it did pick.  If we add no clause to this join, we'll end up with
    1456             :      * insufficient enforcement of the EC; either Z.Z or X.X will fail to be
    1457             :      * constrained to be equal to the other members of the EC.  (When we come
    1458             :      * to join Z to this X/Y path, we will certainly drop whichever EC clause
    1459             :      * is generated at that join, so this omission won't get fixed later.)
    1460             :      *
    1461             :      * To handle this, for each EC we discarded such a clause from, try to
    1462             :      * generate a clause connecting the required_outer rels to the join's LHS
    1463             :      * ("Z.Z = X.X" in the terms of the above example).  If successful, and if
    1464             :      * the clause can't be moved to the LHS, add it to the current join's
    1465             :      * restriction clauses.  (If an EC cannot generate such a clause then it
    1466             :      * has nothing that needs to be enforced here, while if the clause can be
    1467             :      * moved into the LHS then it should have been enforced within that path.)
    1468             :      *
    1469             :      * Note that we don't need similar processing for ECs whose clause was
    1470             :      * considered to be movable into the LHS, because the LHS can't refer to
    1471             :      * the RHS so there is no comparable ambiguity about what it might
    1472             :      * actually be enforcing internally.
    1473             :      */
    1474        6218 :     if (dropped_ecs)
    1475             :     {
    1476             :         Relids      real_outer_and_req;
    1477             : 
    1478         792 :         real_outer_and_req = bms_union(outer_path->parent->relids,
    1479             :                                        required_outer);
    1480         792 :         eclauses =
    1481         792 :             generate_join_implied_equalities_for_ecs(root,
    1482             :                                                      dropped_ecs,
    1483             :                                                      real_outer_and_req,
    1484             :                                                      required_outer,
    1485             :                                                      outer_path->parent);
    1486         820 :         foreach(lc, eclauses)
    1487             :         {
    1488          28 :             RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    1489             : 
    1490             :             /* As above, can't quite assert this here */
    1491             : #ifdef NOT_USED
    1492             :             Assert(join_clause_is_movable_into(rinfo,
    1493             :                                                outer_path->parent->relids,
    1494             :                                                real_outer_and_req));
    1495             : #endif
    1496          28 :             if (!join_clause_is_movable_into(rinfo,
    1497          28 :                                              outer_path->parent->relids,
    1498             :                                              outer_and_req))
    1499          20 :                 pclauses = lappend(pclauses, rinfo);
    1500             :         }
    1501             :     }
    1502             : 
    1503             :     /*
    1504             :      * Now, attach the identified moved-down clauses to the caller's
    1505             :      * restrict_clauses list.  By using list_concat in this order, we leave
    1506             :      * the original list structure of restrict_clauses undamaged.
    1507             :      */
    1508        6218 :     *restrict_clauses = list_concat(pclauses, *restrict_clauses);
    1509             : 
    1510             :     /* If we already have a PPI for this parameterization, just return it */
    1511        6218 :     if ((ppi = find_param_path_info(joinrel, required_outer)))
    1512        4326 :         return ppi;
    1513             : 
    1514             :     /* Estimate the number of rows returned by the parameterized join */
    1515        1892 :     rows = get_parameterized_joinrel_size(root, joinrel,
    1516             :                                           outer_path,
    1517             :                                           inner_path,
    1518             :                                           sjinfo,
    1519             :                                           *restrict_clauses);
    1520             : 
    1521             :     /*
    1522             :      * And now we can build the ParamPathInfo.  No point in saving the
    1523             :      * input-pair-dependent clause list, though.
    1524             :      *
    1525             :      * Note: in GEQO mode, we'll be called in a temporary memory context, but
    1526             :      * the joinrel structure is there too, so no problem.
    1527             :      */
    1528        1892 :     ppi = makeNode(ParamPathInfo);
    1529        1892 :     ppi->ppi_req_outer = required_outer;
    1530        1892 :     ppi->ppi_rows = rows;
    1531        1892 :     ppi->ppi_clauses = NIL;
    1532        1892 :     joinrel->ppilist = lappend(joinrel->ppilist, ppi);
    1533             : 
    1534        1892 :     return ppi;
    1535             : }
    1536             : 
    1537             : /*
    1538             :  * get_appendrel_parampathinfo
    1539             :  *      Get the ParamPathInfo for a parameterized path for an append relation.
    1540             :  *
    1541             :  * For an append relation, the rowcount estimate will just be the sum of
    1542             :  * the estimates for its children.  However, we still need a ParamPathInfo
    1543             :  * to flag the fact that the path requires parameters.  So this just creates
    1544             :  * a suitable struct with zero ppi_rows (and no ppi_clauses either, since
    1545             :  * the Append node isn't responsible for checking quals).
    1546             :  */
    1547             : ParamPathInfo *
    1548       18184 : get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer)
    1549             : {
    1550             :     ParamPathInfo *ppi;
    1551             : 
    1552             :     /* If rel has LATERAL refs, every path for it should account for them */
    1553             :     Assert(bms_is_subset(appendrel->lateral_relids, required_outer));
    1554             : 
    1555             :     /* Unparameterized paths have no ParamPathInfo */
    1556       18184 :     if (bms_is_empty(required_outer))
    1557       17744 :         return NULL;
    1558             : 
    1559             :     Assert(!bms_overlap(appendrel->relids, required_outer));
    1560             : 
    1561             :     /* If we already have a PPI for this parameterization, just return it */
    1562         440 :     if ((ppi = find_param_path_info(appendrel, required_outer)))
    1563          64 :         return ppi;
    1564             : 
    1565             :     /* Else build the ParamPathInfo */
    1566         376 :     ppi = makeNode(ParamPathInfo);
    1567         376 :     ppi->ppi_req_outer = required_outer;
    1568         376 :     ppi->ppi_rows = 0;
    1569         376 :     ppi->ppi_clauses = NIL;
    1570         376 :     appendrel->ppilist = lappend(appendrel->ppilist, ppi);
    1571             : 
    1572         376 :     return ppi;
    1573             : }
    1574             : 
    1575             : /*
    1576             :  * Returns a ParamPathInfo for the parameterization given by required_outer, if
    1577             :  * already available in the given rel. Returns NULL otherwise.
    1578             :  */
    1579             : ParamPathInfo *
    1580      157542 : find_param_path_info(RelOptInfo *rel, Relids required_outer)
    1581             : {
    1582             :     ListCell   *lc;
    1583             : 
    1584      171664 :     foreach(lc, rel->ppilist)
    1585             :     {
    1586      106856 :         ParamPathInfo *ppi = (ParamPathInfo *) lfirst(lc);
    1587             : 
    1588      106856 :         if (bms_equal(ppi->ppi_req_outer, required_outer))
    1589       92734 :             return ppi;
    1590             :     }
    1591             : 
    1592       64808 :     return NULL;
    1593             : }
    1594             : 
    1595             : /*
    1596             :  * build_joinrel_partition_info
    1597             :  *      If the two relations have same partitioning scheme, their join may be
    1598             :  *      partitioned and will follow the same partitioning scheme as the joining
    1599             :  *      relations. Set the partition scheme and partition key expressions in
    1600             :  *      the join relation.
    1601             :  */
    1602             : static void
    1603       94562 : build_joinrel_partition_info(RelOptInfo *joinrel, RelOptInfo *outer_rel,
    1604             :                              RelOptInfo *inner_rel, List *restrictlist,
    1605             :                              JoinType jointype)
    1606             : {
    1607             :     int         partnatts;
    1608             :     int         cnt;
    1609             :     PartitionScheme part_scheme;
    1610             : 
    1611             :     /* Nothing to do if partitionwise join technique is disabled. */
    1612       94562 :     if (!enable_partitionwise_join)
    1613             :     {
    1614             :         Assert(!IS_PARTITIONED_REL(joinrel));
    1615       92502 :         return;
    1616             :     }
    1617             : 
    1618             :     /*
    1619             :      * We can only consider this join as an input to further partitionwise
    1620             :      * joins if (a) the input relations are partitioned and have
    1621             :      * consider_partitionwise_join=true, (b) the partition schemes match, and
    1622             :      * (c) we can identify an equi-join between the partition keys.  Note that
    1623             :      * if it were possible for have_partkey_equi_join to return different
    1624             :      * answers for the same joinrel depending on which join ordering we try
    1625             :      * first, this logic would break.  That shouldn't happen, though, because
    1626             :      * of the way the query planner deduces implied equalities and reorders
    1627             :      * the joins.  Please see optimizer/README for details.
    1628             :      */
    1629        2740 :     if (!IS_PARTITIONED_REL(outer_rel) || !IS_PARTITIONED_REL(inner_rel) ||
    1630        1328 :         !outer_rel->consider_partitionwise_join ||
    1631        1296 :         !inner_rel->consider_partitionwise_join ||
    1632        1280 :         outer_rel->part_scheme != inner_rel->part_scheme ||
    1633         632 :         !have_partkey_equi_join(joinrel, outer_rel, inner_rel,
    1634             :                                 jointype, restrictlist))
    1635             :     {
    1636             :         Assert(!IS_PARTITIONED_REL(joinrel));
    1637        1504 :         return;
    1638             :     }
    1639             : 
    1640         556 :     part_scheme = outer_rel->part_scheme;
    1641             : 
    1642             :     Assert(REL_HAS_ALL_PART_PROPS(outer_rel) &&
    1643             :            REL_HAS_ALL_PART_PROPS(inner_rel));
    1644             : 
    1645             :     /*
    1646             :      * For now, our partition matching algorithm can match partitions only
    1647             :      * when the partition bounds of the joining relations are exactly same.
    1648             :      * So, bail out otherwise.
    1649             :      */
    1650        1108 :     if (outer_rel->nparts != inner_rel->nparts ||
    1651         552 :         !partition_bounds_equal(part_scheme->partnatts,
    1652             :                                 part_scheme->parttyplen,
    1653             :                                 part_scheme->parttypbyval,
    1654             :                                 outer_rel->boundinfo, inner_rel->boundinfo))
    1655             :     {
    1656             :         Assert(!IS_PARTITIONED_REL(joinrel));
    1657          20 :         return;
    1658             :     }
    1659             : 
    1660             :     /*
    1661             :      * This function will be called only once for each joinrel, hence it
    1662             :      * should not have partition scheme, partition bounds, partition key
    1663             :      * expressions and array for storing child relations set.
    1664             :      */
    1665             :     Assert(!joinrel->part_scheme && !joinrel->partexprs &&
    1666             :            !joinrel->nullable_partexprs && !joinrel->part_rels &&
    1667             :            !joinrel->boundinfo);
    1668             : 
    1669             :     /*
    1670             :      * Join relation is partitioned using the same partitioning scheme as the
    1671             :      * joining relations and has same bounds.
    1672             :      */
    1673         536 :     joinrel->part_scheme = part_scheme;
    1674         536 :     joinrel->boundinfo = outer_rel->boundinfo;
    1675         536 :     partnatts = joinrel->part_scheme->partnatts;
    1676         536 :     joinrel->partexprs = (List **) palloc0(sizeof(List *) * partnatts);
    1677         536 :     joinrel->nullable_partexprs =
    1678         536 :         (List **) palloc0(sizeof(List *) * partnatts);
    1679         536 :     joinrel->nparts = outer_rel->nparts;
    1680         536 :     joinrel->part_rels =
    1681         536 :         (RelOptInfo **) palloc0(sizeof(RelOptInfo *) * joinrel->nparts);
    1682             : 
    1683             :     /*
    1684             :      * Set the consider_partitionwise_join flag.
    1685             :      */
    1686             :     Assert(outer_rel->consider_partitionwise_join);
    1687             :     Assert(inner_rel->consider_partitionwise_join);
    1688         536 :     joinrel->consider_partitionwise_join = true;
    1689             : 
    1690             :     /*
    1691             :      * Construct partition keys for the join.
    1692             :      *
    1693             :      * An INNER join between two partitioned relations can be regarded as
    1694             :      * partitioned by either key expression.  For example, A INNER JOIN B ON
    1695             :      * A.a = B.b can be regarded as partitioned on A.a or on B.b; they are
    1696             :      * equivalent.
    1697             :      *
    1698             :      * For a SEMI or ANTI join, the result can only be regarded as being
    1699             :      * partitioned in the same manner as the outer side, since the inner
    1700             :      * columns are not retained.
    1701             :      *
    1702             :      * An OUTER join like (A LEFT JOIN B ON A.a = B.b) may produce rows with
    1703             :      * B.b NULL. These rows may not fit the partitioning conditions imposed on
    1704             :      * B.b. Hence, strictly speaking, the join is not partitioned by B.b and
    1705             :      * thus partition keys of an OUTER join should include partition key
    1706             :      * expressions from the OUTER side only.  However, because all
    1707             :      * commonly-used comparison operators are strict, the presence of nulls on
    1708             :      * the outer side doesn't cause any problem; they can't match anything at
    1709             :      * future join levels anyway.  Therefore, we track two sets of
    1710             :      * expressions: those that authentically partition the relation
    1711             :      * (partexprs) and those that partition the relation with the exception
    1712             :      * that extra nulls may be present (nullable_partexprs).  When the
    1713             :      * comparison operator is strict, the latter is just as good as the
    1714             :      * former.
    1715             :      */
    1716        1080 :     for (cnt = 0; cnt < partnatts; cnt++)
    1717             :     {
    1718             :         /* mark these const to enforce that we copy them properly */
    1719         544 :         const List *outer_expr = outer_rel->partexprs[cnt];
    1720         544 :         const List *outer_null_expr = outer_rel->nullable_partexprs[cnt];
    1721         544 :         const List *inner_expr = inner_rel->partexprs[cnt];
    1722         544 :         const List *inner_null_expr = inner_rel->nullable_partexprs[cnt];
    1723         544 :         List       *partexpr = NIL;
    1724         544 :         List       *nullable_partexpr = NIL;
    1725             : 
    1726         544 :         switch (jointype)
    1727             :         {
    1728             :             case JOIN_INNER:
    1729         224 :                 partexpr = list_concat_copy(outer_expr, inner_expr);
    1730         224 :                 nullable_partexpr = list_concat_copy(outer_null_expr,
    1731             :                                                      inner_null_expr);
    1732         224 :                 break;
    1733             : 
    1734             :             case JOIN_SEMI:
    1735             :             case JOIN_ANTI:
    1736          56 :                 partexpr = list_copy(outer_expr);
    1737          56 :                 nullable_partexpr = list_copy(outer_null_expr);
    1738          56 :                 break;
    1739             : 
    1740             :             case JOIN_LEFT:
    1741         180 :                 partexpr = list_copy(outer_expr);
    1742         180 :                 nullable_partexpr = list_concat_copy(inner_expr,
    1743             :                                                      outer_null_expr);
    1744         180 :                 nullable_partexpr = list_concat(nullable_partexpr,
    1745             :                                                 inner_null_expr);
    1746         180 :                 break;
    1747             : 
    1748             :             case JOIN_FULL:
    1749          84 :                 nullable_partexpr = list_concat_copy(outer_expr,
    1750             :                                                      inner_expr);
    1751          84 :                 nullable_partexpr = list_concat(nullable_partexpr,
    1752             :                                                 outer_null_expr);
    1753          84 :                 nullable_partexpr = list_concat(nullable_partexpr,
    1754             :                                                 inner_null_expr);
    1755          84 :                 break;
    1756             : 
    1757             :             default:
    1758           0 :                 elog(ERROR, "unrecognized join type: %d", (int) jointype);
    1759             : 
    1760             :         }
    1761             : 
    1762         544 :         joinrel->partexprs[cnt] = partexpr;
    1763         544 :         joinrel->nullable_partexprs[cnt] = nullable_partexpr;
    1764             :     }
    1765             : }
    1766             : 
    1767             : /*
    1768             :  * build_child_join_reltarget
    1769             :  *    Set up a child-join relation's reltarget from a parent-join relation.
    1770             :  */
    1771             : static void
    1772        1400 : build_child_join_reltarget(PlannerInfo *root,
    1773             :                            RelOptInfo *parentrel,
    1774             :                            RelOptInfo *childrel,
    1775             :                            int nappinfos,
    1776             :                            AppendRelInfo **appinfos)
    1777             : {
    1778             :     /* Build the targetlist */
    1779        2800 :     childrel->reltarget->exprs = (List *)
    1780        1400 :         adjust_appendrel_attrs(root,
    1781        1400 :                                (Node *) parentrel->reltarget->exprs,
    1782             :                                nappinfos, appinfos);
    1783             : 
    1784             :     /* Set the cost and width fields */
    1785        1400 :     childrel->reltarget->cost.startup = parentrel->reltarget->cost.startup;
    1786        1400 :     childrel->reltarget->cost.per_tuple = parentrel->reltarget->cost.per_tuple;
    1787        1400 :     childrel->reltarget->width = parentrel->reltarget->width;
    1788        1400 : }

Generated by: LCOV version 1.13