LCOV - differential code coverage report
Current view: top level - src/backend/optimizer/util - relnode.c (source / functions) Coverage Total Hit UNC LBC UIC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 96.2 % 798 768 12 8 10 5 415 141 207 25 507 46
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 29 29 24 5 26 3
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * relnode.c
       4                 :  *    Relation-node lookup/construction routines
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2023, 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 "nodes/nodeFuncs.h"
      21                 : #include "optimizer/appendinfo.h"
      22                 : #include "optimizer/clauses.h"
      23                 : #include "optimizer/cost.h"
      24                 : #include "optimizer/inherit.h"
      25                 : #include "optimizer/pathnode.h"
      26                 : #include "optimizer/paths.h"
      27                 : #include "optimizer/placeholder.h"
      28                 : #include "optimizer/plancat.h"
      29                 : #include "optimizer/restrictinfo.h"
      30                 : #include "optimizer/tlist.h"
      31                 : #include "rewrite/rewriteManip.h"
      32                 : #include "parser/parse_relation.h"
      33                 : #include "utils/hsearch.h"
      34                 : #include "utils/lsyscache.h"
      35                 : 
      36                 : 
      37                 : typedef struct JoinHashEntry
      38                 : {
      39                 :     Relids      join_relids;    /* hash key --- MUST BE FIRST */
      40                 :     RelOptInfo *join_rel;
      41                 : } JoinHashEntry;
      42                 : 
      43                 : static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
      44                 :                                 RelOptInfo *input_rel,
      45                 :                                 SpecialJoinInfo *sjinfo,
      46                 :                                 bool can_null);
      47                 : static List *build_joinrel_restrictlist(PlannerInfo *root,
      48                 :                                         RelOptInfo *joinrel,
      49                 :                                         RelOptInfo *outer_rel,
      50                 :                                         RelOptInfo *inner_rel,
      51                 :                                         SpecialJoinInfo *sjinfo);
      52                 : static void build_joinrel_joinlist(RelOptInfo *joinrel,
      53                 :                                    RelOptInfo *outer_rel,
      54                 :                                    RelOptInfo *inner_rel);
      55                 : static List *subbuild_joinrel_restrictlist(PlannerInfo *root,
      56                 :                                            RelOptInfo *joinrel,
      57                 :                                            RelOptInfo *input_rel,
      58                 :                                            Relids both_input_relids,
      59                 :                                            List *new_restrictlist);
      60                 : static List *subbuild_joinrel_joinlist(RelOptInfo *joinrel,
      61                 :                                        List *joininfo_list,
      62                 :                                        List *new_joininfo);
      63                 : static void set_foreign_rel_properties(RelOptInfo *joinrel,
      64                 :                                        RelOptInfo *outer_rel, RelOptInfo *inner_rel);
      65                 : static void add_join_rel(PlannerInfo *root, RelOptInfo *joinrel);
      66                 : static void build_joinrel_partition_info(PlannerInfo *root,
      67                 :                                          RelOptInfo *joinrel,
      68                 :                                          RelOptInfo *outer_rel, RelOptInfo *inner_rel,
      69                 :                                          SpecialJoinInfo *sjinfo,
      70                 :                                          List *restrictlist);
      71                 : static bool have_partkey_equi_join(PlannerInfo *root, RelOptInfo *joinrel,
      72                 :                                    RelOptInfo *rel1, RelOptInfo *rel2,
      73                 :                                    JoinType jointype, List *restrictlist);
      74                 : static int  match_expr_to_partition_keys(Expr *expr, RelOptInfo *rel,
      75                 :                                          bool strict_op);
      76                 : static void set_joinrel_partition_key_exprs(RelOptInfo *joinrel,
      77                 :                                             RelOptInfo *outer_rel, RelOptInfo *inner_rel,
      78                 :                                             JoinType jointype);
      79                 : static void build_child_join_reltarget(PlannerInfo *root,
      80                 :                                        RelOptInfo *parentrel,
      81                 :                                        RelOptInfo *childrel,
      82                 :                                        int nappinfos,
      83                 :                                        AppendRelInfo **appinfos);
      84                 : 
      85                 : 
      86                 : /*
      87                 :  * setup_simple_rel_arrays
      88                 :  *    Prepare the arrays we use for quickly accessing base relations
      89                 :  *    and AppendRelInfos.
      90                 :  */
      91                 : void
      92 GIC      240087 : setup_simple_rel_arrays(PlannerInfo *root)
      93                 : {
      94                 :     int         size;
      95                 :     Index       rti;
      96                 :     ListCell   *lc;
      97                 : 
      98                 :     /* Arrays are accessed using RT indexes (1..N) */
      99          240087 :     size = list_length(root->parse->rtable) + 1;
     100          240087 :     root->simple_rel_array_size = size;
     101 ECB             : 
     102                 :     /*
     103                 :      * simple_rel_array is initialized to all NULLs, since no RelOptInfos
     104                 :      * exist yet.  It'll be filled by later calls to build_simple_rel().
     105                 :      */
     106 GIC      240087 :     root->simple_rel_array = (RelOptInfo **)
     107          240087 :         palloc0(size * sizeof(RelOptInfo *));
     108 ECB             : 
     109                 :     /* simple_rte_array is an array equivalent of the rtable list */
     110 GIC      240087 :     root->simple_rte_array = (RangeTblEntry **)
     111          240087 :         palloc0(size * sizeof(RangeTblEntry *));
     112          240087 :     rti = 1;
     113          631721 :     foreach(lc, root->parse->rtable)
     114                 :     {
     115 CBC      391634 :         RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
     116 ECB             : 
     117 GIC      391634 :         root->simple_rte_array[rti++] = rte;
     118                 :     }
     119 ECB             : 
     120                 :     /* append_rel_array is not needed if there are no AppendRelInfos */
     121 CBC      240087 :     if (root->append_rel_list == NIL)
     122 ECB             :     {
     123 GIC      239368 :         root->append_rel_array = NULL;
     124 CBC      239368 :         return;
     125                 :     }
     126 ECB             : 
     127 GIC         719 :     root->append_rel_array = (AppendRelInfo **)
     128             719 :         palloc0(size * sizeof(AppendRelInfo *));
     129                 : 
     130 ECB             :     /*
     131                 :      * append_rel_array is filled with any already-existing AppendRelInfos,
     132                 :      * which currently could only come from UNION ALL flattening.  We might
     133                 :      * add more later during inheritance expansion, but it's the
     134                 :      * responsibility of the expansion code to update the array properly.
     135                 :      */
     136 CBC        2487 :     foreach(lc, root->append_rel_list)
     137 ECB             :     {
     138 GIC        1768 :         AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
     139            1768 :         int         child_relid = appinfo->child_relid;
     140                 : 
     141                 :         /* Sanity check */
     142            1768 :         Assert(child_relid < size);
     143                 : 
     144            1768 :         if (root->append_rel_array[child_relid])
     145 LBC           0 :             elog(ERROR, "child relation already exists");
     146                 : 
     147 CBC        1768 :         root->append_rel_array[child_relid] = appinfo;
     148 ECB             :     }
     149                 : }
     150                 : 
     151                 : /*
     152                 :  * expand_planner_arrays
     153                 :  *      Expand the PlannerInfo's per-RTE arrays by add_size members
     154 EUB             :  *      and initialize the newly added entries to NULLs
     155                 :  *
     156 ECB             :  * Note: this causes the append_rel_array to become allocated even if
     157                 :  * it was not before.  This is okay for current uses, because we only call
     158                 :  * this when adding child relations, which always have AppendRelInfos.
     159                 :  */
     160                 : void
     161 GIC        8433 : expand_planner_arrays(PlannerInfo *root, int add_size)
     162                 : {
     163                 :     int         new_size;
     164                 : 
     165            8433 :     Assert(add_size > 0);
     166                 : 
     167            8433 :     new_size = root->simple_rel_array_size + add_size;
     168                 : 
     169 GNC        8433 :     root->simple_rel_array =
     170            8433 :         repalloc0_array(root->simple_rel_array, RelOptInfo *, root->simple_rel_array_size, new_size);
     171 ECB             : 
     172 GNC        8433 :     root->simple_rte_array =
     173            8433 :         repalloc0_array(root->simple_rte_array, RangeTblEntry *, root->simple_rel_array_size, new_size);
     174                 : 
     175 CBC        8433 :     if (root->append_rel_array)
     176 GNC        2431 :         root->append_rel_array =
     177            2431 :             repalloc0_array(root->append_rel_array, AppendRelInfo *, root->simple_rel_array_size, new_size);
     178 ECB             :     else
     179 GNC        6002 :         root->append_rel_array =
     180            6002 :             palloc0_array(AppendRelInfo *, new_size);
     181                 : 
     182 GIC        8433 :     root->simple_rel_array_size = new_size;
     183            8433 : }
     184                 : 
     185                 : /*
     186 ECB             :  * build_simple_rel
     187                 :  *    Construct a new RelOptInfo for a base relation or 'other' relation.
     188                 :  */
     189                 : RelOptInfo *
     190 GIC      315683 : build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
     191                 : {
     192 ECB             :     RelOptInfo *rel;
     193                 :     RangeTblEntry *rte;
     194 EUB             : 
     195                 :     /* Rel should not exist already */
     196 GIC      315683 :     Assert(relid > 0 && relid < root->simple_rel_array_size);
     197 CBC      315683 :     if (root->simple_rel_array[relid] != NULL)
     198 LBC           0 :         elog(ERROR, "rel %d already exists", relid);
     199                 : 
     200 ECB             :     /* Fetch RTE for relation */
     201 CBC      315683 :     rte = root->simple_rte_array[relid];
     202          315683 :     Assert(rte != NULL);
     203 ECB             : 
     204 GIC      315683 :     rel = makeNode(RelOptInfo);
     205 CBC      315683 :     rel->reloptkind = parent ? RELOPT_OTHER_MEMBER_REL : RELOPT_BASEREL;
     206          315683 :     rel->relids = bms_make_singleton(relid);
     207          315683 :     rel->rows = 0;
     208 ECB             :     /* cheap startup cost is interesting iff not all tuples to be retrieved */
     209 CBC      315683 :     rel->consider_startup = (root->tuple_fraction > 0);
     210          315683 :     rel->consider_param_startup = false; /* might get changed later */
     211          315683 :     rel->consider_parallel = false; /* might get changed later */
     212          315683 :     rel->reltarget = create_empty_pathtarget();
     213          315683 :     rel->pathlist = NIL;
     214          315683 :     rel->ppilist = NIL;
     215          315683 :     rel->partial_pathlist = NIL;
     216          315683 :     rel->cheapest_startup_path = NULL;
     217          315683 :     rel->cheapest_total_path = NULL;
     218 GIC      315683 :     rel->cheapest_unique_path = NULL;
     219 CBC      315683 :     rel->cheapest_parameterized_paths = NIL;
     220          315683 :     rel->relid = relid;
     221          315683 :     rel->rtekind = rte->rtekind;
     222 ECB             :     /* min_attr, max_attr, attr_needed, attr_widths are set below */
     223 CBC      315683 :     rel->lateral_vars = NIL;
     224          315683 :     rel->indexlist = NIL;
     225          315683 :     rel->statlist = NIL;
     226          315683 :     rel->pages = 0;
     227          315683 :     rel->tuples = 0;
     228          315683 :     rel->allvisfrac = 0;
     229          315683 :     rel->eclass_indexes = NULL;
     230          315683 :     rel->subroot = NULL;
     231          315683 :     rel->subplan_params = NIL;
     232 GIC      315683 :     rel->rel_parallel_workers = -1; /* set up in get_relation_info */
     233 CBC      315683 :     rel->amflags = 0;
     234 GIC      315683 :     rel->serverid = InvalidOid;
     235 GNC      315683 :     if (rte->rtekind == RTE_RELATION)
     236                 :     {
     237          185453 :         Assert(parent == NULL ||
     238                 :                parent->rtekind == RTE_RELATION ||
     239                 :                parent->rtekind == RTE_SUBQUERY);
     240                 : 
     241                 :         /*
     242                 :          * For any RELATION rte, we need a userid with which to check
     243                 :          * permission access. Baserels simply use their own
     244                 :          * RTEPermissionInfo's checkAsUser.
     245                 :          *
     246                 :          * For otherrels normally there's no RTEPermissionInfo, so we use the
     247                 :          * parent's, which normally has one. The exceptional case is that the
     248                 :          * parent is a subquery, in which case the otherrel will have its own.
     249                 :          */
     250          185453 :         if (rel->reloptkind == RELOPT_BASEREL ||
     251           18338 :             (rel->reloptkind == RELOPT_OTHER_MEMBER_REL &&
     252           18338 :              parent->rtekind == RTE_SUBQUERY))
     253          167631 :         {
     254                 :             RTEPermissionInfo *perminfo;
     255                 : 
     256          167631 :             perminfo = getRTEPermissionInfo(root->parse->rteperminfos, rte);
     257          167631 :             rel->userid = perminfo->checkAsUser;
     258                 :         }
     259                 :         else
     260           17822 :             rel->userid = parent->userid;
     261                 :     }
     262                 :     else
     263          130230 :         rel->userid = InvalidOid;
     264 GIC      315683 :     rel->useridiscurrent = false;
     265          315683 :     rel->fdwroutine = NULL;
     266          315683 :     rel->fdw_private = NULL;
     267          315683 :     rel->unique_for_rels = NIL;
     268          315683 :     rel->non_unique_for_rels = NIL;
     269          315683 :     rel->baserestrictinfo = NIL;
     270          315683 :     rel->baserestrictcost.startup = 0;
     271          315683 :     rel->baserestrictcost.per_tuple = 0;
     272          315683 :     rel->baserestrict_min_security = UINT_MAX;
     273          315683 :     rel->joininfo = NIL;
     274 CBC      315683 :     rel->has_eclass_joins = false;
     275          315683 :     rel->consider_partitionwise_join = false;    /* might get changed later */
     276          315683 :     rel->part_scheme = NULL;
     277          315683 :     rel->nparts = -1;
     278 GIC      315683 :     rel->boundinfo = NULL;
     279          315683 :     rel->partbounds_merged = false;
     280 CBC      315683 :     rel->partition_qual = NIL;
     281          315683 :     rel->part_rels = NULL;
     282 GIC      315683 :     rel->live_parts = NULL;
     283          315683 :     rel->all_partrels = NULL;
     284 CBC      315683 :     rel->partexprs = NULL;
     285 GIC      315683 :     rel->nullable_partexprs = NULL;
     286                 : 
     287 ECB             :     /*
     288                 :      * Pass assorted information down the inheritance hierarchy.
     289                 :      */
     290 CBC      315683 :     if (parent)
     291 ECB             :     {
     292                 :         /* We keep back-links to immediate parent and topmost parent. */
     293 GNC       19590 :         rel->parent = parent;
     294           19590 :         rel->top_parent = parent->top_parent ? parent->top_parent : parent;
     295           19590 :         rel->top_parent_relids = rel->top_parent->relids;
     296                 : 
     297 ECB             :         /*
     298                 :          * A child rel is below the same outer joins as its parent.  (We
     299                 :          * presume this info was already calculated for the parent.)
     300                 :          */
     301 GNC       19590 :         rel->nulling_relids = parent->nulling_relids;
     302 ECB             : 
     303                 :         /*
     304                 :          * Also propagate lateral-reference information from appendrel parent
     305                 :          * rels to their child rels.  We intentionally give each child rel the
     306                 :          * same minimum parameterization, even though it's quite possible that
     307                 :          * some don't reference all the lateral rels.  This is because any
     308                 :          * append path for the parent will have to have the same
     309                 :          * parameterization for every child anyway, and there's no value in
     310                 :          * forcing extra reparameterize_path() calls.  Similarly, a lateral
     311                 :          * reference to the parent prevents use of otherwise-movable join rels
     312                 :          * for each child.
     313                 :          *
     314                 :          * It's possible for child rels to have their own children, in which
     315                 :          * case the topmost parent's lateral info propagates all the way down.
     316                 :          */
     317 GIC       19590 :         rel->direct_lateral_relids = parent->direct_lateral_relids;
     318           19590 :         rel->lateral_relids = parent->lateral_relids;
     319 CBC       19590 :         rel->lateral_referencers = parent->lateral_referencers;
     320 ECB             :     }
     321                 :     else
     322                 :     {
     323 GNC      296093 :         rel->parent = NULL;
     324          296093 :         rel->top_parent = NULL;
     325 GIC      296093 :         rel->top_parent_relids = NULL;
     326 GNC      296093 :         rel->nulling_relids = NULL;
     327 GIC      296093 :         rel->direct_lateral_relids = NULL;
     328          296093 :         rel->lateral_relids = NULL;
     329          296093 :         rel->lateral_referencers = NULL;
     330 ECB             :     }
     331                 : 
     332                 :     /* Check type of rtable entry */
     333 GIC      315683 :     switch (rte->rtekind)
     334                 :     {
     335          185453 :         case RTE_RELATION:
     336                 :             /* Table --- retrieve statistics from the system catalogs */
     337          185453 :             get_relation_info(root, rte->relid, rte->inh, rel);
     338          185446 :             break;
     339           34308 :         case RTE_SUBQUERY:
     340                 :         case RTE_FUNCTION:
     341                 :         case RTE_TABLEFUNC:
     342                 :         case RTE_VALUES:
     343                 :         case RTE_CTE:
     344                 :         case RTE_NAMEDTUPLESTORE:
     345                 : 
     346 ECB             :             /*
     347                 :              * Subquery, function, tablefunc, values list, CTE, or ENR --- set
     348                 :              * up attr range and arrays
     349                 :              *
     350                 :              * Note: 0 is included in range to support whole-row Vars
     351                 :              */
     352 CBC       34308 :             rel->min_attr = 0;
     353           34308 :             rel->max_attr = list_length(rte->eref->colnames);
     354           34308 :             rel->attr_needed = (Relids *)
     355           34308 :                 palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids));
     356           34308 :             rel->attr_widths = (int32 *)
     357           34308 :                 palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32));
     358           34308 :             break;
     359 GIC       95922 :         case RTE_RESULT:
     360                 :             /* RTE_RESULT has no columns, nor could it have whole-row Var */
     361           95922 :             rel->min_attr = 0;
     362 CBC       95922 :             rel->max_attr = -1;
     363 GIC       95922 :             rel->attr_needed = NULL;
     364 CBC       95922 :             rel->attr_widths = NULL;
     365 GIC       95922 :             break;
     366 LBC           0 :         default:
     367               0 :             elog(ERROR, "unrecognized RTE kind: %d",
     368 ECB             :                  (int) rte->rtekind);
     369                 :             break;
     370                 :     }
     371                 : 
     372                 :     /*
     373                 :      * Copy the parent's quals to the child, with appropriate substitution of
     374                 :      * variables.  If any constant false or NULL clauses turn up, we can mark
     375                 :      * the child as dummy right away.  (We must do this immediately so that
     376                 :      * pruning works correctly when recursing in expand_partitioned_rtentry.)
     377                 :      */
     378 GIC      315676 :     if (parent)
     379                 :     {
     380           19590 :         AppendRelInfo *appinfo = root->append_rel_array[relid];
     381 ECB             : 
     382 CBC       19590 :         Assert(appinfo != NULL);
     383           19590 :         if (!apply_child_basequals(root, parent, rel, rte, appinfo))
     384 ECB             :         {
     385                 :             /*
     386                 :              * Some restriction clause reduced to constant FALSE or NULL after
     387                 :              * substitution, so this child need not be scanned.
     388                 :              */
     389 GIC          39 :             mark_dummy_rel(rel);
     390 ECB             :         }
     391                 :     }
     392                 : 
     393                 :     /* Save the finished struct in the query's simple_rel_array */
     394 CBC      315676 :     root->simple_rel_array[relid] = rel;
     395 EUB             : 
     396 GBC      315676 :     return rel;
     397                 : }
     398                 : 
     399                 : /*
     400                 :  * find_base_rel
     401                 :  *    Find a base or otherrel relation entry, which must already exist.
     402                 :  */
     403                 : RelOptInfo *
     404 GIC     2797883 : find_base_rel(PlannerInfo *root, int relid)
     405                 : {
     406                 :     RelOptInfo *rel;
     407 ECB             : 
     408 GIC     2797883 :     Assert(relid > 0);
     409 ECB             : 
     410 GIC     2797883 :     if (relid < root->simple_rel_array_size)
     411 ECB             :     {
     412 CBC     2797883 :         rel = root->simple_rel_array[relid];
     413 GIC     2797883 :         if (rel)
     414         2797883 :             return rel;
     415                 :     }
     416                 : 
     417 UIC           0 :     elog(ERROR, "no relation entry for relid %d", relid);
     418 ECB             : 
     419                 :     return NULL;                /* keep compiler quiet */
     420                 : }
     421                 : 
     422                 : /*
     423                 :  * find_base_rel_ignore_join
     424                 :  *    Find a base or otherrel relation entry, which must already exist.
     425                 :  *
     426                 :  * Unlike find_base_rel, if relid references an outer join then this
     427                 :  * will return NULL rather than raising an error.  This is convenient
     428                 :  * for callers that must deal with relid sets including both base and
     429                 :  * outer joins.
     430                 :  */
     431                 : RelOptInfo *
     432 GNC       73288 : find_base_rel_ignore_join(PlannerInfo *root, int relid)
     433                 : {
     434           73288 :     Assert(relid > 0);
     435                 : 
     436           73288 :     if (relid < root->simple_rel_array_size)
     437                 :     {
     438                 :         RelOptInfo *rel;
     439                 :         RangeTblEntry *rte;
     440                 : 
     441           73288 :         rel = root->simple_rel_array[relid];
     442           73288 :         if (rel)
     443           65207 :             return rel;
     444                 : 
     445                 :         /*
     446                 :          * We could just return NULL here, but for debugging purposes it seems
     447                 :          * best to actually verify that the relid is an outer join and not
     448                 :          * something weird.
     449                 :          */
     450            8081 :         rte = root->simple_rte_array[relid];
     451            8081 :         if (rte && rte->rtekind == RTE_JOIN && rte->jointype != JOIN_INNER)
     452            8081 :             return NULL;
     453                 :     }
     454                 : 
     455 UNC           0 :     elog(ERROR, "no relation entry for relid %d", relid);
     456                 : 
     457                 :     return NULL;                /* keep compiler quiet */
     458                 : }
     459                 : 
     460                 : /*
     461 ECB             :  * build_join_rel_hash
     462                 :  *    Construct the auxiliary hash table for join relations.
     463                 :  */
     464                 : static void
     465 GIC          19 : build_join_rel_hash(PlannerInfo *root)
     466                 : {
     467                 :     HTAB       *hashtab;
     468                 :     HASHCTL     hash_ctl;
     469                 :     ListCell   *l;
     470                 : 
     471 ECB             :     /* Create the hash table */
     472 GIC          19 :     hash_ctl.keysize = sizeof(Relids);
     473              19 :     hash_ctl.entrysize = sizeof(JoinHashEntry);
     474              19 :     hash_ctl.hash = bitmap_hash;
     475 CBC          19 :     hash_ctl.match = bitmap_match;
     476 GIC          19 :     hash_ctl.hcxt = CurrentMemoryContext;
     477 CBC          19 :     hashtab = hash_create("JoinRelHashTable",
     478                 :                           256L,
     479 ECB             :                           &hash_ctl,
     480                 :                           HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT);
     481                 : 
     482                 :     /* Insert all the already-existing joinrels */
     483 GIC         646 :     foreach(l, root->join_rel_list)
     484 EUB             :     {
     485 GIC         627 :         RelOptInfo *rel = (RelOptInfo *) lfirst(l);
     486                 :         JoinHashEntry *hentry;
     487                 :         bool        found;
     488                 : 
     489             627 :         hentry = (JoinHashEntry *) hash_search(hashtab,
     490             627 :                                                &(rel->relids),
     491                 :                                                HASH_ENTER,
     492                 :                                                &found);
     493             627 :         Assert(!found);
     494             627 :         hentry->join_rel = rel;
     495                 :     }
     496                 : 
     497              19 :     root->join_rel_hash = hashtab;
     498              19 : }
     499 ECB             : 
     500                 : /*
     501                 :  * find_join_rel
     502                 :  *    Returns relation entry corresponding to 'relids' (a set of RT indexes),
     503                 :  *    or NULL if none exists.  This is for join relations.
     504                 :  */
     505                 : RelOptInfo *
     506 GIC      118080 : find_join_rel(PlannerInfo *root, Relids relids)
     507                 : {
     508 ECB             :     /*
     509                 :      * Switch to using hash lookup when list grows "too long".  The threshold
     510                 :      * is arbitrary and is known only here.
     511                 :      */
     512 GIC      118080 :     if (!root->join_rel_hash && list_length(root->join_rel_list) > 32)
     513              19 :         build_join_rel_hash(root);
     514                 : 
     515                 :     /*
     516                 :      * Use either hashtable lookup or linear search, as appropriate.
     517 ECB             :      *
     518                 :      * Note: the seemingly redundant hashkey variable is used to avoid taking
     519                 :      * the address of relids; unless the compiler is exceedingly smart, doing
     520                 :      * so would force relids out of a register and thus probably slow down the
     521                 :      * list-search case.
     522 EUB             :      */
     523 GIC      118080 :     if (root->join_rel_hash)
     524                 :     {
     525            1812 :         Relids      hashkey = relids;
     526                 :         JoinHashEntry *hentry;
     527                 : 
     528            1812 :         hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
     529                 :                                                &hashkey,
     530                 :                                                HASH_FIND,
     531                 :                                                NULL);
     532 CBC        1812 :         if (hentry)
     533 GIC        1602 :             return hentry->join_rel;
     534                 :     }
     535                 :     else
     536                 :     {
     537                 :         ListCell   *l;
     538                 : 
     539 CBC      680268 :         foreach(l, root->join_rel_list)
     540 ECB             :         {
     541 CBC      602911 :             RelOptInfo *rel = (RelOptInfo *) lfirst(l);
     542 ECB             : 
     543 CBC      602911 :             if (bms_equal(rel->relids, relids))
     544           38911 :                 return rel;
     545                 :         }
     546                 :     }
     547                 : 
     548 GIC       77567 :     return NULL;
     549                 : }
     550 ECB             : 
     551                 : /*
     552                 :  * set_foreign_rel_properties
     553                 :  *      Set up foreign-join fields if outer and inner relation are foreign
     554                 :  *      tables (or joins) belonging to the same server and assigned to the same
     555                 :  *      user to check access permissions as.
     556                 :  *
     557                 :  * In addition to an exact match of userid, we allow the case where one side
     558                 :  * has zero userid (implying current user) and the other side has explicit
     559                 :  * userid that happens to equal the current user; but in that case, pushdown of
     560                 :  * the join is only valid for the current user.  The useridiscurrent field
     561                 :  * records whether we had to make such an assumption for this join or any
     562                 :  * sub-join.
     563                 :  *
     564                 :  * Otherwise these fields are left invalid, so GetForeignJoinPaths will not be
     565                 :  * called for the join relation.
     566                 :  */
     567                 : static void
     568 GIC       76713 : set_foreign_rel_properties(RelOptInfo *joinrel, RelOptInfo *outer_rel,
     569                 :                            RelOptInfo *inner_rel)
     570                 : {
     571           76713 :     if (OidIsValid(outer_rel->serverid) &&
     572 CBC         292 :         inner_rel->serverid == outer_rel->serverid)
     573                 :     {
     574 GIC         256 :         if (inner_rel->userid == outer_rel->userid)
     575                 :         {
     576             250 :             joinrel->serverid = outer_rel->serverid;
     577             250 :             joinrel->userid = outer_rel->userid;
     578 CBC         250 :             joinrel->useridiscurrent = outer_rel->useridiscurrent || inner_rel->useridiscurrent;
     579             250 :             joinrel->fdwroutine = outer_rel->fdwroutine;
     580                 :         }
     581 GIC          10 :         else if (!OidIsValid(inner_rel->userid) &&
     582               4 :                  outer_rel->userid == GetUserId())
     583                 :         {
     584               2 :             joinrel->serverid = outer_rel->serverid;
     585               2 :             joinrel->userid = outer_rel->userid;
     586               2 :             joinrel->useridiscurrent = true;
     587               2 :             joinrel->fdwroutine = outer_rel->fdwroutine;
     588                 :         }
     589 CBC           4 :         else if (!OidIsValid(outer_rel->userid) &&
     590 UIC           0 :                  inner_rel->userid == GetUserId())
     591 ECB             :         {
     592 UIC           0 :             joinrel->serverid = outer_rel->serverid;
     593               0 :             joinrel->userid = inner_rel->userid;
     594 LBC           0 :             joinrel->useridiscurrent = true;
     595 UIC           0 :             joinrel->fdwroutine = outer_rel->fdwroutine;
     596                 :         }
     597                 :     }
     598 CBC       76713 : }
     599 ECB             : 
     600                 : /*
     601                 :  * add_join_rel
     602                 :  *      Add given join relation to the list of join relations in the given
     603                 :  *      PlannerInfo. Also add it to the auxiliary hashtable if there is one.
     604                 :  */
     605                 : static void
     606 GIC       76713 : add_join_rel(PlannerInfo *root, RelOptInfo *joinrel)
     607 ECB             : {
     608                 :     /* GEQO requires us to append the new joinrel to the end of the list! */
     609 CBC       76713 :     root->join_rel_list = lappend(root->join_rel_list, joinrel);
     610 ECB             : 
     611                 :     /* store it into the auxiliary hashtable if there is one. */
     612 GIC       76713 :     if (root->join_rel_hash)
     613                 :     {
     614 ECB             :         JoinHashEntry *hentry;
     615                 :         bool        found;
     616                 : 
     617 GIC         210 :         hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
     618             210 :                                                &(joinrel->relids),
     619                 :                                                HASH_ENTER,
     620                 :                                                &found);
     621             210 :         Assert(!found);
     622             210 :         hentry->join_rel = joinrel;
     623                 :     }
     624           76713 : }
     625                 : 
     626                 : /*
     627                 :  * build_join_rel
     628                 :  *    Returns relation entry corresponding to the union of two given rels,
     629                 :  *    creating a new relation entry if none already exists.
     630                 :  *
     631                 :  * 'joinrelids' is the Relids set that uniquely identifies the join
     632                 :  * 'outer_rel' and 'inner_rel' are relation nodes for the relations to be
     633                 :  *      joined
     634 ECB             :  * 'sjinfo': join context info
     635                 :  * 'restrictlist_ptr': result variable.  If not NULL, *restrictlist_ptr
     636                 :  *      receives the list of RestrictInfo nodes that apply to this
     637                 :  *      particular pair of joinable relations.
     638                 :  *
     639                 :  * restrictlist_ptr makes the routine's API a little grotty, but it saves
     640                 :  * duplicated calculation of the restrictlist...
     641                 :  */
     642                 : RelOptInfo *
     643 CBC      114035 : build_join_rel(PlannerInfo *root,
     644 ECB             :                Relids joinrelids,
     645                 :                RelOptInfo *outer_rel,
     646                 :                RelOptInfo *inner_rel,
     647                 :                SpecialJoinInfo *sjinfo,
     648                 :                List **restrictlist_ptr)
     649                 : {
     650                 :     RelOptInfo *joinrel;
     651                 :     List       *restrictlist;
     652                 : 
     653                 :     /* This function should be used only for join between parents. */
     654 GIC      114035 :     Assert(!IS_OTHER_REL(outer_rel) && !IS_OTHER_REL(inner_rel));
     655 ECB             : 
     656 EUB             :     /*
     657                 :      * See if we already have a joinrel for this set of base rels.
     658                 :      */
     659 GBC      114035 :     joinrel = find_join_rel(root, joinrelids);
     660 EUB             : 
     661 GBC      114035 :     if (joinrel)
     662                 :     {
     663                 :         /*
     664 ECB             :          * Yes, so we only need to figure the restrictlist for this particular
     665                 :          * pair of component relations.
     666                 :          */
     667 GIC       39472 :         if (restrictlist_ptr)
     668           39472 :             *restrictlist_ptr = build_joinrel_restrictlist(root,
     669                 :                                                            joinrel,
     670                 :                                                            outer_rel,
     671                 :                                                            inner_rel,
     672                 :                                                            sjinfo);
     673 CBC       39472 :         return joinrel;
     674                 :     }
     675                 : 
     676 ECB             :     /*
     677                 :      * Nope, so make one.
     678                 :      */
     679 CBC       74563 :     joinrel = makeNode(RelOptInfo);
     680 GIC       74563 :     joinrel->reloptkind = RELOPT_JOINREL;
     681           74563 :     joinrel->relids = bms_copy(joinrelids);
     682           74563 :     joinrel->rows = 0;
     683                 :     /* cheap startup cost is interesting iff not all tuples to be retrieved */
     684 CBC       74563 :     joinrel->consider_startup = (root->tuple_fraction > 0);
     685           74563 :     joinrel->consider_param_startup = false;
     686 GIC       74563 :     joinrel->consider_parallel = false;
     687           74563 :     joinrel->reltarget = create_empty_pathtarget();
     688 CBC       74563 :     joinrel->pathlist = NIL;
     689           74563 :     joinrel->ppilist = NIL;
     690 GIC       74563 :     joinrel->partial_pathlist = NIL;
     691 CBC       74563 :     joinrel->cheapest_startup_path = NULL;
     692 GIC       74563 :     joinrel->cheapest_total_path = NULL;
     693           74563 :     joinrel->cheapest_unique_path = NULL;
     694           74563 :     joinrel->cheapest_parameterized_paths = NIL;
     695                 :     /* init direct_lateral_relids from children; we'll finish it up below */
     696           74563 :     joinrel->direct_lateral_relids =
     697           74563 :         bms_union(outer_rel->direct_lateral_relids,
     698           74563 :                   inner_rel->direct_lateral_relids);
     699           74563 :     joinrel->lateral_relids = min_join_parameterization(root, joinrel->relids,
     700                 :                                                         outer_rel, inner_rel);
     701           74563 :     joinrel->relid = 0;          /* indicates not a baserel */
     702           74563 :     joinrel->rtekind = RTE_JOIN;
     703           74563 :     joinrel->min_attr = 0;
     704           74563 :     joinrel->max_attr = 0;
     705           74563 :     joinrel->attr_needed = NULL;
     706           74563 :     joinrel->attr_widths = NULL;
     707 GNC       74563 :     joinrel->nulling_relids = NULL;
     708 GIC       74563 :     joinrel->lateral_vars = NIL;
     709           74563 :     joinrel->lateral_referencers = NULL;
     710           74563 :     joinrel->indexlist = NIL;
     711 CBC       74563 :     joinrel->statlist = NIL;
     712 GIC       74563 :     joinrel->pages = 0;
     713           74563 :     joinrel->tuples = 0;
     714           74563 :     joinrel->allvisfrac = 0;
     715           74563 :     joinrel->eclass_indexes = NULL;
     716           74563 :     joinrel->subroot = NULL;
     717           74563 :     joinrel->subplan_params = NIL;
     718           74563 :     joinrel->rel_parallel_workers = -1;
     719           74563 :     joinrel->amflags = 0;
     720           74563 :     joinrel->serverid = InvalidOid;
     721           74563 :     joinrel->userid = InvalidOid;
     722 CBC       74563 :     joinrel->useridiscurrent = false;
     723 GIC       74563 :     joinrel->fdwroutine = NULL;
     724           74563 :     joinrel->fdw_private = NULL;
     725           74563 :     joinrel->unique_for_rels = NIL;
     726           74563 :     joinrel->non_unique_for_rels = NIL;
     727 CBC       74563 :     joinrel->baserestrictinfo = NIL;
     728 GIC       74563 :     joinrel->baserestrictcost.startup = 0;
     729 CBC       74563 :     joinrel->baserestrictcost.per_tuple = 0;
     730 GIC       74563 :     joinrel->baserestrict_min_security = UINT_MAX;
     731           74563 :     joinrel->joininfo = NIL;
     732           74563 :     joinrel->has_eclass_joins = false;
     733           74563 :     joinrel->consider_partitionwise_join = false;    /* might get changed later */
     734 GNC       74563 :     joinrel->parent = NULL;
     735           74563 :     joinrel->top_parent = NULL;
     736 GIC       74563 :     joinrel->top_parent_relids = NULL;
     737 CBC       74563 :     joinrel->part_scheme = NULL;
     738           74563 :     joinrel->nparts = -1;
     739 GIC       74563 :     joinrel->boundinfo = NULL;
     740           74563 :     joinrel->partbounds_merged = false;
     741           74563 :     joinrel->partition_qual = NIL;
     742           74563 :     joinrel->part_rels = NULL;
     743 CBC       74563 :     joinrel->live_parts = NULL;
     744 GIC       74563 :     joinrel->all_partrels = NULL;
     745           74563 :     joinrel->partexprs = NULL;
     746           74563 :     joinrel->nullable_partexprs = NULL;
     747                 : 
     748                 :     /* Compute information relevant to the foreign relations. */
     749 CBC       74563 :     set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
     750 ECB             : 
     751                 :     /*
     752                 :      * Fill the joinrel's tlist with just the Vars and PHVs that need to be
     753                 :      * output from this join (ie, are needed for higher joinclauses or final
     754                 :      * output).
     755                 :      *
     756                 :      * NOTE: the tlist order for a join rel will depend on which pair of outer
     757                 :      * and inner rels we first try to build it from.  But the contents should
     758                 :      * be the same regardless.
     759                 :      */
     760 GNC       74563 :     build_joinrel_tlist(root, joinrel, outer_rel, sjinfo,
     761           74563 :                         (sjinfo->jointype == JOIN_FULL));
     762           74563 :     build_joinrel_tlist(root, joinrel, inner_rel, sjinfo,
     763           74563 :                         (sjinfo->jointype != JOIN_INNER));
     764           74563 :     add_placeholders_to_joinrel(root, joinrel, outer_rel, inner_rel, sjinfo);
     765 ECB             : 
     766                 :     /*
     767                 :      * add_placeholders_to_joinrel also took care of adding the ph_lateral
     768                 :      * sets of any PlaceHolderVars computed here to direct_lateral_relids, so
     769                 :      * now we can finish computing that.  This is much like the computation of
     770                 :      * the transitively-closed lateral_relids in min_join_parameterization,
     771                 :      * except that here we *do* have to consider the added PHVs.
     772                 :      */
     773 GIC       74563 :     joinrel->direct_lateral_relids =
     774 CBC       74563 :         bms_del_members(joinrel->direct_lateral_relids, joinrel->relids);
     775 ECB             : 
     776                 :     /*
     777                 :      * Construct restrict and join clause lists for the new joinrel. (The
     778                 :      * caller might or might not need the restrictlist, but I need it anyway
     779                 :      * for set_joinrel_size_estimates().)
     780                 :      */
     781 CBC       74563 :     restrictlist = build_joinrel_restrictlist(root, joinrel,
     782                 :                                               outer_rel, inner_rel,
     783                 :                                               sjinfo);
     784           74563 :     if (restrictlist_ptr)
     785           74563 :         *restrictlist_ptr = restrictlist;
     786           74563 :     build_joinrel_joinlist(joinrel, outer_rel, inner_rel);
     787 ECB             : 
     788                 :     /*
     789                 :      * This is also the right place to check whether the joinrel has any
     790                 :      * pending EquivalenceClass joins.
     791                 :      */
     792 CBC       74563 :     joinrel->has_eclass_joins = has_relevant_eclass_joinclause(root, joinrel);
     793 ECB             : 
     794                 :     /* Store the partition information. */
     795 GNC       74563 :     build_joinrel_partition_info(root, joinrel, outer_rel, inner_rel, sjinfo,
     796                 :                                  restrictlist);
     797 ECB             : 
     798                 :     /*
     799                 :      * Set estimates of the joinrel's size.
     800                 :      */
     801 CBC       74563 :     set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
     802 ECB             :                                sjinfo, restrictlist);
     803                 : 
     804                 :     /*
     805                 :      * Set the consider_parallel flag if this joinrel could potentially be
     806                 :      * scanned within a parallel worker.  If this flag is false for either
     807                 :      * inner_rel or outer_rel, then it must be false for the joinrel also.
     808                 :      * Even if both are true, there might be parallel-restricted expressions
     809                 :      * in the targetlist or quals.
     810                 :      *
     811                 :      * Note that if there are more than two rels in this relation, they could
     812                 :      * be divided between inner_rel and outer_rel in any arbitrary way.  We
     813                 :      * assume this doesn't matter, because we should hit all the same baserels
     814                 :      * and joinclauses while building up to this joinrel no matter which we
     815                 :      * take; therefore, we should make the same decision here however we get
     816                 :      * here.
     817                 :      */
     818 CBC      134166 :     if (inner_rel->consider_parallel && outer_rel->consider_parallel &&
     819 GIC      119051 :         is_parallel_safe(root, (Node *) restrictlist) &&
     820           59448 :         is_parallel_safe(root, (Node *) joinrel->reltarget->exprs))
     821 CBC       59445 :         joinrel->consider_parallel = true;
     822                 : 
     823                 :     /* Add the joinrel to the PlannerInfo. */
     824 GIC       74563 :     add_join_rel(root, joinrel);
     825                 : 
     826                 :     /*
     827                 :      * Also, if dynamic-programming join search is active, add the new joinrel
     828                 :      * to the appropriate sublist.  Note: you might think the Assert on number
     829                 :      * of members should be for equality, but some of the level 1 rels might
     830                 :      * have been joinrels already, so we can only assert <=.
     831                 :      */
     832 CBC       74563 :     if (root->join_rel_level)
     833 ECB             :     {
     834 CBC       73015 :         Assert(root->join_cur_level > 0);
     835           73015 :         Assert(root->join_cur_level <= bms_num_members(joinrel->relids));
     836           73015 :         root->join_rel_level[root->join_cur_level] =
     837 GIC       73015 :             lappend(root->join_rel_level[root->join_cur_level], joinrel);
     838                 :     }
     839                 : 
     840           74563 :     return joinrel;
     841                 : }
     842                 : 
     843                 : /*
     844                 :  * build_child_join_rel
     845 ECB             :  *    Builds RelOptInfo representing join between given two child relations.
     846                 :  *
     847                 :  * 'outer_rel' and 'inner_rel' are the RelOptInfos of child relations being
     848                 :  *      joined
     849                 :  * 'parent_joinrel' is the RelOptInfo representing the join between parent
     850                 :  *      relations. Some of the members of new RelOptInfo are produced by
     851                 :  *      translating corresponding members of this RelOptInfo
     852                 :  * 'restrictlist': list of RestrictInfo nodes that apply to this particular
     853                 :  *      pair of joinable relations
     854                 :  * 'sjinfo': child join's join-type details
     855                 :  */
     856                 : RelOptInfo *
     857 CBC        2150 : build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
     858                 :                      RelOptInfo *inner_rel, RelOptInfo *parent_joinrel,
     859                 :                      List *restrictlist, SpecialJoinInfo *sjinfo)
     860                 : {
     861 GIC        2150 :     RelOptInfo *joinrel = makeNode(RelOptInfo);
     862 ECB             :     AppendRelInfo **appinfos;
     863                 :     int         nappinfos;
     864                 : 
     865                 :     /* Only joins between "other" relations land here. */
     866 GIC        2150 :     Assert(IS_OTHER_REL(outer_rel) && IS_OTHER_REL(inner_rel));
     867                 : 
     868                 :     /* The parent joinrel should have consider_partitionwise_join set. */
     869            2150 :     Assert(parent_joinrel->consider_partitionwise_join);
     870                 : 
     871 CBC        2150 :     joinrel->reloptkind = RELOPT_OTHER_JOINREL;
     872 GIC        2150 :     joinrel->relids = bms_union(outer_rel->relids, inner_rel->relids);
     873 GNC        2150 :     if (sjinfo->ojrelid != 0)
     874            1014 :         joinrel->relids = bms_add_member(joinrel->relids, sjinfo->ojrelid);
     875 GIC        2150 :     joinrel->rows = 0;
     876                 :     /* cheap startup cost is interesting iff not all tuples to be retrieved */
     877            2150 :     joinrel->consider_startup = (root->tuple_fraction > 0);
     878            2150 :     joinrel->consider_param_startup = false;
     879            2150 :     joinrel->consider_parallel = false;
     880            2150 :     joinrel->reltarget = create_empty_pathtarget();
     881            2150 :     joinrel->pathlist = NIL;
     882            2150 :     joinrel->ppilist = NIL;
     883            2150 :     joinrel->partial_pathlist = NIL;
     884            2150 :     joinrel->cheapest_startup_path = NULL;
     885            2150 :     joinrel->cheapest_total_path = NULL;
     886            2150 :     joinrel->cheapest_unique_path = NULL;
     887            2150 :     joinrel->cheapest_parameterized_paths = NIL;
     888            2150 :     joinrel->direct_lateral_relids = NULL;
     889            2150 :     joinrel->lateral_relids = NULL;
     890 CBC        2150 :     joinrel->relid = 0;          /* indicates not a baserel */
     891            2150 :     joinrel->rtekind = RTE_JOIN;
     892            2150 :     joinrel->min_attr = 0;
     893            2150 :     joinrel->max_attr = 0;
     894 GIC        2150 :     joinrel->attr_needed = NULL;
     895            2150 :     joinrel->attr_widths = NULL;
     896 GNC        2150 :     joinrel->nulling_relids = NULL;
     897 CBC        2150 :     joinrel->lateral_vars = NIL;
     898 GIC        2150 :     joinrel->lateral_referencers = NULL;
     899            2150 :     joinrel->indexlist = NIL;
     900            2150 :     joinrel->pages = 0;
     901            2150 :     joinrel->tuples = 0;
     902            2150 :     joinrel->allvisfrac = 0;
     903            2150 :     joinrel->eclass_indexes = NULL;
     904            2150 :     joinrel->subroot = NULL;
     905 CBC        2150 :     joinrel->subplan_params = NIL;
     906 GIC        2150 :     joinrel->amflags = 0;
     907 CBC        2150 :     joinrel->serverid = InvalidOid;
     908            2150 :     joinrel->userid = InvalidOid;
     909            2150 :     joinrel->useridiscurrent = false;
     910            2150 :     joinrel->fdwroutine = NULL;
     911 GIC        2150 :     joinrel->fdw_private = NULL;
     912            2150 :     joinrel->baserestrictinfo = NIL;
     913 CBC        2150 :     joinrel->baserestrictcost.startup = 0;
     914 GIC        2150 :     joinrel->baserestrictcost.per_tuple = 0;
     915            2150 :     joinrel->joininfo = NIL;
     916            2150 :     joinrel->has_eclass_joins = false;
     917            2150 :     joinrel->consider_partitionwise_join = false;    /* might get changed later */
     918 GNC        2150 :     joinrel->parent = parent_joinrel;
     919            2150 :     joinrel->top_parent = parent_joinrel->top_parent ? parent_joinrel->top_parent : parent_joinrel;
     920            2150 :     joinrel->top_parent_relids = joinrel->top_parent->relids;
     921 GIC        2150 :     joinrel->part_scheme = NULL;
     922            2150 :     joinrel->nparts = -1;
     923            2150 :     joinrel->boundinfo = NULL;
     924            2150 :     joinrel->partbounds_merged = false;
     925            2150 :     joinrel->partition_qual = NIL;
     926            2150 :     joinrel->part_rels = NULL;
     927            2150 :     joinrel->live_parts = NULL;
     928            2150 :     joinrel->all_partrels = NULL;
     929            2150 :     joinrel->partexprs = NULL;
     930            2150 :     joinrel->nullable_partexprs = NULL;
     931                 : 
     932                 :     /* Compute information relevant to foreign relations. */
     933 CBC        2150 :     set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
     934                 : 
     935                 :     /* Compute information needed for mapping Vars to the child rel */
     936 GIC        2150 :     appinfos = find_appinfos_by_relids(root, joinrel->relids, &nappinfos);
     937                 : 
     938 ECB             :     /* Set up reltarget struct */
     939 GIC        2150 :     build_child_join_reltarget(root, parent_joinrel, joinrel,
     940                 :                                nappinfos, appinfos);
     941 ECB             : 
     942                 :     /* Construct joininfo list. */
     943 CBC        4300 :     joinrel->joininfo = (List *) adjust_appendrel_attrs(root,
     944            2150 :                                                         (Node *) parent_joinrel->joininfo,
     945 ECB             :                                                         nappinfos,
     946                 :                                                         appinfos);
     947                 : 
     948                 :     /*
     949                 :      * Lateral relids referred in child join will be same as that referred in
     950                 :      * the parent relation.
     951                 :      */
     952 CBC        2150 :     joinrel->direct_lateral_relids = (Relids) bms_copy(parent_joinrel->direct_lateral_relids);
     953            2150 :     joinrel->lateral_relids = (Relids) bms_copy(parent_joinrel->lateral_relids);
     954 ECB             : 
     955                 :     /*
     956                 :      * If the parent joinrel has pending equivalence classes, so does the
     957                 :      * child.
     958                 :      */
     959 CBC        2150 :     joinrel->has_eclass_joins = parent_joinrel->has_eclass_joins;
     960 ECB             : 
     961                 :     /* Is the join between partitions itself partitioned? */
     962 GNC        2150 :     build_joinrel_partition_info(root, joinrel, outer_rel, inner_rel, sjinfo,
     963                 :                                  restrictlist);
     964 ECB             : 
     965                 :     /* Child joinrel is parallel safe if parent is parallel safe. */
     966 CBC        2150 :     joinrel->consider_parallel = parent_joinrel->consider_parallel;
     967 ECB             : 
     968                 :     /* Set estimates of the child-joinrel's size. */
     969 CBC        2150 :     set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
     970 ECB             :                                sjinfo, restrictlist);
     971                 : 
     972                 :     /* We build the join only once. */
     973 CBC        2150 :     Assert(!find_join_rel(root, joinrel->relids));
     974 ECB             : 
     975                 :     /* Add the relation to the PlannerInfo. */
     976 CBC        2150 :     add_join_rel(root, joinrel);
     977 ECB             : 
     978                 :     /*
     979                 :      * We might need EquivalenceClass members corresponding to the child join,
     980                 :      * so that we can represent sort pathkeys for it.  As with children of
     981                 :      * baserels, we shouldn't need this unless there are relevant eclass joins
     982                 :      * (implying that a merge join might be possible) or pathkeys to sort by.
     983                 :      */
     984 CBC        2150 :     if (joinrel->has_eclass_joins || has_useful_pathkeys(root, parent_joinrel))
     985            2054 :         add_child_join_rel_equivalences(root,
     986 ECB             :                                         nappinfos, appinfos,
     987                 :                                         parent_joinrel, joinrel);
     988                 : 
     989 CBC        2150 :     pfree(appinfos);
     990 ECB             : 
     991 CBC        2150 :     return joinrel;
     992 ECB             : }
     993                 : 
     994                 : /*
     995                 :  * min_join_parameterization
     996                 :  *
     997                 :  * Determine the minimum possible parameterization of a joinrel, that is, the
     998                 :  * set of other rels it contains LATERAL references to.  We save this value in
     999                 :  * the join's RelOptInfo.  This function is split out of build_join_rel()
    1000                 :  * because join_is_legal() needs the value to check a prospective join.
    1001                 :  */
    1002                 : Relids
    1003 GIC       80472 : min_join_parameterization(PlannerInfo *root,
    1004                 :                           Relids joinrelids,
    1005 ECB             :                           RelOptInfo *outer_rel,
    1006                 :                           RelOptInfo *inner_rel)
    1007                 : {
    1008                 :     Relids      result;
    1009                 : 
    1010                 :     /*
    1011                 :      * Basically we just need the union of the inputs' lateral_relids, less
    1012                 :      * whatever is already in the join.
    1013                 :      *
    1014                 :      * It's not immediately obvious that this is a valid way to compute the
    1015                 :      * result, because it might seem that we're ignoring possible lateral refs
    1016                 :      * of PlaceHolderVars that are due to be computed at the join but not in
    1017                 :      * either input.  However, because create_lateral_join_info() already
    1018                 :      * charged all such PHV refs to each member baserel of the join, they'll
    1019                 :      * be accounted for already in the inputs' lateral_relids.  Likewise, we
    1020                 :      * do not need to worry about doing transitive closure here, because that
    1021                 :      * was already accounted for in the original baserel lateral_relids.
    1022                 :      */
    1023 GIC       80472 :     result = bms_union(outer_rel->lateral_relids, inner_rel->lateral_relids);
    1024 CBC       80472 :     result = bms_del_members(result, joinrelids);
    1025 GIC       80472 :     return result;
    1026 ECB             : }
    1027                 : 
    1028                 : /*
    1029                 :  * build_joinrel_tlist
    1030                 :  *    Builds a join relation's target list from an input relation.
    1031                 :  *    (This is invoked twice to handle the two input relations.)
    1032                 :  *
    1033                 :  * The join's targetlist includes all Vars of its member relations that
    1034                 :  * will still be needed above the join.  This subroutine adds all such
    1035                 :  * Vars from the specified input rel's tlist to the join rel's tlist.
    1036                 :  * Likewise for any PlaceHolderVars emitted by the input rel.
    1037                 :  *
    1038                 :  * We also compute the expected width of the join's output, making use
    1039                 :  * of data that was cached at the baserel level by set_rel_width().
    1040                 :  *
    1041                 :  * Pass can_null as true if the join is an outer join that can null Vars
    1042                 :  * from this input relation.  If so, we will (normally) add the join's relid
    1043                 :  * to the nulling bitmaps of Vars and PHVs bubbled up from the input.
    1044                 :  *
    1045                 :  * When forming an outer join's target list, special handling is needed
    1046                 :  * in case the outer join was commuted with another one per outer join
    1047                 :  * identity 3 (see optimizer/README).  We must take steps to ensure that
    1048                 :  * the output Vars have the same nulling bitmaps that they would if the
    1049                 :  * two joins had been done in syntactic order; else they won't match Vars
    1050                 :  * appearing higher in the query tree.  We need to do two things:
    1051                 :  *
    1052                 :  * First, we add the outer join's relid to the nulling bitmap only if the Var
    1053                 :  * or PHV actually comes from within the syntactically nullable side(s) of the
    1054                 :  * outer join.  This takes care of the possibility that we have transformed
    1055                 :  *      (A leftjoin B on (Pab)) leftjoin C on (Pbc)
    1056                 :  * to
    1057                 :  *      A leftjoin (B leftjoin C on (Pbc)) on (Pab)
    1058                 :  * Here the now-upper A/B join must not mark C columns as nulled by itself.
    1059                 :  *
    1060                 :  * Second, any relid in sjinfo->commute_above_r that is already part of
    1061                 :  * the joinrel is added to the nulling bitmaps of nullable Vars and PHVs.
    1062                 :  * This takes care of the reverse case where we implement
    1063                 :  *      A leftjoin (B leftjoin C on (Pbc)) on (Pab)
    1064                 :  * as
    1065                 :  *      (A leftjoin B on (Pab)) leftjoin C on (Pbc)
    1066                 :  * The C columns emitted by the B/C join need to be shown as nulled by both
    1067                 :  * the B/C and A/B joins, even though they've not physically traversed the
    1068                 :  * A/B join.
    1069                 :  */
    1070                 : static void
    1071 GIC      149126 : build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
    1072                 :                     RelOptInfo *input_rel,
    1073                 :                     SpecialJoinInfo *sjinfo,
    1074                 :                     bool can_null)
    1075 ECB             : {
    1076 GIC      149126 :     Relids      relids = joinrel->relids;
    1077                 :     ListCell   *vars;
    1078                 : 
    1079          679437 :     foreach(vars, input_rel->reltarget->exprs)
    1080                 :     {
    1081          530311 :         Var        *var = (Var *) lfirst(vars);
    1082                 : 
    1083 ECB             :         /*
    1084                 :          * For a PlaceHolderVar, we have to look up the PlaceHolderInfo.
    1085                 :          */
    1086 GIC      530311 :         if (IsA(var, PlaceHolderVar))
    1087 GNC         815 :         {
    1088             815 :             PlaceHolderVar *phv = (PlaceHolderVar *) var;
    1089             815 :             PlaceHolderInfo *phinfo = find_placeholder_info(root, phv);
    1090                 : 
    1091                 :             /* Is it still needed above this joinrel? */
    1092             815 :             if (bms_nonempty_difference(phinfo->ph_needed, relids))
    1093                 :             {
    1094                 :                 /*
    1095                 :                  * Yup, add it to the output.  If this join potentially nulls
    1096                 :                  * this input, we have to update the PHV's phnullingrels,
    1097                 :                  * which means making a copy.
    1098                 :                  */
    1099             593 :                 if (can_null)
    1100                 :                 {
    1101             347 :                     phv = copyObject(phv);
    1102                 :                     /* See comments above to understand this logic */
    1103             694 :                     if (sjinfo->ojrelid != 0 &&
    1104             347 :                         (bms_is_subset(phv->phrels, sjinfo->syn_righthand) ||
    1105             120 :                          (sjinfo->jointype == JOIN_FULL &&
    1106              57 :                           bms_is_subset(phv->phrels, sjinfo->syn_lefthand))))
    1107             341 :                         phv->phnullingrels = bms_add_member(phv->phnullingrels,
    1108             341 :                                                             sjinfo->ojrelid);
    1109             347 :                     phv->phnullingrels =
    1110             347 :                         bms_join(phv->phnullingrels,
    1111             347 :                                  bms_intersect(sjinfo->commute_above_r,
    1112                 :                                                relids));
    1113                 :                 }
    1114                 : 
    1115             593 :                 joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs,
    1116                 :                                                     phv);
    1117                 :                 /* Bubbling up the precomputed result has cost zero */
    1118             593 :                 joinrel->reltarget->width += phinfo->ph_width;
    1119                 :             }
    1120 CBC         815 :             continue;
    1121                 :         }
    1122                 : 
    1123 ECB             :         /*
    1124                 :          * Otherwise, anything in a baserel or joinrel targetlist ought to be
    1125                 :          * a Var.  (More general cases can only appear in appendrel child
    1126                 :          * rels, which will never be seen here.)
    1127                 :          */
    1128 GIC      529496 :         if (!IsA(var, Var))
    1129 UIC           0 :             elog(ERROR, "unexpected node type in rel targetlist: %d",
    1130                 :                  (int) nodeTag(var));
    1131                 : 
    1132 GIC      529496 :         if (var->varno == ROWID_VAR)
    1133                 :         {
    1134                 :             /* UPDATE/DELETE/MERGE row identity vars are always needed */
    1135 ECB             :             RowIdentityVarInfo *ridinfo = (RowIdentityVarInfo *)
    1136 GIC         364 :             list_nth(root->row_identity_vars, var->varattno - 1);
    1137                 : 
    1138                 :             /* Update reltarget width estimate from RowIdentityVarInfo */
    1139             364 :             joinrel->reltarget->width += ridinfo->rowidwidth;
    1140                 :         }
    1141                 :         else
    1142                 :         {
    1143                 :             RelOptInfo *baserel;
    1144                 :             int         ndx;
    1145                 : 
    1146                 :             /* Get the Var's original base rel */
    1147          529132 :             baserel = find_base_rel(root, var->varno);
    1148                 : 
    1149                 :             /* Is it still needed above this joinrel? */
    1150          529132 :             ndx = var->varattno - baserel->min_attr;
    1151 GNC      529132 :             if (!bms_nonempty_difference(baserel->attr_needed[ndx], relids))
    1152          102594 :                 continue;       /* nope, skip it */
    1153                 : 
    1154                 :             /* Update reltarget width estimate from baserel's attr_widths */
    1155          426538 :             joinrel->reltarget->width += baserel->attr_widths[ndx];
    1156                 :         }
    1157                 : 
    1158                 :         /*
    1159                 :          * Add the Var to the output.  If this join potentially nulls this
    1160                 :          * input, we have to update the Var's varnullingrels, which means
    1161                 :          * making a copy.  But note that we don't ever add nullingrel bits to
    1162                 :          * row identity Vars (cf. comments in setrefs.c).
    1163                 :          */
    1164          426902 :         if (can_null && var->varno != ROWID_VAR)
    1165                 :         {
    1166           41704 :             var = copyObject(var);
    1167                 :             /* See comments above to understand this logic */
    1168           83230 :             if (sjinfo->ojrelid != 0 &&
    1169           41526 :                 (bms_is_member(var->varno, sjinfo->syn_righthand) ||
    1170            1692 :                  (sjinfo->jointype == JOIN_FULL &&
    1171             837 :                   bms_is_member(var->varno, sjinfo->syn_lefthand))))
    1172           41508 :                 var->varnullingrels = bms_add_member(var->varnullingrels,
    1173           41508 :                                                      sjinfo->ojrelid);
    1174           41704 :             var->varnullingrels =
    1175           41704 :                 bms_join(var->varnullingrels,
    1176           41704 :                          bms_intersect(sjinfo->commute_above_r,
    1177                 :                                        relids));
    1178                 :         }
    1179                 : 
    1180          426902 :         joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs,
    1181                 :                                             var);
    1182                 : 
    1183                 :         /* Vars have cost zero, so no need to adjust reltarget->cost */
    1184                 :     }
    1185 GIC      149126 : }
    1186                 : 
    1187                 : /*
    1188                 :  * build_joinrel_restrictlist
    1189                 :  * build_joinrel_joinlist
    1190                 :  *    These routines build lists of restriction and join clauses for a
    1191                 :  *    join relation from the joininfo lists of the relations it joins.
    1192                 :  *
    1193                 :  *    These routines are separate because the restriction list must be
    1194                 :  *    built afresh for each pair of input sub-relations we consider, whereas
    1195                 :  *    the join list need only be computed once for any join RelOptInfo.
    1196                 :  *    The join list is fully determined by the set of rels making up the
    1197                 :  *    joinrel, so we should get the same results (up to ordering) from any
    1198                 :  *    candidate pair of sub-relations.  But the restriction list is whatever
    1199                 :  *    is not handled in the sub-relations, so it depends on which
    1200                 :  *    sub-relations are considered.
    1201                 :  *
    1202                 :  *    If a join clause from an input relation refers to base+OJ rels still not
    1203                 :  *    present in the joinrel, then it is still a join clause for the joinrel;
    1204                 :  *    we put it into the joininfo list for the joinrel.  Otherwise,
    1205                 :  *    the clause is now a restrict clause for the joined relation, and we
    1206                 :  *    return it to the caller of build_joinrel_restrictlist() to be stored in
    1207                 :  *    join paths made from this pair of sub-relations.  (It will not need to
    1208                 :  *    be considered further up the join tree.)
    1209                 :  *
    1210                 :  *    In many cases we will find the same RestrictInfos in both input
    1211                 :  *    relations' joinlists, so be careful to eliminate duplicates.
    1212                 :  *    Pointer equality should be a sufficient test for dups, since all
    1213                 :  *    the various joinlist entries ultimately refer to RestrictInfos
    1214                 :  *    pushed into them by distribute_restrictinfo_to_rels().
    1215                 :  *
    1216                 :  * 'joinrel' is a join relation node
    1217                 :  * 'outer_rel' and 'inner_rel' are a pair of relations that can be joined
    1218                 :  *      to form joinrel.
    1219                 :  * 'sjinfo': join context info
    1220                 :  *
    1221                 :  * build_joinrel_restrictlist() returns a list of relevant restrictinfos,
    1222                 :  * whereas build_joinrel_joinlist() stores its results in the joinrel's
    1223                 :  * joininfo list.  One or the other must accept each given clause!
    1224                 :  *
    1225                 :  * NB: Formerly, we made deep(!) copies of each input RestrictInfo to pass
    1226 ECB             :  * up to the join relation.  I believe this is no longer necessary, because
    1227                 :  * RestrictInfo nodes are no longer context-dependent.  Instead, just include
    1228                 :  * the original nodes in the lists made for the join relation.
    1229                 :  */
    1230                 : static List *
    1231 CBC      114035 : build_joinrel_restrictlist(PlannerInfo *root,
    1232                 :                            RelOptInfo *joinrel,
    1233                 :                            RelOptInfo *outer_rel,
    1234                 :                            RelOptInfo *inner_rel,
    1235                 :                            SpecialJoinInfo *sjinfo)
    1236                 : {
    1237 ECB             :     List       *result;
    1238                 :     Relids      both_input_relids;
    1239                 : 
    1240 GNC      114035 :     both_input_relids = bms_union(outer_rel->relids, inner_rel->relids);
    1241                 : 
    1242                 :     /*
    1243                 :      * Collect all the clauses that syntactically belong at this level,
    1244                 :      * eliminating any duplicates (important since we will see many of the
    1245 ECB             :      * same clauses arriving from both input relations).
    1246                 :      */
    1247 GNC      114035 :     result = subbuild_joinrel_restrictlist(root, joinrel, outer_rel,
    1248                 :                                            both_input_relids, NIL);
    1249          114035 :     result = subbuild_joinrel_restrictlist(root, joinrel, inner_rel,
    1250                 :                                            both_input_relids, result);
    1251                 : 
    1252                 :     /*
    1253 ECB             :      * Add on any clauses derived from EquivalenceClasses.  These cannot be
    1254                 :      * redundant with the clauses in the joininfo lists, so don't bother
    1255                 :      * checking.
    1256                 :      */
    1257 GIC      114035 :     result = list_concat(result,
    1258          114035 :                          generate_join_implied_equalities(root,
    1259                 :                                                           joinrel->relids,
    1260 ECB             :                                                           outer_rel->relids,
    1261                 :                                                           inner_rel,
    1262                 :                                                           sjinfo->ojrelid));
    1263                 : 
    1264 GIC      114035 :     return result;
    1265 ECB             : }
    1266                 : 
    1267                 : static void
    1268 CBC       74563 : build_joinrel_joinlist(RelOptInfo *joinrel,
    1269 ECB             :                        RelOptInfo *outer_rel,
    1270                 :                        RelOptInfo *inner_rel)
    1271                 : {
    1272                 :     List       *result;
    1273                 : 
    1274                 :     /*
    1275                 :      * Collect all the clauses that syntactically belong above this level,
    1276                 :      * eliminating any duplicates (important since we will see many of the
    1277                 :      * same clauses arriving from both input relations).
    1278                 :      */
    1279 GIC       74563 :     result = subbuild_joinrel_joinlist(joinrel, outer_rel->joininfo, NIL);
    1280 CBC       74563 :     result = subbuild_joinrel_joinlist(joinrel, inner_rel->joininfo, result);
    1281                 : 
    1282           74563 :     joinrel->joininfo = result;
    1283 GIC       74563 : }
    1284                 : 
    1285                 : static List *
    1286 GNC      228070 : subbuild_joinrel_restrictlist(PlannerInfo *root,
    1287                 :                               RelOptInfo *joinrel,
    1288                 :                               RelOptInfo *input_rel,
    1289                 :                               Relids both_input_relids,
    1290                 :                               List *new_restrictlist)
    1291                 : {
    1292 ECB             :     ListCell   *l;
    1293 EUB             : 
    1294 GNC      445608 :     foreach(l, input_rel->joininfo)
    1295                 :     {
    1296 CBC      217538 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
    1297                 : 
    1298 GIC      217538 :         if (bms_is_subset(rinfo->required_relids, joinrel->relids))
    1299                 :         {
    1300 ECB             :             /*
    1301                 :              * This clause should become a restriction clause for the joinrel,
    1302                 :              * since it refers to no outside rels.  However, if it's a clone
    1303                 :              * clause then it might be too late to evaluate it, so we have to
    1304                 :              * check.  (If it is too late, just ignore the clause, taking it
    1305                 :              * on faith that another clone was or will be selected.)  Clone
    1306                 :              * clauses should always be outer-join clauses, so we compare
    1307                 :              * against both_input_relids.
    1308                 :              */
    1309 GNC      128814 :             if (rinfo->has_clone || rinfo->is_clone)
    1310                 :             {
    1311           18668 :                 Assert(!RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids));
    1312           18668 :                 if (!bms_is_subset(rinfo->required_relids, both_input_relids))
    1313            3076 :                     continue;
    1314           15592 :                 if (!clause_is_computable_at(root, rinfo->clause_relids,
    1315                 :                                              both_input_relids))
    1316            6170 :                     continue;
    1317                 :             }
    1318                 :             else
    1319                 :             {
    1320                 :                 /*
    1321                 :                  * For non-clone clauses, we just Assert it's OK.  These might
    1322                 :                  * be either join or filter clauses.
    1323                 :                  */
    1324                 : #ifdef USE_ASSERT_CHECKING
    1325          110146 :                 if (RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids))
    1326           29044 :                     Assert(clause_is_computable_at(root, rinfo->clause_relids,
    1327                 :                                                    joinrel->relids));
    1328                 :                 else
    1329                 :                 {
    1330           81102 :                     Assert(bms_is_subset(rinfo->required_relids,
    1331                 :                                          both_input_relids));
    1332           81102 :                     Assert(clause_is_computable_at(root, rinfo->clause_relids,
    1333                 :                                                    both_input_relids));
    1334                 :                 }
    1335                 : #endif
    1336                 :             }
    1337                 : 
    1338                 :             /*
    1339                 :              * OK, so add it to the list, being careful to eliminate
    1340                 :              * duplicates.  (Since RestrictInfo nodes in different joinlists
    1341                 :              * will have been multiply-linked rather than copied, pointer
    1342                 :              * equality should be a sufficient test.)
    1343                 :              */
    1344 GIC      119568 :             new_restrictlist = list_append_unique_ptr(new_restrictlist, rinfo);
    1345                 :         }
    1346                 :         else
    1347                 :         {
    1348 ECB             :             /*
    1349                 :              * This clause is still a join clause at this level, so we ignore
    1350                 :              * it in this routine.
    1351                 :              */
    1352                 :         }
    1353                 :     }
    1354                 : 
    1355 GIC      228070 :     return new_restrictlist;
    1356 ECB             : }
    1357                 : 
    1358                 : static List *
    1359 GIC      149126 : subbuild_joinrel_joinlist(RelOptInfo *joinrel,
    1360                 :                           List *joininfo_list,
    1361                 :                           List *new_joininfo)
    1362                 : {
    1363                 :     ListCell   *l;
    1364                 : 
    1365 ECB             :     /* Expected to be called only for join between parent relations. */
    1366 GIC      149126 :     Assert(joinrel->reloptkind == RELOPT_JOINREL);
    1367 ECB             : 
    1368 GIC      286491 :     foreach(l, joininfo_list)
    1369 ECB             :     {
    1370 CBC      137365 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
    1371 ECB             : 
    1372 CBC      137365 :         if (bms_is_subset(rinfo->required_relids, joinrel->relids))
    1373 ECB             :         {
    1374                 :             /*
    1375                 :              * This clause becomes a restriction clause for the joinrel, since
    1376                 :              * it refers to no outside rels.  So we can ignore it in this
    1377                 :              * routine.
    1378                 :              */
    1379                 :         }
    1380                 :         else
    1381                 :         {
    1382                 :             /*
    1383                 :              * This clause is still a join clause at this level, so add it to
    1384                 :              * the new joininfo list, being careful to eliminate duplicates.
    1385                 :              * (Since RestrictInfo nodes in different joinlists will have been
    1386                 :              * multiply-linked rather than copied, pointer equality should be
    1387                 :              * a sufficient test.)
    1388                 :              */
    1389 GIC       54642 :             new_joininfo = list_append_unique_ptr(new_joininfo, rinfo);
    1390                 :         }
    1391                 :     }
    1392                 : 
    1393          149126 :     return new_joininfo;
    1394                 : }
    1395                 : 
    1396                 : 
    1397                 : /*
    1398                 :  * fetch_upper_rel
    1399                 :  *      Build a RelOptInfo describing some post-scan/join query processing,
    1400                 :  *      or return a pre-existing one if somebody already built it.
    1401                 :  *
    1402                 :  * An "upper" relation is identified by an UpperRelationKind and a Relids set.
    1403                 :  * The meaning of the Relids set is not specified here, and very likely will
    1404                 :  * vary for different relation kinds.
    1405                 :  *
    1406                 :  * Most of the fields in an upper-level RelOptInfo are not used and are not
    1407                 :  * set here (though makeNode should ensure they're zeroes).  We basically only
    1408                 :  * care about fields that are of interest to add_path() and set_cheapest().
    1409                 :  */
    1410                 : RelOptInfo *
    1411          746412 : fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
    1412                 : {
    1413                 :     RelOptInfo *upperrel;
    1414                 :     ListCell   *lc;
    1415                 : 
    1416                 :     /*
    1417                 :      * For the moment, our indexing data structure is just a List for each
    1418                 :      * relation kind.  If we ever get so many of one kind that this stops
    1419                 :      * working well, we can improve it.  No code outside this function should
    1420                 :      * assume anything about how to find a particular upperrel.
    1421                 :      */
    1422                 : 
    1423                 :     /* If we already made this upperrel for the query, return it */
    1424          751571 :     foreach(lc, root->upper_rels[kind])
    1425                 :     {
    1426          476862 :         upperrel = (RelOptInfo *) lfirst(lc);
    1427                 : 
    1428          476862 :         if (bms_equal(upperrel->relids, relids))
    1429          471703 :             return upperrel;
    1430                 :     }
    1431                 : 
    1432 CBC      274709 :     upperrel = makeNode(RelOptInfo);
    1433 GIC      274709 :     upperrel->reloptkind = RELOPT_UPPER_REL;
    1434          274709 :     upperrel->relids = bms_copy(relids);
    1435                 : 
    1436                 :     /* cheap startup cost is interesting iff not all tuples to be retrieved */
    1437          274709 :     upperrel->consider_startup = (root->tuple_fraction > 0);
    1438          274709 :     upperrel->consider_param_startup = false;
    1439          274709 :     upperrel->consider_parallel = false; /* might get changed later */
    1440          274709 :     upperrel->reltarget = create_empty_pathtarget();
    1441 CBC      274709 :     upperrel->pathlist = NIL;
    1442 GIC      274709 :     upperrel->cheapest_startup_path = NULL;
    1443          274709 :     upperrel->cheapest_total_path = NULL;
    1444          274709 :     upperrel->cheapest_unique_path = NULL;
    1445          274709 :     upperrel->cheapest_parameterized_paths = NIL;
    1446                 : 
    1447          274709 :     root->upper_rels[kind] = lappend(root->upper_rels[kind], upperrel);
    1448 ECB             : 
    1449 GIC      274709 :     return upperrel;
    1450 ECB             : }
    1451                 : 
    1452                 : 
    1453                 : /*
    1454                 :  * find_childrel_parents
    1455                 :  *      Compute the set of parent relids of an appendrel child rel.
    1456                 :  *
    1457                 :  * Since appendrels can be nested, a child could have multiple levels of
    1458                 :  * appendrel ancestors.  This function computes a Relids set of all the
    1459                 :  * parent relation IDs.
    1460                 :  */
    1461                 : Relids
    1462 GIC        5039 : find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
    1463                 : {
    1464            5039 :     Relids      result = NULL;
    1465 ECB             : 
    1466 GIC        5039 :     Assert(rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
    1467            5039 :     Assert(rel->relid > 0 && rel->relid < root->simple_rel_array_size);
    1468                 : 
    1469 ECB             :     do
    1470                 :     {
    1471 GIC        5973 :         AppendRelInfo *appinfo = root->append_rel_array[rel->relid];
    1472            5973 :         Index       prelid = appinfo->parent_relid;
    1473                 : 
    1474            5973 :         result = bms_add_member(result, prelid);
    1475                 : 
    1476                 :         /* traverse up to the parent rel, loop if it's also a child rel */
    1477            5973 :         rel = find_base_rel(root, prelid);
    1478            5973 :     } while (rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
    1479                 : 
    1480 CBC        5039 :     Assert(rel->reloptkind == RELOPT_BASEREL);
    1481 ECB             : 
    1482 GIC        5039 :     return result;
    1483 ECB             : }
    1484                 : 
    1485                 : 
    1486                 : /*
    1487                 :  * get_baserel_parampathinfo
    1488                 :  *      Get the ParamPathInfo for a parameterized path for a base relation,
    1489                 :  *      constructing one if we don't have one already.
    1490                 :  *
    1491                 :  * This centralizes estimating the rowcounts for parameterized paths.
    1492                 :  * We need to cache those to be sure we use the same rowcount for all paths
    1493                 :  * of the same parameterization for a given rel.  This is also a convenient
    1494                 :  * place to determine which movable join clauses the parameterized path will
    1495                 :  * be responsible for evaluating.
    1496                 :  */
    1497                 : ParamPathInfo *
    1498 GIC      639139 : get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel,
    1499 ECB             :                           Relids required_outer)
    1500                 : {
    1501                 :     ParamPathInfo *ppi;
    1502                 :     Relids      joinrelids;
    1503                 :     List       *pclauses;
    1504                 :     Bitmapset  *pserials;
    1505                 :     double      rows;
    1506                 :     ListCell   *lc;
    1507                 : 
    1508                 :     /* If rel has LATERAL refs, every path for it should account for them */
    1509 GIC      639139 :     Assert(bms_is_subset(baserel->lateral_relids, required_outer));
    1510                 : 
    1511 ECB             :     /* Unparameterized paths have no ParamPathInfo */
    1512 GIC      639139 :     if (bms_is_empty(required_outer))
    1513 CBC      528092 :         return NULL;
    1514 ECB             : 
    1515 CBC      111047 :     Assert(!bms_overlap(baserel->relids, required_outer));
    1516 ECB             : 
    1517                 :     /* If we already have a PPI for this parameterization, just return it */
    1518 CBC      111047 :     if ((ppi = find_param_path_info(baserel, required_outer)))
    1519 GIC       58089 :         return ppi;
    1520                 : 
    1521                 :     /*
    1522                 :      * Identify all joinclauses that are movable to this base rel given this
    1523                 :      * parameterization.
    1524                 :      */
    1525           52958 :     joinrelids = bms_union(baserel->relids, required_outer);
    1526           52958 :     pclauses = NIL;
    1527 CBC       89012 :     foreach(lc, baserel->joininfo)
    1528 ECB             :     {
    1529 GIC       36054 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    1530                 : 
    1531           36054 :         if (join_clause_is_movable_into(rinfo,
    1532 ECB             :                                         baserel->relids,
    1533                 :                                         joinrelids))
    1534 CBC       16090 :             pclauses = lappend(pclauses, rinfo);
    1535                 :     }
    1536                 : 
    1537                 :     /*
    1538                 :      * Add in joinclauses generated by EquivalenceClasses, too.  (These
    1539                 :      * necessarily satisfy join_clause_is_movable_into.)
    1540                 :      */
    1541 GIC       52958 :     pclauses = list_concat(pclauses,
    1542           52958 :                            generate_join_implied_equalities(root,
    1543                 :                                                             joinrelids,
    1544                 :                                                             required_outer,
    1545                 :                                                             baserel,
    1546                 :                                                             0));
    1547                 : 
    1548                 :     /* Compute set of serial numbers of the enforced clauses */
    1549 GNC       52958 :     pserials = NULL;
    1550          106202 :     foreach(lc, pclauses)
    1551                 :     {
    1552           53244 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    1553                 : 
    1554           53244 :         pserials = bms_add_member(pserials, rinfo->rinfo_serial);
    1555                 :     }
    1556 ECB             : 
    1557                 :     /* Estimate the number of rows returned by the parameterized scan */
    1558 GIC       52958 :     rows = get_parameterized_baserel_size(root, baserel, pclauses);
    1559                 : 
    1560                 :     /* And now we can build the ParamPathInfo */
    1561           52958 :     ppi = makeNode(ParamPathInfo);
    1562           52958 :     ppi->ppi_req_outer = required_outer;
    1563           52958 :     ppi->ppi_rows = rows;
    1564           52958 :     ppi->ppi_clauses = pclauses;
    1565 GNC       52958 :     ppi->ppi_serials = pserials;
    1566 GIC       52958 :     baserel->ppilist = lappend(baserel->ppilist, ppi);
    1567                 : 
    1568 CBC       52958 :     return ppi;
    1569                 : }
    1570                 : 
    1571                 : /*
    1572 ECB             :  * get_joinrel_parampathinfo
    1573                 :  *      Get the ParamPathInfo for a parameterized path for a join relation,
    1574                 :  *      constructing one if we don't have one already.
    1575                 :  *
    1576                 :  * This centralizes estimating the rowcounts for parameterized paths.
    1577                 :  * We need to cache those to be sure we use the same rowcount for all paths
    1578                 :  * of the same parameterization for a given rel.  This is also a convenient
    1579                 :  * place to determine which movable join clauses the parameterized path will
    1580                 :  * be responsible for evaluating.
    1581                 :  *
    1582                 :  * outer_path and inner_path are a pair of input paths that can be used to
    1583                 :  * construct the join, and restrict_clauses is the list of regular join
    1584                 :  * clauses (including clauses derived from EquivalenceClasses) that must be
    1585                 :  * applied at the join node when using these inputs.
    1586                 :  *
    1587                 :  * Unlike the situation for base rels, the set of movable join clauses to be
    1588                 :  * enforced at a join varies with the selected pair of input paths, so we
    1589                 :  * must calculate that and pass it back, even if we already have a matching
    1590                 :  * ParamPathInfo.  We handle this by adding any clauses moved down to this
    1591                 :  * join to *restrict_clauses, which is an in/out parameter.  (The addition
    1592                 :  * is done in such a way as to not modify the passed-in List structure.)
    1593                 :  *
    1594                 :  * Note: when considering a nestloop join, the caller must have removed from
    1595                 :  * restrict_clauses any movable clauses that are themselves scheduled to be
    1596                 :  * pushed into the right-hand path.  We do not do that here since it's
    1597                 :  * unnecessary for other join types.
    1598                 :  */
    1599                 : ParamPathInfo *
    1600 GIC      648742 : get_joinrel_parampathinfo(PlannerInfo *root, RelOptInfo *joinrel,
    1601                 :                           Path *outer_path,
    1602 ECB             :                           Path *inner_path,
    1603                 :                           SpecialJoinInfo *sjinfo,
    1604                 :                           Relids required_outer,
    1605                 :                           List **restrict_clauses)
    1606                 : {
    1607                 :     ParamPathInfo *ppi;
    1608                 :     Relids      join_and_req;
    1609                 :     Relids      outer_and_req;
    1610                 :     Relids      inner_and_req;
    1611                 :     List       *pclauses;
    1612                 :     List       *eclauses;
    1613                 :     List       *dropped_ecs;
    1614                 :     double      rows;
    1615                 :     ListCell   *lc;
    1616                 : 
    1617                 :     /* If rel has LATERAL refs, every path for it should account for them */
    1618 GIC      648742 :     Assert(bms_is_subset(joinrel->lateral_relids, required_outer));
    1619                 : 
    1620                 :     /* Unparameterized paths have no ParamPathInfo or extra join clauses */
    1621          648742 :     if (bms_is_empty(required_outer))
    1622          638215 :         return NULL;
    1623                 : 
    1624 CBC       10527 :     Assert(!bms_overlap(joinrel->relids, required_outer));
    1625                 : 
    1626                 :     /*
    1627                 :      * Identify all joinclauses that are movable to this join rel given this
    1628                 :      * parameterization.  These are the clauses that are movable into this
    1629                 :      * join, but not movable into either input path.  Treat an unparameterized
    1630                 :      * input path as not accepting parameterized clauses (because it won't,
    1631                 :      * per the shortcut exit above), even though the joinclause movement rules
    1632                 :      * might allow the same clauses to be moved into a parameterized path for
    1633                 :      * that rel.
    1634                 :      */
    1635 GIC       10527 :     join_and_req = bms_union(joinrel->relids, required_outer);
    1636           10527 :     if (outer_path->param_info)
    1637 CBC        9683 :         outer_and_req = bms_union(outer_path->parent->relids,
    1638 GIC        9683 :                                   PATH_REQ_OUTER(outer_path));
    1639 ECB             :     else
    1640 GIC         844 :         outer_and_req = NULL;   /* outer path does not accept parameters */
    1641 CBC       10527 :     if (inner_path->param_info)
    1642            5585 :         inner_and_req = bms_union(inner_path->parent->relids,
    1643 GIC        5585 :                                   PATH_REQ_OUTER(inner_path));
    1644                 :     else
    1645 CBC        4942 :         inner_and_req = NULL;   /* inner path does not accept parameters */
    1646 ECB             : 
    1647 CBC       10527 :     pclauses = NIL;
    1648 GIC       27394 :     foreach(lc, joinrel->joininfo)
    1649                 :     {
    1650 CBC       16867 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    1651 ECB             : 
    1652 CBC       16867 :         if (join_clause_is_movable_into(rinfo,
    1653 ECB             :                                         joinrel->relids,
    1654 CBC        8724 :                                         join_and_req) &&
    1655            8724 :             !join_clause_is_movable_into(rinfo,
    1656            8724 :                                          outer_path->parent->relids,
    1657             356 :                                          outer_and_req) &&
    1658             356 :             !join_clause_is_movable_into(rinfo,
    1659 GIC         356 :                                          inner_path->parent->relids,
    1660 ECB             :                                          inner_and_req))
    1661 GIC          60 :             pclauses = lappend(pclauses, rinfo);
    1662 ECB             :     }
    1663                 : 
    1664                 :     /* Consider joinclauses generated by EquivalenceClasses, too */
    1665 GIC       10527 :     eclauses = generate_join_implied_equalities(root,
    1666                 :                                                 join_and_req,
    1667                 :                                                 required_outer,
    1668                 :                                                 joinrel,
    1669                 :                                                 0);
    1670                 :     /* We only want ones that aren't movable to lower levels */
    1671           10527 :     dropped_ecs = NIL;
    1672           11769 :     foreach(lc, eclauses)
    1673                 :     {
    1674            1242 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    1675                 : 
    1676            1242 :         Assert(join_clause_is_movable_into(rinfo,
    1677 ECB             :                                            joinrel->relids,
    1678                 :                                            join_and_req));
    1679 CBC        1242 :         if (join_clause_is_movable_into(rinfo,
    1680 GIC        1242 :                                         outer_path->parent->relids,
    1681                 :                                         outer_and_req))
    1682 CBC         616 :             continue;           /* drop if movable into LHS */
    1683             626 :         if (join_clause_is_movable_into(rinfo,
    1684 GIC         626 :                                         inner_path->parent->relids,
    1685 ECB             :                                         inner_and_req))
    1686                 :         {
    1687                 :             /* drop if movable into RHS, but remember EC for use below */
    1688 GIC         322 :             Assert(rinfo->left_ec == rinfo->right_ec);
    1689             322 :             dropped_ecs = lappend(dropped_ecs, rinfo->left_ec);
    1690             322 :             continue;
    1691                 :         }
    1692             304 :         pclauses = lappend(pclauses, rinfo);
    1693                 :     }
    1694                 : 
    1695                 :     /*
    1696                 :      * EquivalenceClasses are harder to deal with than we could wish, because
    1697                 :      * of the fact that a given EC can generate different clauses depending on
    1698                 :      * context.  Suppose we have an EC {X.X, Y.Y, Z.Z} where X and Y are the
    1699                 :      * LHS and RHS of the current join and Z is in required_outer, and further
    1700                 :      * suppose that the inner_path is parameterized by both X and Z.  The code
    1701                 :      * above will have produced either Z.Z = X.X or Z.Z = Y.Y from that EC,
    1702                 :      * and in the latter case will have discarded it as being movable into the
    1703 ECB             :      * RHS.  However, the EC machinery might have produced either Y.Y = X.X or
    1704                 :      * Y.Y = Z.Z as the EC enforcement clause within the inner_path; it will
    1705                 :      * not have produced both, and we can't readily tell from here which one
    1706                 :      * it did pick.  If we add no clause to this join, we'll end up with
    1707                 :      * insufficient enforcement of the EC; either Z.Z or X.X will fail to be
    1708                 :      * constrained to be equal to the other members of the EC.  (When we come
    1709                 :      * to join Z to this X/Y path, we will certainly drop whichever EC clause
    1710                 :      * is generated at that join, so this omission won't get fixed later.)
    1711                 :      *
    1712                 :      * To handle this, for each EC we discarded such a clause from, try to
    1713                 :      * generate a clause connecting the required_outer rels to the join's LHS
    1714                 :      * ("Z.Z = X.X" in the terms of the above example).  If successful, and if
    1715                 :      * the clause can't be moved to the LHS, add it to the current join's
    1716                 :      * restriction clauses.  (If an EC cannot generate such a clause then it
    1717                 :      * has nothing that needs to be enforced here, while if the clause can be
    1718                 :      * moved into the LHS then it should have been enforced within that path.)
    1719                 :      *
    1720                 :      * Note that we don't need similar processing for ECs whose clause was
    1721                 :      * considered to be movable into the LHS, because the LHS can't refer to
    1722                 :      * the RHS so there is no comparable ambiguity about what it might
    1723                 :      * actually be enforcing internally.
    1724                 :      */
    1725 GIC       10527 :     if (dropped_ecs)
    1726                 :     {
    1727                 :         Relids      real_outer_and_req;
    1728                 : 
    1729             307 :         real_outer_and_req = bms_union(outer_path->parent->relids,
    1730 ECB             :                                        required_outer);
    1731                 :         eclauses =
    1732 CBC         307 :             generate_join_implied_equalities_for_ecs(root,
    1733                 :                                                      dropped_ecs,
    1734 ECB             :                                                      real_outer_and_req,
    1735                 :                                                      required_outer,
    1736                 :                                                      outer_path->parent);
    1737 GIC         328 :         foreach(lc, eclauses)
    1738                 :         {
    1739 CBC          21 :             RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    1740                 : 
    1741 GIC          21 :             Assert(join_clause_is_movable_into(rinfo,
    1742                 :                                                outer_path->parent->relids,
    1743                 :                                                real_outer_and_req));
    1744 CBC          21 :             if (!join_clause_is_movable_into(rinfo,
    1745 GIC          21 :                                              outer_path->parent->relids,
    1746                 :                                              outer_and_req))
    1747              15 :                 pclauses = lappend(pclauses, rinfo);
    1748                 :         }
    1749                 :     }
    1750                 : 
    1751 ECB             :     /*
    1752                 :      * Now, attach the identified moved-down clauses to the caller's
    1753                 :      * restrict_clauses list.  By using list_concat in this order, we leave
    1754                 :      * the original list structure of restrict_clauses undamaged.
    1755                 :      */
    1756 CBC       10527 :     *restrict_clauses = list_concat(pclauses, *restrict_clauses);
    1757                 : 
    1758                 :     /* If we already have a PPI for this parameterization, just return it */
    1759 GIC       10527 :     if ((ppi = find_param_path_info(joinrel, required_outer)))
    1760 CBC        7821 :         return ppi;
    1761                 : 
    1762                 :     /* Estimate the number of rows returned by the parameterized join */
    1763            2706 :     rows = get_parameterized_joinrel_size(root, joinrel,
    1764 ECB             :                                           outer_path,
    1765                 :                                           inner_path,
    1766                 :                                           sjinfo,
    1767                 :                                           *restrict_clauses);
    1768                 : 
    1769                 :     /*
    1770                 :      * And now we can build the ParamPathInfo.  No point in saving the
    1771                 :      * input-pair-dependent clause list, though.
    1772                 :      *
    1773                 :      * Note: in GEQO mode, we'll be called in a temporary memory context, but
    1774                 :      * the joinrel structure is there too, so no problem.
    1775                 :      */
    1776 GIC        2706 :     ppi = makeNode(ParamPathInfo);
    1777            2706 :     ppi->ppi_req_outer = required_outer;
    1778            2706 :     ppi->ppi_rows = rows;
    1779            2706 :     ppi->ppi_clauses = NIL;
    1780 GNC        2706 :     ppi->ppi_serials = NULL;
    1781 GIC        2706 :     joinrel->ppilist = lappend(joinrel->ppilist, ppi);
    1782                 : 
    1783            2706 :     return ppi;
    1784                 : }
    1785                 : 
    1786                 : /*
    1787                 :  * get_appendrel_parampathinfo
    1788                 :  *      Get the ParamPathInfo for a parameterized path for an append relation.
    1789                 :  *
    1790                 :  * For an append relation, the rowcount estimate will just be the sum of
    1791                 :  * the estimates for its children.  However, we still need a ParamPathInfo
    1792                 :  * to flag the fact that the path requires parameters.  So this just creates
    1793                 :  * a suitable struct with zero ppi_rows (and no ppi_clauses either, since
    1794                 :  * the Append node isn't responsible for checking quals).
    1795                 :  */
    1796                 : ParamPathInfo *
    1797           19299 : get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer)
    1798                 : {
    1799                 :     ParamPathInfo *ppi;
    1800                 : 
    1801                 :     /* If rel has LATERAL refs, every path for it should account for them */
    1802           19299 :     Assert(bms_is_subset(appendrel->lateral_relids, required_outer));
    1803 ECB             : 
    1804                 :     /* Unparameterized paths have no ParamPathInfo */
    1805 GIC       19299 :     if (bms_is_empty(required_outer))
    1806           19072 :         return NULL;
    1807                 : 
    1808             227 :     Assert(!bms_overlap(appendrel->relids, required_outer));
    1809                 : 
    1810                 :     /* If we already have a PPI for this parameterization, just return it */
    1811             227 :     if ((ppi = find_param_path_info(appendrel, required_outer)))
    1812              51 :         return ppi;
    1813                 : 
    1814                 :     /* Else build the ParamPathInfo */
    1815             176 :     ppi = makeNode(ParamPathInfo);
    1816             176 :     ppi->ppi_req_outer = required_outer;
    1817             176 :     ppi->ppi_rows = 0;
    1818             176 :     ppi->ppi_clauses = NIL;
    1819 GNC         176 :     ppi->ppi_serials = NULL;
    1820 GIC         176 :     appendrel->ppilist = lappend(appendrel->ppilist, ppi);
    1821                 : 
    1822 CBC         176 :     return ppi;
    1823                 : }
    1824                 : 
    1825 ECB             : /*
    1826                 :  * Returns a ParamPathInfo for the parameterization given by required_outer, if
    1827                 :  * already available in the given rel. Returns NULL otherwise.
    1828                 :  */
    1829                 : ParamPathInfo *
    1830 GIC      125883 : find_param_path_info(RelOptInfo *rel, Relids required_outer)
    1831                 : {
    1832                 :     ListCell   *lc;
    1833                 : 
    1834          150215 :     foreach(lc, rel->ppilist)
    1835                 :     {
    1836           93370 :         ParamPathInfo *ppi = (ParamPathInfo *) lfirst(lc);
    1837                 : 
    1838           93370 :         if (bms_equal(ppi->ppi_req_outer, required_outer))
    1839 CBC       69038 :             return ppi;
    1840 ECB             :     }
    1841                 : 
    1842 CBC       56845 :     return NULL;
    1843                 : }
    1844 ECB             : 
    1845                 : /*
    1846                 :  * get_param_path_clause_serials
    1847                 :  *      Given a parameterized Path, return the set of pushed-down clauses
    1848                 :  *      (identified by rinfo_serial numbers) enforced within the Path.
    1849                 :  */
    1850                 : Bitmapset *
    1851 GNC      137725 : get_param_path_clause_serials(Path *path)
    1852                 : {
    1853          137725 :     if (path->param_info == NULL)
    1854             393 :         return NULL;            /* not parameterized */
    1855          137332 :     if (IsA(path, NestPath) ||
    1856          132914 :         IsA(path, MergePath) ||
    1857          132875 :         IsA(path, HashPath))
    1858                 :     {
    1859                 :         /*
    1860                 :          * For a join path, combine clauses enforced within either input path
    1861                 :          * with those enforced as joinrestrictinfo in this path.  Note that
    1862                 :          * joinrestrictinfo may include some non-pushed-down clauses, but for
    1863                 :          * current purposes it's okay if we include those in the result. (To
    1864                 :          * be more careful, we could check for clause_relids overlapping the
    1865                 :          * path parameterization, but it's not worth the cycles for now.)
    1866                 :          */
    1867            4836 :         JoinPath   *jpath = (JoinPath *) path;
    1868                 :         Bitmapset  *pserials;
    1869                 :         ListCell   *lc;
    1870                 : 
    1871            4836 :         pserials = NULL;
    1872            4836 :         pserials = bms_add_members(pserials,
    1873            4836 :                                    get_param_path_clause_serials(jpath->outerjoinpath));
    1874            4836 :         pserials = bms_add_members(pserials,
    1875            4836 :                                    get_param_path_clause_serials(jpath->innerjoinpath));
    1876            5645 :         foreach(lc, jpath->joinrestrictinfo)
    1877                 :         {
    1878             809 :             RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    1879                 : 
    1880             809 :             pserials = bms_add_member(pserials, rinfo->rinfo_serial);
    1881                 :         }
    1882            4836 :         return pserials;
    1883                 :     }
    1884          132496 :     else if (IsA(path, AppendPath))
    1885                 :     {
    1886                 :         /*
    1887                 :          * For an appendrel, take the intersection of the sets of clauses
    1888                 :          * enforced in each input path.
    1889                 :          */
    1890             967 :         AppendPath *apath = (AppendPath *) path;
    1891                 :         Bitmapset  *pserials;
    1892                 :         ListCell   *lc;
    1893                 : 
    1894             967 :         pserials = NULL;
    1895            4069 :         foreach(lc, apath->subpaths)
    1896                 :         {
    1897            3102 :             Path       *subpath = (Path *) lfirst(lc);
    1898                 :             Bitmapset  *subserials;
    1899                 : 
    1900            3102 :             subserials = get_param_path_clause_serials(subpath);
    1901            3102 :             if (lc == list_head(apath->subpaths))
    1902             961 :                 pserials = bms_copy(subserials);
    1903                 :             else
    1904            2141 :                 pserials = bms_int_members(pserials, subserials);
    1905                 :         }
    1906             967 :         return pserials;
    1907                 :     }
    1908          131529 :     else if (IsA(path, MergeAppendPath))
    1909                 :     {
    1910                 :         /* Same as AppendPath case */
    1911 UNC           0 :         MergeAppendPath *apath = (MergeAppendPath *) path;
    1912                 :         Bitmapset  *pserials;
    1913                 :         ListCell   *lc;
    1914                 : 
    1915               0 :         pserials = NULL;
    1916               0 :         foreach(lc, apath->subpaths)
    1917                 :         {
    1918               0 :             Path       *subpath = (Path *) lfirst(lc);
    1919                 :             Bitmapset  *subserials;
    1920                 : 
    1921               0 :             subserials = get_param_path_clause_serials(subpath);
    1922               0 :             if (lc == list_head(apath->subpaths))
    1923               0 :                 pserials = bms_copy(subserials);
    1924                 :             else
    1925               0 :                 pserials = bms_int_members(pserials, subserials);
    1926                 :         }
    1927               0 :         return pserials;
    1928                 :     }
    1929                 :     else
    1930                 :     {
    1931                 :         /*
    1932                 :          * Otherwise, it's a baserel path and we can use the
    1933                 :          * previously-computed set of serial numbers.
    1934                 :          */
    1935 GNC      131529 :         return path->param_info->ppi_serials;
    1936                 :     }
    1937                 : }
    1938                 : 
    1939 ECB             : /*
    1940                 :  * build_joinrel_partition_info
    1941                 :  *      Checks if the two relations being joined can use partitionwise join
    1942                 :  *      and if yes, initialize partitioning information of the resulting
    1943                 :  *      partitioned join relation.
    1944                 :  */
    1945                 : static void
    1946 GNC       76713 : build_joinrel_partition_info(PlannerInfo *root,
    1947                 :                              RelOptInfo *joinrel, RelOptInfo *outer_rel,
    1948                 :                              RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo,
    1949                 :                              List *restrictlist)
    1950                 : {
    1951 ECB             :     PartitionScheme part_scheme;
    1952                 : 
    1953                 :     /* Nothing to do if partitionwise join technique is disabled. */
    1954 CBC       76713 :     if (!enable_partitionwise_join)
    1955 ECB             :     {
    1956 CBC       73644 :         Assert(!IS_PARTITIONED_REL(joinrel));
    1957           73644 :         return;
    1958 ECB             :     }
    1959                 : 
    1960                 :     /*
    1961                 :      * We can only consider this join as an input to further partitionwise
    1962                 :      * joins if (a) the input relations are partitioned and have
    1963                 :      * consider_partitionwise_join=true, (b) the partition schemes match, and
    1964                 :      * (c) we can identify an equi-join between the partition keys.  Note that
    1965                 :      * if it were possible for have_partkey_equi_join to return different
    1966                 :      * answers for the same joinrel depending on which join ordering we try
    1967                 :      * first, this logic would break.  That shouldn't happen, though, because
    1968                 :      * of the way the query planner deduces implied equalities and reorders
    1969                 :      * the joins.  Please see optimizer/README for details.
    1970                 :      */
    1971 CBC        3069 :     if (outer_rel->part_scheme == NULL || inner_rel->part_scheme == NULL ||
    1972 GIC        1009 :         !outer_rel->consider_partitionwise_join ||
    1973 CBC         987 :         !inner_rel->consider_partitionwise_join ||
    1974 GIC         987 :         outer_rel->part_scheme != inner_rel->part_scheme ||
    1975 GNC         975 :         !have_partkey_equi_join(root, joinrel, outer_rel, inner_rel,
    1976                 :                                 sjinfo->jointype, restrictlist))
    1977                 :     {
    1978 CBC        2172 :         Assert(!IS_PARTITIONED_REL(joinrel));
    1979            2172 :         return;
    1980                 :     }
    1981 ECB             : 
    1982 CBC         897 :     part_scheme = outer_rel->part_scheme;
    1983 ECB             : 
    1984                 :     /*
    1985                 :      * This function will be called only once for each joinrel, hence it
    1986                 :      * should not have partitioning fields filled yet.
    1987                 :      */
    1988 CBC         897 :     Assert(!joinrel->part_scheme && !joinrel->partexprs &&
    1989 ECB             :            !joinrel->nullable_partexprs && !joinrel->part_rels &&
    1990                 :            !joinrel->boundinfo);
    1991                 : 
    1992                 :     /*
    1993                 :      * If the join relation is partitioned, it uses the same partitioning
    1994                 :      * scheme as the joining relations.
    1995                 :      *
    1996                 :      * Note: we calculate the partition bounds, number of partitions, and
    1997                 :      * child-join relations of the join relation in try_partitionwise_join().
    1998                 :      */
    1999 GIC         897 :     joinrel->part_scheme = part_scheme;
    2000 GNC         897 :     set_joinrel_partition_key_exprs(joinrel, outer_rel, inner_rel,
    2001                 :                                     sjinfo->jointype);
    2002                 : 
    2003                 :     /*
    2004                 :      * Set the consider_partitionwise_join flag.
    2005                 :      */
    2006 GIC         897 :     Assert(outer_rel->consider_partitionwise_join);
    2007             897 :     Assert(inner_rel->consider_partitionwise_join);
    2008             897 :     joinrel->consider_partitionwise_join = true;
    2009                 : }
    2010                 : 
    2011                 : /*
    2012                 :  * have_partkey_equi_join
    2013                 :  *
    2014                 :  * Returns true if there exist equi-join conditions involving pairs
    2015                 :  * of matching partition keys of the relations being joined for all
    2016                 :  * partition keys.
    2017                 :  */
    2018                 : static bool
    2019 GNC         975 : have_partkey_equi_join(PlannerInfo *root, RelOptInfo *joinrel,
    2020                 :                        RelOptInfo *rel1, RelOptInfo *rel2,
    2021                 :                        JoinType jointype, List *restrictlist)
    2022                 : {
    2023 GIC         975 :     PartitionScheme part_scheme = rel1->part_scheme;
    2024                 :     ListCell   *lc;
    2025 ECB             :     int         cnt_pks;
    2026                 :     bool        pk_has_clause[PARTITION_MAX_KEYS];
    2027                 :     bool        strict_op;
    2028                 : 
    2029                 :     /*
    2030                 :      * This function must only be called when the joined relations have same
    2031                 :      * partitioning scheme.
    2032                 :      */
    2033 GIC         975 :     Assert(rel1->part_scheme == rel2->part_scheme);
    2034             975 :     Assert(part_scheme);
    2035                 : 
    2036             975 :     memset(pk_has_clause, 0, sizeof(pk_has_clause));
    2037 CBC        2567 :     foreach(lc, restrictlist)
    2038                 :     {
    2039            1592 :         RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
    2040                 :         OpExpr     *opexpr;
    2041 ECB             :         Expr       *expr1;
    2042                 :         Expr       *expr2;
    2043                 :         int         ipk1;
    2044                 :         int         ipk2;
    2045                 : 
    2046                 :         /* If processing an outer join, only use its own join clauses. */
    2047 CBC        1592 :         if (IS_OUTER_JOIN(jointype) &&
    2048 GIC         936 :             RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids))
    2049             168 :             continue;
    2050                 : 
    2051                 :         /* Skip clauses which can not be used for a join. */
    2052            1424 :         if (!rinfo->can_join)
    2053               9 :             continue;
    2054                 : 
    2055                 :         /* Skip clauses which are not equality conditions. */
    2056 CBC        1415 :         if (!rinfo->mergeopfamilies && !OidIsValid(rinfo->hashjoinoperator))
    2057 GIC           3 :             continue;
    2058                 : 
    2059 ECB             :         /* Should be OK to assume it's an OpExpr. */
    2060 CBC        1412 :         opexpr = castNode(OpExpr, rinfo->clause);
    2061                 : 
    2062                 :         /* Match the operands to the relation. */
    2063            2720 :         if (bms_is_subset(rinfo->left_relids, rel1->relids) &&
    2064 GIC        1308 :             bms_is_subset(rinfo->right_relids, rel2->relids))
    2065                 :         {
    2066            1308 :             expr1 = linitial(opexpr->args);
    2067            1308 :             expr2 = lsecond(opexpr->args);
    2068                 :         }
    2069             208 :         else if (bms_is_subset(rinfo->left_relids, rel2->relids) &&
    2070             104 :                  bms_is_subset(rinfo->right_relids, rel1->relids))
    2071                 :         {
    2072             104 :             expr1 = lsecond(opexpr->args);
    2073             104 :             expr2 = linitial(opexpr->args);
    2074                 :         }
    2075                 :         else
    2076 LBC           0 :             continue;
    2077 ECB             : 
    2078                 :         /*
    2079                 :          * Now we need to know whether the join operator is strict; see
    2080                 :          * comments in pathnodes.h.
    2081                 :          */
    2082 GIC        1412 :         strict_op = op_strict(opexpr->opno);
    2083 ECB             : 
    2084                 :         /*
    2085                 :          * Vars appearing in the relation's partition keys will not have any
    2086                 :          * varnullingrels, but those in expr1 and expr2 will if we're above
    2087                 :          * outer joins that could null the respective rels.  It's okay to
    2088                 :          * match anyway, if the join operator is strict.
    2089                 :          */
    2090 GNC        1412 :         if (strict_op)
    2091                 :         {
    2092            1412 :             if (bms_overlap(rel1->relids, root->outer_join_rels))
    2093             105 :                 expr1 = (Expr *) remove_nulling_relids((Node *) expr1,
    2094             105 :                                                        root->outer_join_rels,
    2095                 :                                                        NULL);
    2096            1412 :             if (bms_overlap(rel2->relids, root->outer_join_rels))
    2097 UNC           0 :                 expr2 = (Expr *) remove_nulling_relids((Node *) expr2,
    2098               0 :                                                        root->outer_join_rels,
    2099                 :                                                        NULL);
    2100                 :         }
    2101                 : 
    2102                 :         /*
    2103                 :          * Only clauses referencing the partition keys are useful for
    2104                 :          * partitionwise join.
    2105                 :          */
    2106 GIC        1412 :         ipk1 = match_expr_to_partition_keys(expr1, rel1, strict_op);
    2107            1412 :         if (ipk1 < 0)
    2108             503 :             continue;
    2109             909 :         ipk2 = match_expr_to_partition_keys(expr2, rel2, strict_op);
    2110             909 :         if (ipk2 < 0)
    2111 UIC           0 :             continue;
    2112                 : 
    2113                 :         /*
    2114                 :          * If the clause refers to keys at different ordinal positions, it can
    2115 ECB             :          * not be used for partitionwise join.
    2116                 :          */
    2117 GIC         909 :         if (ipk1 != ipk2)
    2118               3 :             continue;
    2119                 : 
    2120 ECB             :         /*
    2121                 :          * The clause allows partitionwise join only if it uses the same
    2122                 :          * operator family as that specified by the partition key.
    2123                 :          */
    2124 CBC         906 :         if (rel1->part_scheme->strategy == PARTITION_STRATEGY_HASH)
    2125                 :         {
    2126              24 :             if (!OidIsValid(rinfo->hashjoinoperator) ||
    2127 GIC          24 :                 !op_in_opfamily(rinfo->hashjoinoperator,
    2128              24 :                                 part_scheme->partopfamily[ipk1]))
    2129 LBC           0 :                 continue;
    2130 ECB             :         }
    2131 GIC         882 :         else if (!list_member_oid(rinfo->mergeopfamilies,
    2132             882 :                                   part_scheme->partopfamily[ipk1]))
    2133 LBC           0 :             continue;
    2134 ECB             : 
    2135                 :         /* Mark the partition key as having an equi-join clause. */
    2136 CBC         906 :         pk_has_clause[ipk1] = true;
    2137 ECB             :     }
    2138                 : 
    2139                 :     /* Check whether every partition key has an equi-join condition. */
    2140 CBC        1881 :     for (cnt_pks = 0; cnt_pks < part_scheme->partnatts; cnt_pks++)
    2141                 :     {
    2142 GIC         984 :         if (!pk_has_clause[cnt_pks])
    2143              78 :             return false;
    2144                 :     }
    2145                 : 
    2146             897 :     return true;
    2147                 : }
    2148 ECB             : 
    2149                 : /*
    2150                 :  * match_expr_to_partition_keys
    2151                 :  *
    2152                 :  * Tries to match an expression to one of the nullable or non-nullable
    2153                 :  * partition keys of "rel".  Returns the matched key's ordinal position,
    2154                 :  * or -1 if the expression could not be matched to any of the keys.
    2155                 :  *
    2156                 :  * strict_op must be true if the expression will be compared with the
    2157                 :  * partition key using a strict operator.  This allows us to consider
    2158                 :  * nullable as well as nonnullable partition keys.
    2159                 :  */
    2160                 : static int
    2161 GIC        2321 : match_expr_to_partition_keys(Expr *expr, RelOptInfo *rel, bool strict_op)
    2162                 : {
    2163                 :     int         cnt;
    2164                 : 
    2165                 :     /* This function should be called only for partitioned relations. */
    2166            2321 :     Assert(rel->part_scheme);
    2167            2321 :     Assert(rel->partexprs);
    2168            2321 :     Assert(rel->nullable_partexprs);
    2169 ECB             : 
    2170                 :     /* Remove any relabel decorations. */
    2171 CBC        2444 :     while (IsA(expr, RelabelType))
    2172             123 :         expr = (Expr *) (castNode(RelabelType, expr))->arg;
    2173 ECB             : 
    2174 CBC        2842 :     for (cnt = 0; cnt < rel->part_scheme->partnatts; cnt++)
    2175 ECB             :     {
    2176                 :         ListCell   *lc;
    2177                 : 
    2178                 :         /* We can always match to the non-nullable partition keys. */
    2179 GIC        2854 :         foreach(lc, rel->partexprs[cnt])
    2180                 :         {
    2181            2297 :             if (equal(lfirst(lc), expr))
    2182            1782 :                 return cnt;
    2183                 :         }
    2184                 : 
    2185 CBC         557 :         if (!strict_op)
    2186 UIC           0 :             continue;
    2187                 : 
    2188                 :         /*
    2189 ECB             :          * If it's a strict join operator then a NULL partition key on one
    2190                 :          * side will not join to any partition key on the other side, and in
    2191                 :          * particular such a row can't join to a row from a different
    2192                 :          * partition on the other side.  So, it's okay to search the nullable
    2193                 :          * partition keys as well.
    2194                 :          */
    2195 GIC         707 :         foreach(lc, rel->nullable_partexprs[cnt])
    2196 ECB             :         {
    2197 GIC         186 :             if (equal(lfirst(lc), expr))
    2198 CBC          36 :                 return cnt;
    2199                 :         }
    2200 ECB             :     }
    2201                 : 
    2202 CBC         503 :     return -1;
    2203                 : }
    2204                 : 
    2205                 : /*
    2206                 :  * set_joinrel_partition_key_exprs
    2207                 :  *      Initialize partition key expressions for a partitioned joinrel.
    2208 ECB             :  */
    2209                 : static void
    2210 GIC         897 : set_joinrel_partition_key_exprs(RelOptInfo *joinrel,
    2211                 :                                 RelOptInfo *outer_rel, RelOptInfo *inner_rel,
    2212 ECB             :                                 JoinType jointype)
    2213                 : {
    2214 GIC         897 :     PartitionScheme part_scheme = joinrel->part_scheme;
    2215 CBC         897 :     int         partnatts = part_scheme->partnatts;
    2216                 : 
    2217 GIC         897 :     joinrel->partexprs = (List **) palloc0(sizeof(List *) * partnatts);
    2218 CBC         897 :     joinrel->nullable_partexprs =
    2219             897 :         (List **) palloc0(sizeof(List *) * partnatts);
    2220 ECB             : 
    2221                 :     /*
    2222                 :      * The joinrel's partition expressions are the same as those of the input
    2223                 :      * rels, but we must properly classify them as nullable or not in the
    2224                 :      * joinrel's output.  (Also, we add some more partition expressions if
    2225                 :      * it's a FULL JOIN.)
    2226                 :      */
    2227 GIC        1800 :     for (int cnt = 0; cnt < partnatts; cnt++)
    2228                 :     {
    2229 EUB             :         /* mark these const to enforce that we copy them properly */
    2230 GIC         903 :         const List *outer_expr = outer_rel->partexprs[cnt];
    2231             903 :         const List *outer_null_expr = outer_rel->nullable_partexprs[cnt];
    2232             903 :         const List *inner_expr = inner_rel->partexprs[cnt];
    2233 GBC         903 :         const List *inner_null_expr = inner_rel->nullable_partexprs[cnt];
    2234             903 :         List       *partexpr = NIL;
    2235 GIC         903 :         List       *nullable_partexpr = NIL;
    2236 EUB             :         ListCell   *lc;
    2237                 : 
    2238 GIC         903 :         switch (jointype)
    2239 EUB             :         {
    2240                 :                 /*
    2241                 :                  * A join relation resulting from an INNER join may be
    2242                 :                  * regarded as partitioned by either of the inner and outer
    2243                 :                  * relation keys.  For example, A INNER JOIN B ON A.a = B.b
    2244                 :                  * can be regarded as partitioned on either A.a or B.b.  So we
    2245                 :                  * add both keys to the joinrel's partexpr lists.  However,
    2246                 :                  * anything that was already nullable still has to be treated
    2247                 :                  * as nullable.
    2248                 :                  */
    2249 GIC         350 :             case JOIN_INNER:
    2250             350 :                 partexpr = list_concat_copy(outer_expr, inner_expr);
    2251             350 :                 nullable_partexpr = list_concat_copy(outer_null_expr,
    2252                 :                                                      inner_null_expr);
    2253 CBC         350 :                 break;
    2254                 : 
    2255                 :                 /*
    2256                 :                  * A join relation resulting from a SEMI or ANTI join may be
    2257                 :                  * regarded as partitioned by the outer relation keys.  The
    2258                 :                  * inner relation's keys are no longer interesting; since they
    2259                 :                  * aren't visible in the join output, nothing could join to
    2260                 :                  * them.
    2261                 :                  */
    2262 GIC         132 :             case JOIN_SEMI:
    2263                 :             case JOIN_ANTI:
    2264 CBC         132 :                 partexpr = list_copy(outer_expr);
    2265 GIC         132 :                 nullable_partexpr = list_copy(outer_null_expr);
    2266             132 :                 break;
    2267                 : 
    2268                 :                 /*
    2269                 :                  * A join relation resulting from a LEFT OUTER JOIN likewise
    2270                 :                  * may be regarded as partitioned on the (non-nullable) outer
    2271                 :                  * relation keys.  The inner (nullable) relation keys are okay
    2272 ECB             :                  * as partition keys for further joins as long as they involve
    2273                 :                  * strict join operators.
    2274                 :                  */
    2275 CBC         278 :             case JOIN_LEFT:
    2276 GIC         278 :                 partexpr = list_copy(outer_expr);
    2277             278 :                 nullable_partexpr = list_concat_copy(inner_expr,
    2278                 :                                                      outer_null_expr);
    2279             278 :                 nullable_partexpr = list_concat(nullable_partexpr,
    2280                 :                                                 inner_null_expr);
    2281             278 :                 break;
    2282                 : 
    2283                 :                 /*
    2284                 :                  * For FULL OUTER JOINs, both relations are nullable, so the
    2285                 :                  * resulting join relation may be regarded as partitioned on
    2286                 :                  * either of inner and outer relation keys, but only for joins
    2287                 :                  * that involve strict join operators.
    2288                 :                  */
    2289 CBC         143 :             case JOIN_FULL:
    2290             143 :                 nullable_partexpr = list_concat_copy(outer_expr,
    2291 ECB             :                                                      inner_expr);
    2292 CBC         143 :                 nullable_partexpr = list_concat(nullable_partexpr,
    2293 ECB             :                                                 outer_null_expr);
    2294 GIC         143 :                 nullable_partexpr = list_concat(nullable_partexpr,
    2295                 :                                                 inner_null_expr);
    2296 ECB             : 
    2297                 :                 /*
    2298                 :                  * Also add CoalesceExprs corresponding to each possible
    2299                 :                  * full-join output variable (that is, left side coalesced to
    2300                 :                  * right side), so that we can match equijoin expressions
    2301                 :                  * using those variables.  We really only need these for
    2302                 :                  * columns merged by JOIN USING, and only with the pairs of
    2303                 :                  * input items that correspond to the data structures that
    2304                 :                  * parse analysis would build for such variables.  But it's
    2305                 :                  * hard to tell which those are, so just make all the pairs.
    2306                 :                  * Extra items in the nullable_partexprs list won't cause big
    2307                 :                  * problems.  (It's possible that such items will get matched
    2308                 :                  * to user-written COALESCEs, but it should still be valid to
    2309                 :                  * partition on those, since they're going to be either the
    2310                 :                  * partition column or NULL; it's the same argument as for
    2311                 :                  * partitionwise nesting of any outer join.)  We assume no
    2312                 :                  * type coercions are needed to make the coalesce expressions,
    2313                 :                  * since columns of different types won't have gotten
    2314                 :                  * classified as the same PartitionScheme.  Note that we
    2315                 :                  * intentionally leave out the varnullingrels decoration that
    2316                 :                  * would ordinarily appear on the Vars inside these
    2317                 :                  * CoalesceExprs, because have_partkey_equi_join will strip
    2318                 :                  * varnullingrels from the expressions it will compare to the
    2319                 :                  * partexprs.
    2320                 :                  */
    2321 GIC         364 :                 foreach(lc, list_concat_copy(outer_expr, outer_null_expr))
    2322 ECB             :                 {
    2323 CBC         221 :                     Node       *larg = (Node *) lfirst(lc);
    2324                 :                     ListCell   *lc2;
    2325                 : 
    2326 GIC         442 :                     foreach(lc2, list_concat_copy(inner_expr, inner_null_expr))
    2327                 :                     {
    2328             221 :                         Node       *rarg = (Node *) lfirst(lc2);
    2329 CBC         221 :                         CoalesceExpr *c = makeNode(CoalesceExpr);
    2330 ECB             : 
    2331 CBC         221 :                         c->coalescetype = exprType(larg);
    2332 GIC         221 :                         c->coalescecollid = exprCollation(larg);
    2333             221 :                         c->args = list_make2(larg, rarg);
    2334             221 :                         c->location = -1;
    2335             221 :                         nullable_partexpr = lappend(nullable_partexpr, c);
    2336                 :                     }
    2337                 :                 }
    2338             143 :                 break;
    2339                 : 
    2340 UIC           0 :             default:
    2341               0 :                 elog(ERROR, "unrecognized join type: %d", (int) jointype);
    2342 ECB             :         }
    2343                 : 
    2344 GIC         903 :         joinrel->partexprs[cnt] = partexpr;
    2345             903 :         joinrel->nullable_partexprs[cnt] = nullable_partexpr;
    2346 ECB             :     }
    2347 GIC         897 : }
    2348                 : 
    2349                 : /*
    2350                 :  * build_child_join_reltarget
    2351                 :  *    Set up a child-join relation's reltarget from a parent-join relation.
    2352                 :  */
    2353                 : static void
    2354            2150 : build_child_join_reltarget(PlannerInfo *root,
    2355                 :                            RelOptInfo *parentrel,
    2356 ECB             :                            RelOptInfo *childrel,
    2357                 :                            int nappinfos,
    2358                 :                            AppendRelInfo **appinfos)
    2359                 : {
    2360                 :     /* Build the targetlist */
    2361 GIC        4300 :     childrel->reltarget->exprs = (List *)
    2362 CBC        2150 :         adjust_appendrel_attrs(root,
    2363 GIC        2150 :                                (Node *) parentrel->reltarget->exprs,
    2364                 :                                nappinfos, appinfos);
    2365                 : 
    2366                 :     /* Set the cost and width fields */
    2367            2150 :     childrel->reltarget->cost.startup = parentrel->reltarget->cost.startup;
    2368            2150 :     childrel->reltarget->cost.per_tuple = parentrel->reltarget->cost.per_tuple;
    2369            2150 :     childrel->reltarget->width = parentrel->reltarget->width;
    2370 CBC        2150 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a