LCOV - code coverage report
Current view: top level - src/backend/optimizer/util - relnode.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 96.5 % 988 953
Test Date: 2026-03-01 20:14:47 Functions: 100.0 % 38 38
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * relnode.c
       4              :  *    Relation-node lookup/construction routines
       5              :  *
       6              :  * Portions Copyright (c) 1996-2026, 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 "access/nbtree.h"
      20              : #include "catalog/pg_constraint.h"
      21              : #include "miscadmin.h"
      22              : #include "nodes/nodeFuncs.h"
      23              : #include "optimizer/appendinfo.h"
      24              : #include "optimizer/clauses.h"
      25              : #include "optimizer/cost.h"
      26              : #include "optimizer/inherit.h"
      27              : #include "optimizer/optimizer.h"
      28              : #include "optimizer/pathnode.h"
      29              : #include "optimizer/paths.h"
      30              : #include "optimizer/placeholder.h"
      31              : #include "optimizer/plancat.h"
      32              : #include "optimizer/planner.h"
      33              : #include "optimizer/restrictinfo.h"
      34              : #include "optimizer/tlist.h"
      35              : #include "parser/parse_oper.h"
      36              : #include "parser/parse_relation.h"
      37              : #include "rewrite/rewriteManip.h"
      38              : #include "utils/hsearch.h"
      39              : #include "utils/lsyscache.h"
      40              : #include "utils/selfuncs.h"
      41              : #include "utils/typcache.h"
      42              : 
      43              : 
      44              : typedef struct JoinHashEntry
      45              : {
      46              :     Relids      join_relids;    /* hash key --- MUST BE FIRST */
      47              :     RelOptInfo *join_rel;
      48              : } JoinHashEntry;
      49              : 
      50              : /* Hook for plugins to get control during joinrel setup */
      51              : joinrel_setup_hook_type joinrel_setup_hook = NULL;
      52              : 
      53              : static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
      54              :                                 RelOptInfo *input_rel,
      55              :                                 SpecialJoinInfo *sjinfo,
      56              :                                 List *pushed_down_joins,
      57              :                                 bool can_null);
      58              : static List *build_joinrel_restrictlist(PlannerInfo *root,
      59              :                                         RelOptInfo *joinrel,
      60              :                                         RelOptInfo *outer_rel,
      61              :                                         RelOptInfo *inner_rel,
      62              :                                         SpecialJoinInfo *sjinfo);
      63              : static void build_joinrel_joinlist(RelOptInfo *joinrel,
      64              :                                    RelOptInfo *outer_rel,
      65              :                                    RelOptInfo *inner_rel);
      66              : static List *subbuild_joinrel_restrictlist(PlannerInfo *root,
      67              :                                            RelOptInfo *joinrel,
      68              :                                            RelOptInfo *input_rel,
      69              :                                            Relids both_input_relids,
      70              :                                            List *new_restrictlist);
      71              : static List *subbuild_joinrel_joinlist(RelOptInfo *joinrel,
      72              :                                        List *joininfo_list,
      73              :                                        List *new_joininfo);
      74              : static void set_foreign_rel_properties(RelOptInfo *joinrel,
      75              :                                        RelOptInfo *outer_rel, RelOptInfo *inner_rel);
      76              : static void add_join_rel(PlannerInfo *root, RelOptInfo *joinrel);
      77              : static void build_joinrel_partition_info(PlannerInfo *root,
      78              :                                          RelOptInfo *joinrel,
      79              :                                          RelOptInfo *outer_rel, RelOptInfo *inner_rel,
      80              :                                          SpecialJoinInfo *sjinfo,
      81              :                                          List *restrictlist);
      82              : static bool have_partkey_equi_join(PlannerInfo *root, RelOptInfo *joinrel,
      83              :                                    RelOptInfo *rel1, RelOptInfo *rel2,
      84              :                                    JoinType jointype, List *restrictlist);
      85              : static int  match_expr_to_partition_keys(Expr *expr, RelOptInfo *rel,
      86              :                                          bool strict_op);
      87              : static void set_joinrel_partition_key_exprs(RelOptInfo *joinrel,
      88              :                                             RelOptInfo *outer_rel, RelOptInfo *inner_rel,
      89              :                                             JoinType jointype);
      90              : static void build_child_join_reltarget(PlannerInfo *root,
      91              :                                        RelOptInfo *parentrel,
      92              :                                        RelOptInfo *childrel,
      93              :                                        int nappinfos,
      94              :                                        AppendRelInfo **appinfos);
      95              : static bool eager_aggregation_possible_for_relation(PlannerInfo *root,
      96              :                                                     RelOptInfo *rel);
      97              : static bool init_grouping_targets(PlannerInfo *root, RelOptInfo *rel,
      98              :                                   PathTarget *target, PathTarget *agg_input,
      99              :                                   List **group_clauses, List **group_exprs);
     100              : static bool is_var_in_aggref_only(PlannerInfo *root, Var *var);
     101              : static bool is_var_needed_by_join(PlannerInfo *root, Var *var, RelOptInfo *rel);
     102              : static Index get_expression_sortgroupref(PlannerInfo *root, Expr *expr);
     103              : 
     104              : 
     105              : /*
     106              :  * setup_simple_rel_arrays
     107              :  *    Prepare the arrays we use for quickly accessing base relations
     108              :  *    and AppendRelInfos.
     109              :  */
     110              : void
     111       299002 : setup_simple_rel_arrays(PlannerInfo *root)
     112              : {
     113              :     int         size;
     114              :     Index       rti;
     115              :     ListCell   *lc;
     116              : 
     117              :     /* Arrays are accessed using RT indexes (1..N) */
     118       299002 :     size = list_length(root->parse->rtable) + 1;
     119       299002 :     root->simple_rel_array_size = size;
     120              : 
     121              :     /*
     122              :      * simple_rel_array is initialized to all NULLs, since no RelOptInfos
     123              :      * exist yet.  It'll be filled by later calls to build_simple_rel().
     124              :      */
     125       299002 :     root->simple_rel_array = (RelOptInfo **)
     126       299002 :         palloc0_array(RelOptInfo *, size);
     127              : 
     128              :     /* simple_rte_array is an array equivalent of the rtable list */
     129       299002 :     root->simple_rte_array = (RangeTblEntry **)
     130       299002 :         palloc0_array(RangeTblEntry *, size);
     131       299002 :     rti = 1;
     132       806517 :     foreach(lc, root->parse->rtable)
     133              :     {
     134       507515 :         RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
     135              : 
     136       507515 :         root->simple_rte_array[rti++] = rte;
     137              :     }
     138              : 
     139              :     /* append_rel_array is not needed if there are no AppendRelInfos */
     140       299002 :     if (root->append_rel_list == NIL)
     141              :     {
     142       296219 :         root->append_rel_array = NULL;
     143       296219 :         return;
     144              :     }
     145              : 
     146         2783 :     root->append_rel_array = (AppendRelInfo **)
     147         2783 :         palloc0_array(AppendRelInfo *, size);
     148              : 
     149              :     /*
     150              :      * append_rel_array is filled with any already-existing AppendRelInfos,
     151              :      * which currently could only come from UNION ALL flattening.  We might
     152              :      * add more later during inheritance expansion, but it's the
     153              :      * responsibility of the expansion code to update the array properly.
     154              :      */
     155        11635 :     foreach(lc, root->append_rel_list)
     156              :     {
     157         8852 :         AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
     158         8852 :         int         child_relid = appinfo->child_relid;
     159              : 
     160              :         /* Sanity check */
     161              :         Assert(child_relid < size);
     162              : 
     163         8852 :         if (root->append_rel_array[child_relid])
     164            0 :             elog(ERROR, "child relation already exists");
     165              : 
     166         8852 :         root->append_rel_array[child_relid] = appinfo;
     167              :     }
     168              : }
     169              : 
     170              : /*
     171              :  * expand_planner_arrays
     172              :  *      Expand the PlannerInfo's per-RTE arrays by add_size members
     173              :  *      and initialize the newly added entries to NULLs
     174              :  *
     175              :  * Note: this causes the append_rel_array to become allocated even if
     176              :  * it was not before.  This is okay for current uses, because we only call
     177              :  * this when adding child relations, which always have AppendRelInfos.
     178              :  */
     179              : void
     180        10291 : expand_planner_arrays(PlannerInfo *root, int add_size)
     181              : {
     182              :     int         new_size;
     183              : 
     184              :     Assert(add_size > 0);
     185              : 
     186        10291 :     new_size = root->simple_rel_array_size + add_size;
     187              : 
     188        10291 :     root->simple_rel_array =
     189        10291 :         repalloc0_array(root->simple_rel_array, RelOptInfo *, root->simple_rel_array_size, new_size);
     190              : 
     191        10291 :     root->simple_rte_array =
     192        10291 :         repalloc0_array(root->simple_rte_array, RangeTblEntry *, root->simple_rel_array_size, new_size);
     193              : 
     194        10291 :     if (root->append_rel_array)
     195         2997 :         root->append_rel_array =
     196         2997 :             repalloc0_array(root->append_rel_array, AppendRelInfo *, root->simple_rel_array_size, new_size);
     197              :     else
     198         7294 :         root->append_rel_array =
     199         7294 :             palloc0_array(AppendRelInfo *, new_size);
     200              : 
     201        10291 :     root->simple_rel_array_size = new_size;
     202        10291 : }
     203              : 
     204              : /*
     205              :  * build_simple_rel
     206              :  *    Construct a new RelOptInfo for a base relation or 'other' relation.
     207              :  */
     208              : RelOptInfo *
     209       416266 : build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
     210              : {
     211              :     RelOptInfo *rel;
     212              :     RangeTblEntry *rte;
     213              : 
     214              :     /* Rel should not exist already */
     215              :     Assert(relid > 0 && relid < root->simple_rel_array_size);
     216       416266 :     if (root->simple_rel_array[relid] != NULL)
     217            0 :         elog(ERROR, "rel %d already exists", relid);
     218              : 
     219              :     /* Fetch RTE for relation */
     220       416266 :     rte = root->simple_rte_array[relid];
     221              :     Assert(rte != NULL);
     222              : 
     223       416266 :     rel = makeNode(RelOptInfo);
     224       416266 :     rel->reloptkind = parent ? RELOPT_OTHER_MEMBER_REL : RELOPT_BASEREL;
     225       416266 :     rel->relids = bms_make_singleton(relid);
     226       416266 :     rel->rows = 0;
     227              :     /* cheap startup cost is interesting iff not all tuples to be retrieved */
     228       416266 :     rel->consider_startup = (root->tuple_fraction > 0);
     229       416266 :     rel->consider_param_startup = false; /* might get changed later */
     230       416266 :     rel->consider_parallel = false; /* might get changed later */
     231       416266 :     rel->pgs_mask = root->glob->default_pgs_mask;
     232       416266 :     rel->reltarget = create_empty_pathtarget();
     233       416266 :     rel->pathlist = NIL;
     234       416266 :     rel->ppilist = NIL;
     235       416266 :     rel->partial_pathlist = NIL;
     236       416266 :     rel->cheapest_startup_path = NULL;
     237       416266 :     rel->cheapest_total_path = NULL;
     238       416266 :     rel->cheapest_parameterized_paths = NIL;
     239       416266 :     rel->relid = relid;
     240       416266 :     rel->rtekind = rte->rtekind;
     241              :     /* min_attr, max_attr, attr_needed, attr_widths are set below */
     242       416266 :     rel->notnullattnums = NULL;
     243       416266 :     rel->lateral_vars = NIL;
     244       416266 :     rel->indexlist = NIL;
     245       416266 :     rel->statlist = NIL;
     246       416266 :     rel->pages = 0;
     247       416266 :     rel->tuples = 0;
     248       416266 :     rel->allvisfrac = 0;
     249       416266 :     rel->eclass_indexes = NULL;
     250       416266 :     rel->subroot = NULL;
     251       416266 :     rel->subplan_params = NIL;
     252       416266 :     rel->rel_parallel_workers = -1; /* set up in get_relation_info */
     253       416266 :     rel->amflags = 0;
     254       416266 :     rel->serverid = InvalidOid;
     255       416266 :     if (rte->rtekind == RTE_RELATION)
     256              :     {
     257              :         Assert(parent == NULL ||
     258              :                parent->rtekind == RTE_RELATION ||
     259              :                parent->rtekind == RTE_SUBQUERY);
     260              : 
     261              :         /*
     262              :          * For any RELATION rte, we need a userid with which to check
     263              :          * permission access. Baserels simply use their own
     264              :          * RTEPermissionInfo's checkAsUser.
     265              :          *
     266              :          * For otherrels normally there's no RTEPermissionInfo, so we use the
     267              :          * parent's, which normally has one. The exceptional case is that the
     268              :          * parent is a subquery, in which case the otherrel will have its own.
     269              :          */
     270       256135 :         if (rel->reloptkind == RELOPT_BASEREL ||
     271        22293 :             (rel->reloptkind == RELOPT_OTHER_MEMBER_REL &&
     272        22293 :              parent->rtekind == RTE_SUBQUERY))
     273       234397 :         {
     274              :             RTEPermissionInfo *perminfo;
     275              : 
     276       234397 :             perminfo = getRTEPermissionInfo(root->parse->rteperminfos, rte);
     277       234397 :             rel->userid = perminfo->checkAsUser;
     278              :         }
     279              :         else
     280        21738 :             rel->userid = parent->userid;
     281              :     }
     282              :     else
     283       160131 :         rel->userid = InvalidOid;
     284       416266 :     rel->useridiscurrent = false;
     285       416266 :     rel->fdwroutine = NULL;
     286       416266 :     rel->fdw_private = NULL;
     287       416266 :     rel->unique_for_rels = NIL;
     288       416266 :     rel->non_unique_for_rels = NIL;
     289       416266 :     rel->unique_rel = NULL;
     290       416266 :     rel->unique_pathkeys = NIL;
     291       416266 :     rel->unique_groupclause = NIL;
     292       416266 :     rel->baserestrictinfo = NIL;
     293       416266 :     rel->baserestrictcost.startup = 0;
     294       416266 :     rel->baserestrictcost.per_tuple = 0;
     295       416266 :     rel->baserestrict_min_security = UINT_MAX;
     296       416266 :     rel->joininfo = NIL;
     297       416266 :     rel->has_eclass_joins = false;
     298       416266 :     rel->consider_partitionwise_join = false;    /* might get changed later */
     299       416266 :     rel->agg_info = NULL;
     300       416266 :     rel->grouped_rel = NULL;
     301       416266 :     rel->part_scheme = NULL;
     302       416266 :     rel->nparts = -1;
     303       416266 :     rel->boundinfo = NULL;
     304       416266 :     rel->partbounds_merged = false;
     305       416266 :     rel->partition_qual = NIL;
     306       416266 :     rel->part_rels = NULL;
     307       416266 :     rel->live_parts = NULL;
     308       416266 :     rel->all_partrels = NULL;
     309       416266 :     rel->partexprs = NULL;
     310       416266 :     rel->nullable_partexprs = NULL;
     311              : 
     312              :     /*
     313              :      * Pass assorted information down the inheritance hierarchy.
     314              :      */
     315       416266 :     if (parent)
     316              :     {
     317              :         /* We keep back-links to immediate parent and topmost parent. */
     318        30590 :         rel->parent = parent;
     319        30590 :         rel->top_parent = parent->top_parent ? parent->top_parent : parent;
     320        30590 :         rel->top_parent_relids = rel->top_parent->relids;
     321              : 
     322              :         /*
     323              :          * A child rel is below the same outer joins as its parent.  (We
     324              :          * presume this info was already calculated for the parent.)
     325              :          */
     326        30590 :         rel->nulling_relids = parent->nulling_relids;
     327              : 
     328              :         /*
     329              :          * Also propagate lateral-reference information from appendrel parent
     330              :          * rels to their child rels.  We intentionally give each child rel the
     331              :          * same minimum parameterization, even though it's quite possible that
     332              :          * some don't reference all the lateral rels.  This is because any
     333              :          * append path for the parent will have to have the same
     334              :          * parameterization for every child anyway, and there's no value in
     335              :          * forcing extra reparameterize_path() calls.  Similarly, a lateral
     336              :          * reference to the parent prevents use of otherwise-movable join rels
     337              :          * for each child.
     338              :          *
     339              :          * It's possible for child rels to have their own children, in which
     340              :          * case the topmost parent's lateral info propagates all the way down.
     341              :          */
     342        30590 :         rel->direct_lateral_relids = parent->direct_lateral_relids;
     343        30590 :         rel->lateral_relids = parent->lateral_relids;
     344        30590 :         rel->lateral_referencers = parent->lateral_referencers;
     345              :     }
     346              :     else
     347              :     {
     348       385676 :         rel->parent = NULL;
     349       385676 :         rel->top_parent = NULL;
     350       385676 :         rel->top_parent_relids = NULL;
     351       385676 :         rel->nulling_relids = NULL;
     352       385676 :         rel->direct_lateral_relids = NULL;
     353       385676 :         rel->lateral_relids = NULL;
     354       385676 :         rel->lateral_referencers = NULL;
     355              :     }
     356              : 
     357              :     /* Check type of rtable entry */
     358       416266 :     switch (rte->rtekind)
     359              :     {
     360       256135 :         case RTE_RELATION:
     361              :             /* Table --- retrieve statistics from the system catalogs */
     362       256135 :             get_relation_info(root, rte->relid, rte->inh, rel);
     363       256126 :             break;
     364        59380 :         case RTE_SUBQUERY:
     365              :         case RTE_FUNCTION:
     366              :         case RTE_TABLEFUNC:
     367              :         case RTE_VALUES:
     368              :         case RTE_CTE:
     369              :         case RTE_NAMEDTUPLESTORE:
     370              : 
     371              :             /*
     372              :              * Subquery, function, tablefunc, values list, CTE, or ENR --- set
     373              :              * up attr range and arrays
     374              :              *
     375              :              * Note: 0 is included in range to support whole-row Vars
     376              :              */
     377        59380 :             rel->min_attr = 0;
     378        59380 :             rel->max_attr = list_length(rte->eref->colnames);
     379        59380 :             rel->attr_needed = (Relids *)
     380        59380 :                 palloc0_array(Relids, rel->max_attr - rel->min_attr + 1);
     381        59380 :             rel->attr_widths = (int32 *)
     382        59380 :                 palloc0_array(int32, rel->max_attr - rel->min_attr + 1);
     383        59380 :             break;
     384       100751 :         case RTE_RESULT:
     385              :             /* RTE_RESULT has no columns, nor could it have whole-row Var */
     386       100751 :             rel->min_attr = 0;
     387       100751 :             rel->max_attr = -1;
     388       100751 :             rel->attr_needed = NULL;
     389       100751 :             rel->attr_widths = NULL;
     390       100751 :             break;
     391            0 :         default:
     392            0 :             elog(ERROR, "unrecognized RTE kind: %d",
     393              :                  (int) rte->rtekind);
     394              :             break;
     395              :     }
     396              : 
     397              :     /*
     398              :      * We must apply the partially filled in RelOptInfo before calling
     399              :      * apply_child_basequals due to some transformations within that function
     400              :      * which require the RelOptInfo to be available in the simple_rel_array.
     401              :      */
     402       416257 :     root->simple_rel_array[relid] = rel;
     403              : 
     404              :     /*
     405              :      * Apply the parent's quals to the child, with appropriate substitution of
     406              :      * variables.  If the resulting clause is constant-FALSE or NULL after
     407              :      * applying transformations, apply_child_basequals returns false to
     408              :      * indicate that scanning this relation won't yield any rows.  In this
     409              :      * case, we mark the child as dummy right away.  (We must do this
     410              :      * immediately so that pruning works correctly when recursing in
     411              :      * expand_partitioned_rtentry.)
     412              :      */
     413       416257 :     if (parent)
     414              :     {
     415        30590 :         AppendRelInfo *appinfo = root->append_rel_array[relid];
     416              : 
     417              :         Assert(appinfo != NULL);
     418        30590 :         if (!apply_child_basequals(root, parent, rel, rte, appinfo))
     419              :         {
     420              :             /*
     421              :              * Restriction clause reduced to constant FALSE or NULL.  Mark as
     422              :              * dummy so we won't scan this relation.
     423              :              */
     424           48 :             mark_dummy_rel(rel);
     425              :         }
     426              :     }
     427              : 
     428       416257 :     return rel;
     429              : }
     430              : 
     431              : /*
     432              :  * build_simple_grouped_rel
     433              :  *    Construct a new RelOptInfo representing a grouped version of the input
     434              :  *    simple relation.
     435              :  */
     436              : RelOptInfo *
     437         1536 : build_simple_grouped_rel(PlannerInfo *root, RelOptInfo *rel)
     438              : {
     439              :     RelOptInfo *grouped_rel;
     440              :     RelAggInfo *agg_info;
     441              : 
     442              :     /*
     443              :      * We should have available aggregate expressions and grouping
     444              :      * expressions, otherwise we cannot reach here.
     445              :      */
     446              :     Assert(root->agg_clause_list != NIL);
     447              :     Assert(root->group_expr_list != NIL);
     448              : 
     449              :     /* nothing to do for dummy rel */
     450         1536 :     if (IS_DUMMY_REL(rel))
     451            0 :         return NULL;
     452              : 
     453              :     /*
     454              :      * Prepare the information needed to create grouped paths for this simple
     455              :      * relation.
     456              :      */
     457         1536 :     agg_info = create_rel_agg_info(root, rel, true);
     458         1536 :     if (agg_info == NULL)
     459         1112 :         return NULL;
     460              : 
     461              :     /*
     462              :      * If grouped paths for the given simple relation are not considered
     463              :      * useful, skip building the grouped relation.
     464              :      */
     465          424 :     if (!agg_info->agg_useful)
     466          131 :         return NULL;
     467              : 
     468              :     /* Track the set of relids at which partial aggregation is applied */
     469          293 :     agg_info->apply_agg_at = bms_copy(rel->relids);
     470              : 
     471              :     /* build the grouped relation */
     472          293 :     grouped_rel = build_grouped_rel(root, rel);
     473          293 :     grouped_rel->reltarget = agg_info->target;
     474          293 :     grouped_rel->rows = agg_info->grouped_rows;
     475          293 :     grouped_rel->agg_info = agg_info;
     476              : 
     477          293 :     rel->grouped_rel = grouped_rel;
     478              : 
     479          293 :     return grouped_rel;
     480              : }
     481              : 
     482              : /*
     483              :  * build_grouped_rel
     484              :  *    Build a grouped relation by flat copying the input relation and resetting
     485              :  *    the necessary fields.
     486              :  */
     487              : RelOptInfo *
     488         8728 : build_grouped_rel(PlannerInfo *root, RelOptInfo *rel)
     489              : {
     490              :     RelOptInfo *grouped_rel;
     491              : 
     492         8728 :     grouped_rel = makeNode(RelOptInfo);
     493         8728 :     memcpy(grouped_rel, rel, sizeof(RelOptInfo));
     494              : 
     495              :     /*
     496              :      * clear path info
     497              :      */
     498         8728 :     grouped_rel->pathlist = NIL;
     499         8728 :     grouped_rel->ppilist = NIL;
     500         8728 :     grouped_rel->partial_pathlist = NIL;
     501         8728 :     grouped_rel->cheapest_startup_path = NULL;
     502         8728 :     grouped_rel->cheapest_total_path = NULL;
     503         8728 :     grouped_rel->cheapest_parameterized_paths = NIL;
     504              : 
     505              :     /*
     506              :      * clear partition info
     507              :      */
     508         8728 :     grouped_rel->part_scheme = NULL;
     509         8728 :     grouped_rel->nparts = -1;
     510         8728 :     grouped_rel->boundinfo = NULL;
     511         8728 :     grouped_rel->partbounds_merged = false;
     512         8728 :     grouped_rel->partition_qual = NIL;
     513         8728 :     grouped_rel->part_rels = NULL;
     514         8728 :     grouped_rel->live_parts = NULL;
     515         8728 :     grouped_rel->all_partrels = NULL;
     516         8728 :     grouped_rel->partexprs = NULL;
     517         8728 :     grouped_rel->nullable_partexprs = NULL;
     518         8728 :     grouped_rel->consider_partitionwise_join = false;
     519              : 
     520              :     /*
     521              :      * clear size estimates
     522              :      */
     523         8728 :     grouped_rel->rows = 0;
     524              : 
     525         8728 :     return grouped_rel;
     526              : }
     527              : 
     528              : /*
     529              :  * find_base_rel
     530              :  *    Find a base or otherrel relation entry, which must already exist.
     531              :  */
     532              : RelOptInfo *
     533      3980101 : find_base_rel(PlannerInfo *root, int relid)
     534              : {
     535              :     RelOptInfo *rel;
     536              : 
     537              :     /* use an unsigned comparison to prevent negative array element access */
     538      3980101 :     if ((uint32) relid < (uint32) root->simple_rel_array_size)
     539              :     {
     540      3980101 :         rel = root->simple_rel_array[relid];
     541      3980101 :         if (rel)
     542      3980101 :             return rel;
     543              :     }
     544              : 
     545            0 :     elog(ERROR, "no relation entry for relid %d", relid);
     546              : 
     547              :     return NULL;                /* keep compiler quiet */
     548              : }
     549              : 
     550              : /*
     551              :  * find_base_rel_noerr
     552              :  *    Find a base or otherrel relation entry, returning NULL if there's none
     553              :  */
     554              : RelOptInfo *
     555       892239 : find_base_rel_noerr(PlannerInfo *root, int relid)
     556              : {
     557              :     /* use an unsigned comparison to prevent negative array element access */
     558       892239 :     if ((uint32) relid < (uint32) root->simple_rel_array_size)
     559       892239 :         return root->simple_rel_array[relid];
     560            0 :     return NULL;
     561              : }
     562              : 
     563              : /*
     564              :  * find_base_rel_ignore_join
     565              :  *    Find a base or otherrel relation entry, which must already exist.
     566              :  *
     567              :  * Unlike find_base_rel, if relid references an outer join then this
     568              :  * will return NULL rather than raising an error.  This is convenient
     569              :  * for callers that must deal with relid sets including both base and
     570              :  * outer joins.
     571              :  */
     572              : RelOptInfo *
     573       105266 : find_base_rel_ignore_join(PlannerInfo *root, int relid)
     574              : {
     575              :     /* use an unsigned comparison to prevent negative array element access */
     576       105266 :     if ((uint32) relid < (uint32) root->simple_rel_array_size)
     577              :     {
     578              :         RelOptInfo *rel;
     579              :         RangeTblEntry *rte;
     580              : 
     581       105266 :         rel = root->simple_rel_array[relid];
     582       105266 :         if (rel)
     583        98043 :             return rel;
     584              : 
     585              :         /*
     586              :          * We could just return NULL here, but for debugging purposes it seems
     587              :          * best to actually verify that the relid is an outer join and not
     588              :          * something weird.
     589              :          */
     590         7223 :         rte = root->simple_rte_array[relid];
     591         7223 :         if (rte && rte->rtekind == RTE_JOIN && rte->jointype != JOIN_INNER)
     592         7223 :             return NULL;
     593              :     }
     594              : 
     595            0 :     elog(ERROR, "no relation entry for relid %d", relid);
     596              : 
     597              :     return NULL;                /* keep compiler quiet */
     598              : }
     599              : 
     600              : /*
     601              :  * build_join_rel_hash
     602              :  *    Construct the auxiliary hash table for join relations.
     603              :  */
     604              : static void
     605           28 : build_join_rel_hash(PlannerInfo *root)
     606              : {
     607              :     HTAB       *hashtab;
     608              :     HASHCTL     hash_ctl;
     609              :     ListCell   *l;
     610              : 
     611              :     /* Create the hash table */
     612           28 :     hash_ctl.keysize = sizeof(Relids);
     613           28 :     hash_ctl.entrysize = sizeof(JoinHashEntry);
     614           28 :     hash_ctl.hash = bitmap_hash;
     615           28 :     hash_ctl.match = bitmap_match;
     616           28 :     hash_ctl.hcxt = CurrentMemoryContext;
     617           28 :     hashtab = hash_create("JoinRelHashTable",
     618              :                           256L,
     619              :                           &hash_ctl,
     620              :                           HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT);
     621              : 
     622              :     /* Insert all the already-existing joinrels */
     623          952 :     foreach(l, root->join_rel_list)
     624              :     {
     625          924 :         RelOptInfo *rel = (RelOptInfo *) lfirst(l);
     626              :         JoinHashEntry *hentry;
     627              :         bool        found;
     628              : 
     629          924 :         hentry = (JoinHashEntry *) hash_search(hashtab,
     630          924 :                                                &(rel->relids),
     631              :                                                HASH_ENTER,
     632              :                                                &found);
     633              :         Assert(!found);
     634          924 :         hentry->join_rel = rel;
     635              :     }
     636              : 
     637           28 :     root->join_rel_hash = hashtab;
     638           28 : }
     639              : 
     640              : /*
     641              :  * find_join_rel
     642              :  *    Returns relation entry corresponding to 'relids' (a set of RT indexes),
     643              :  *    or NULL if none exists.  This is for join relations.
     644              :  */
     645              : RelOptInfo *
     646       193095 : find_join_rel(PlannerInfo *root, Relids relids)
     647              : {
     648              :     /*
     649              :      * Switch to using hash lookup when list grows "too long".  The threshold
     650              :      * is arbitrary and is known only here.
     651              :      */
     652       193095 :     if (!root->join_rel_hash && list_length(root->join_rel_list) > 32)
     653           28 :         build_join_rel_hash(root);
     654              : 
     655              :     /*
     656              :      * Use either hashtable lookup or linear search, as appropriate.
     657              :      *
     658              :      * Note: the seemingly redundant hashkey variable is used to avoid taking
     659              :      * the address of relids; unless the compiler is exceedingly smart, doing
     660              :      * so would force relids out of a register and thus probably slow down the
     661              :      * list-search case.
     662              :      */
     663       193095 :     if (root->join_rel_hash)
     664              :     {
     665         2352 :         Relids      hashkey = relids;
     666              :         JoinHashEntry *hentry;
     667              : 
     668         2352 :         hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
     669              :                                                &hashkey,
     670              :                                                HASH_FIND,
     671              :                                                NULL);
     672         2352 :         if (hentry)
     673         2079 :             return hentry->join_rel;
     674              :     }
     675              :     else
     676              :     {
     677              :         ListCell   *l;
     678              : 
     679      1248683 :         foreach(l, root->join_rel_list)
     680              :         {
     681      1126892 :             RelOptInfo *rel = (RelOptInfo *) lfirst(l);
     682              : 
     683      1126892 :             if (bms_equal(rel->relids, relids))
     684        68952 :                 return rel;
     685              :         }
     686              :     }
     687              : 
     688       122064 :     return NULL;
     689              : }
     690              : 
     691              : /*
     692              :  * set_foreign_rel_properties
     693              :  *      Set up foreign-join fields if outer and inner relation are foreign
     694              :  *      tables (or joins) belonging to the same server and assigned to the same
     695              :  *      user to check access permissions as.
     696              :  *
     697              :  * In addition to an exact match of userid, we allow the case where one side
     698              :  * has zero userid (implying current user) and the other side has explicit
     699              :  * userid that happens to equal the current user; but in that case, pushdown of
     700              :  * the join is only valid for the current user.  The useridiscurrent field
     701              :  * records whether we had to make such an assumption for this join or any
     702              :  * sub-join.
     703              :  *
     704              :  * Otherwise these fields are left invalid, so GetForeignJoinPaths will not be
     705              :  * called for the join relation.
     706              :  */
     707              : static void
     708       130788 : set_foreign_rel_properties(RelOptInfo *joinrel, RelOptInfo *outer_rel,
     709              :                            RelOptInfo *inner_rel)
     710              : {
     711       130788 :     if (OidIsValid(outer_rel->serverid) &&
     712          449 :         inner_rel->serverid == outer_rel->serverid)
     713              :     {
     714          403 :         if (inner_rel->userid == outer_rel->userid)
     715              :         {
     716          397 :             joinrel->serverid = outer_rel->serverid;
     717          397 :             joinrel->userid = outer_rel->userid;
     718          397 :             joinrel->useridiscurrent = outer_rel->useridiscurrent || inner_rel->useridiscurrent;
     719          397 :             joinrel->fdwroutine = outer_rel->fdwroutine;
     720              :         }
     721           10 :         else if (!OidIsValid(inner_rel->userid) &&
     722            4 :                  outer_rel->userid == GetUserId())
     723              :         {
     724            2 :             joinrel->serverid = outer_rel->serverid;
     725            2 :             joinrel->userid = outer_rel->userid;
     726            2 :             joinrel->useridiscurrent = true;
     727            2 :             joinrel->fdwroutine = outer_rel->fdwroutine;
     728              :         }
     729            4 :         else if (!OidIsValid(outer_rel->userid) &&
     730            0 :                  inner_rel->userid == GetUserId())
     731              :         {
     732            0 :             joinrel->serverid = outer_rel->serverid;
     733            0 :             joinrel->userid = inner_rel->userid;
     734            0 :             joinrel->useridiscurrent = true;
     735            0 :             joinrel->fdwroutine = outer_rel->fdwroutine;
     736              :         }
     737              :     }
     738       130788 : }
     739              : 
     740              : /*
     741              :  * add_join_rel
     742              :  *      Add given join relation to the list of join relations in the given
     743              :  *      PlannerInfo. Also add it to the auxiliary hashtable if there is one.
     744              :  */
     745              : static void
     746       130788 : add_join_rel(PlannerInfo *root, RelOptInfo *joinrel)
     747              : {
     748              :     /* GEQO requires us to append the new joinrel to the end of the list! */
     749       130788 :     root->join_rel_list = lappend(root->join_rel_list, joinrel);
     750              : 
     751              :     /* store it into the auxiliary hashtable if there is one. */
     752       130788 :     if (root->join_rel_hash)
     753              :     {
     754              :         JoinHashEntry *hentry;
     755              :         bool        found;
     756              : 
     757          273 :         hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
     758          273 :                                                &(joinrel->relids),
     759              :                                                HASH_ENTER,
     760              :                                                &found);
     761              :         Assert(!found);
     762          273 :         hentry->join_rel = joinrel;
     763              :     }
     764       130788 : }
     765              : 
     766              : /*
     767              :  * build_join_rel
     768              :  *    Returns relation entry corresponding to the union of two given rels,
     769              :  *    creating a new relation entry if none already exists.
     770              :  *
     771              :  * 'joinrelids' is the Relids set that uniquely identifies the join
     772              :  * 'outer_rel' and 'inner_rel' are relation nodes for the relations to be
     773              :  *      joined
     774              :  * 'sjinfo': join context info
     775              :  * 'pushed_down_joins': any pushed-down outer joins that are now completed
     776              :  * 'restrictlist_ptr': result variable.  If not NULL, *restrictlist_ptr
     777              :  *      receives the list of RestrictInfo nodes that apply to this
     778              :  *      particular pair of joinable relations.
     779              :  *
     780              :  * restrictlist_ptr makes the routine's API a little grotty, but it saves
     781              :  * duplicated calculation of the restrictlist...
     782              :  */
     783              : RelOptInfo *
     784       191117 : build_join_rel(PlannerInfo *root,
     785              :                Relids joinrelids,
     786              :                RelOptInfo *outer_rel,
     787              :                RelOptInfo *inner_rel,
     788              :                SpecialJoinInfo *sjinfo,
     789              :                List *pushed_down_joins,
     790              :                List **restrictlist_ptr)
     791              : {
     792              :     RelOptInfo *joinrel;
     793              :     List       *restrictlist;
     794              : 
     795              :     /* This function should be used only for join between parents. */
     796              :     Assert(!IS_OTHER_REL(outer_rel) && !IS_OTHER_REL(inner_rel));
     797              : 
     798              :     /*
     799              :      * See if we already have a joinrel for this set of base rels.
     800              :      */
     801       191117 :     joinrel = find_join_rel(root, joinrelids);
     802              : 
     803       191117 :     if (joinrel)
     804              :     {
     805              :         /*
     806              :          * Yes, so we only need to figure the restrictlist for this particular
     807              :          * pair of component relations.
     808              :          */
     809        69514 :         if (restrictlist_ptr)
     810        69514 :             *restrictlist_ptr = build_joinrel_restrictlist(root,
     811              :                                                            joinrel,
     812              :                                                            outer_rel,
     813              :                                                            inner_rel,
     814              :                                                            sjinfo);
     815        69514 :         return joinrel;
     816              :     }
     817              : 
     818              :     /*
     819              :      * Nope, so make one.
     820              :      */
     821       121603 :     joinrel = makeNode(RelOptInfo);
     822       121603 :     joinrel->reloptkind = RELOPT_JOINREL;
     823       121603 :     joinrel->relids = bms_copy(joinrelids);
     824       121603 :     joinrel->rows = 0;
     825              :     /* cheap startup cost is interesting iff not all tuples to be retrieved */
     826       121603 :     joinrel->consider_startup = (root->tuple_fraction > 0);
     827       121603 :     joinrel->consider_param_startup = false;
     828       121603 :     joinrel->consider_parallel = false;
     829       121603 :     joinrel->pgs_mask = root->glob->default_pgs_mask;
     830       121603 :     joinrel->reltarget = create_empty_pathtarget();
     831       121603 :     joinrel->pathlist = NIL;
     832       121603 :     joinrel->ppilist = NIL;
     833       121603 :     joinrel->partial_pathlist = NIL;
     834       121603 :     joinrel->cheapest_startup_path = NULL;
     835       121603 :     joinrel->cheapest_total_path = NULL;
     836       121603 :     joinrel->cheapest_parameterized_paths = NIL;
     837              :     /* init direct_lateral_relids from children; we'll finish it up below */
     838       121603 :     joinrel->direct_lateral_relids =
     839       121603 :         bms_union(outer_rel->direct_lateral_relids,
     840       121603 :                   inner_rel->direct_lateral_relids);
     841       121603 :     joinrel->lateral_relids = min_join_parameterization(root, joinrel->relids,
     842              :                                                         outer_rel, inner_rel);
     843       121603 :     joinrel->relid = 0;          /* indicates not a baserel */
     844       121603 :     joinrel->rtekind = RTE_JOIN;
     845       121603 :     joinrel->min_attr = 0;
     846       121603 :     joinrel->max_attr = 0;
     847       121603 :     joinrel->attr_needed = NULL;
     848       121603 :     joinrel->attr_widths = NULL;
     849       121603 :     joinrel->notnullattnums = NULL;
     850       121603 :     joinrel->nulling_relids = NULL;
     851       121603 :     joinrel->lateral_vars = NIL;
     852       121603 :     joinrel->lateral_referencers = NULL;
     853       121603 :     joinrel->indexlist = NIL;
     854       121603 :     joinrel->statlist = NIL;
     855       121603 :     joinrel->pages = 0;
     856       121603 :     joinrel->tuples = 0;
     857       121603 :     joinrel->allvisfrac = 0;
     858       121603 :     joinrel->eclass_indexes = NULL;
     859       121603 :     joinrel->subroot = NULL;
     860       121603 :     joinrel->subplan_params = NIL;
     861       121603 :     joinrel->rel_parallel_workers = -1;
     862       121603 :     joinrel->amflags = 0;
     863       121603 :     joinrel->serverid = InvalidOid;
     864       121603 :     joinrel->userid = InvalidOid;
     865       121603 :     joinrel->useridiscurrent = false;
     866       121603 :     joinrel->fdwroutine = NULL;
     867       121603 :     joinrel->fdw_private = NULL;
     868       121603 :     joinrel->unique_for_rels = NIL;
     869       121603 :     joinrel->non_unique_for_rels = NIL;
     870       121603 :     joinrel->unique_rel = NULL;
     871       121603 :     joinrel->unique_pathkeys = NIL;
     872       121603 :     joinrel->unique_groupclause = NIL;
     873       121603 :     joinrel->baserestrictinfo = NIL;
     874       121603 :     joinrel->baserestrictcost.startup = 0;
     875       121603 :     joinrel->baserestrictcost.per_tuple = 0;
     876       121603 :     joinrel->baserestrict_min_security = UINT_MAX;
     877       121603 :     joinrel->joininfo = NIL;
     878       121603 :     joinrel->has_eclass_joins = false;
     879       121603 :     joinrel->consider_partitionwise_join = false;    /* might get changed later */
     880       121603 :     joinrel->agg_info = NULL;
     881       121603 :     joinrel->grouped_rel = NULL;
     882       121603 :     joinrel->parent = NULL;
     883       121603 :     joinrel->top_parent = NULL;
     884       121603 :     joinrel->top_parent_relids = NULL;
     885       121603 :     joinrel->part_scheme = NULL;
     886       121603 :     joinrel->nparts = -1;
     887       121603 :     joinrel->boundinfo = NULL;
     888       121603 :     joinrel->partbounds_merged = false;
     889       121603 :     joinrel->partition_qual = NIL;
     890       121603 :     joinrel->part_rels = NULL;
     891       121603 :     joinrel->live_parts = NULL;
     892       121603 :     joinrel->all_partrels = NULL;
     893       121603 :     joinrel->partexprs = NULL;
     894       121603 :     joinrel->nullable_partexprs = NULL;
     895              : 
     896              :     /* Compute information relevant to the foreign relations. */
     897       121603 :     set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
     898              : 
     899              :     /*
     900              :      * Fill the joinrel's tlist with just the Vars and PHVs that need to be
     901              :      * output from this join (ie, are needed for higher joinclauses or final
     902              :      * output).
     903              :      *
     904              :      * NOTE: the tlist order for a join rel will depend on which pair of outer
     905              :      * and inner rels we first try to build it from.  But the contents should
     906              :      * be the same regardless.
     907              :      */
     908       121603 :     build_joinrel_tlist(root, joinrel, outer_rel, sjinfo, pushed_down_joins,
     909       121603 :                         (sjinfo->jointype == JOIN_FULL));
     910       121603 :     build_joinrel_tlist(root, joinrel, inner_rel, sjinfo, pushed_down_joins,
     911       121603 :                         (sjinfo->jointype != JOIN_INNER));
     912       121603 :     add_placeholders_to_joinrel(root, joinrel, outer_rel, inner_rel, sjinfo);
     913              : 
     914              :     /*
     915              :      * add_placeholders_to_joinrel also took care of adding the ph_lateral
     916              :      * sets of any PlaceHolderVars computed here to direct_lateral_relids, so
     917              :      * now we can finish computing that.  This is much like the computation of
     918              :      * the transitively-closed lateral_relids in min_join_parameterization,
     919              :      * except that here we *do* have to consider the added PHVs.
     920              :      */
     921       121603 :     joinrel->direct_lateral_relids =
     922       121603 :         bms_del_members(joinrel->direct_lateral_relids, joinrel->relids);
     923              : 
     924              :     /*
     925              :      * Construct restrict and join clause lists for the new joinrel. (The
     926              :      * caller might or might not need the restrictlist, but I need it anyway
     927              :      * for set_joinrel_size_estimates().)
     928              :      */
     929       121603 :     restrictlist = build_joinrel_restrictlist(root, joinrel,
     930              :                                               outer_rel, inner_rel,
     931              :                                               sjinfo);
     932       121603 :     if (restrictlist_ptr)
     933       121603 :         *restrictlist_ptr = restrictlist;
     934       121603 :     build_joinrel_joinlist(joinrel, outer_rel, inner_rel);
     935              : 
     936              :     /*
     937              :      * This is also the right place to check whether the joinrel has any
     938              :      * pending EquivalenceClass joins.
     939              :      */
     940       121603 :     joinrel->has_eclass_joins = has_relevant_eclass_joinclause(root, joinrel);
     941              : 
     942              :     /*
     943              :      * Set estimates of the joinrel's size.
     944              :      */
     945       121603 :     set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
     946              :                                sjinfo, restrictlist);
     947              : 
     948              :     /*
     949              :      * Set the consider_parallel flag if this joinrel could potentially be
     950              :      * scanned within a parallel worker.  If this flag is false for either
     951              :      * inner_rel or outer_rel, then it must be false for the joinrel also.
     952              :      * Even if both are true, there might be parallel-restricted expressions
     953              :      * in the targetlist or quals.
     954              :      *
     955              :      * Note that if there are more than two rels in this relation, they could
     956              :      * be divided between inner_rel and outer_rel in any arbitrary way.  We
     957              :      * assume this doesn't matter, because we should hit all the same baserels
     958              :      * and joinclauses while building up to this joinrel no matter which we
     959              :      * take; therefore, we should make the same decision here however we get
     960              :      * here.
     961              :      */
     962       224298 :     if (inner_rel->consider_parallel && outer_rel->consider_parallel &&
     963       205017 :         is_parallel_safe(root, (Node *) restrictlist) &&
     964       102322 :         is_parallel_safe(root, (Node *) joinrel->reltarget->exprs))
     965       102316 :         joinrel->consider_parallel = true;
     966              : 
     967              :     /*
     968              :      * Allow a plugin to editorialize on the new joinrel's properties. Actions
     969              :      * might include altering the size estimate, clearing consider_parallel,
     970              :      * or adjusting pgs_mask.
     971              :      */
     972       121603 :     if (joinrel_setup_hook)
     973            0 :         (*joinrel_setup_hook) (root, joinrel, outer_rel, inner_rel, sjinfo,
     974              :                                restrictlist);
     975              : 
     976              :     /* Store the partition information. */
     977       121603 :     build_joinrel_partition_info(root, joinrel, outer_rel, inner_rel, sjinfo,
     978              :                                  restrictlist);
     979              : 
     980              :     /* Add the joinrel to the PlannerInfo. */
     981       121603 :     add_join_rel(root, joinrel);
     982              : 
     983              :     /*
     984              :      * Also, if dynamic-programming join search is active, add the new joinrel
     985              :      * to the appropriate sublist.  Note: you might think the Assert on number
     986              :      * of members should be for equality, but some of the level 1 rels might
     987              :      * have been joinrels already, so we can only assert <=.
     988              :      */
     989       121603 :     if (root->join_rel_level)
     990              :     {
     991              :         Assert(root->join_cur_level > 0);
     992              :         Assert(root->join_cur_level <= bms_num_members(joinrel->relids));
     993       118237 :         root->join_rel_level[root->join_cur_level] =
     994       118237 :             lappend(root->join_rel_level[root->join_cur_level], joinrel);
     995              :     }
     996              : 
     997       121603 :     return joinrel;
     998              : }
     999              : 
    1000              : /*
    1001              :  * build_child_join_rel
    1002              :  *    Builds RelOptInfo representing join between given two child relations.
    1003              :  *
    1004              :  * 'outer_rel' and 'inner_rel' are the RelOptInfos of child relations being
    1005              :  *      joined
    1006              :  * 'parent_joinrel' is the RelOptInfo representing the join between parent
    1007              :  *      relations. Some of the members of new RelOptInfo are produced by
    1008              :  *      translating corresponding members of this RelOptInfo
    1009              :  * 'restrictlist': list of RestrictInfo nodes that apply to this particular
    1010              :  *      pair of joinable relations
    1011              :  * 'sjinfo': child join's join-type details
    1012              :  * 'nappinfos' and 'appinfos': AppendRelInfo array for child relids
    1013              :  */
    1014              : RelOptInfo *
    1015         9185 : build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
    1016              :                      RelOptInfo *inner_rel, RelOptInfo *parent_joinrel,
    1017              :                      List *restrictlist, SpecialJoinInfo *sjinfo,
    1018              :                      int nappinfos, AppendRelInfo **appinfos)
    1019              : {
    1020         9185 :     RelOptInfo *joinrel = makeNode(RelOptInfo);
    1021              : 
    1022              :     /* Only joins between "other" relations land here. */
    1023              :     Assert(IS_OTHER_REL(outer_rel) && IS_OTHER_REL(inner_rel));
    1024              : 
    1025              :     /* The parent joinrel should have consider_partitionwise_join set. */
    1026              :     Assert(parent_joinrel->consider_partitionwise_join);
    1027              : 
    1028         9185 :     joinrel->reloptkind = RELOPT_OTHER_JOINREL;
    1029         9185 :     joinrel->relids = adjust_child_relids(parent_joinrel->relids,
    1030              :                                           nappinfos, appinfos);
    1031         9185 :     joinrel->rows = 0;
    1032              :     /* cheap startup cost is interesting iff not all tuples to be retrieved */
    1033         9185 :     joinrel->consider_startup = (root->tuple_fraction > 0);
    1034         9185 :     joinrel->consider_param_startup = false;
    1035         9185 :     joinrel->consider_parallel = false;
    1036         9185 :     joinrel->pgs_mask = root->glob->default_pgs_mask;
    1037         9185 :     joinrel->reltarget = create_empty_pathtarget();
    1038         9185 :     joinrel->pathlist = NIL;
    1039         9185 :     joinrel->ppilist = NIL;
    1040         9185 :     joinrel->partial_pathlist = NIL;
    1041         9185 :     joinrel->cheapest_startup_path = NULL;
    1042         9185 :     joinrel->cheapest_total_path = NULL;
    1043         9185 :     joinrel->cheapest_parameterized_paths = NIL;
    1044         9185 :     joinrel->direct_lateral_relids = NULL;
    1045         9185 :     joinrel->lateral_relids = NULL;
    1046         9185 :     joinrel->relid = 0;          /* indicates not a baserel */
    1047         9185 :     joinrel->rtekind = RTE_JOIN;
    1048         9185 :     joinrel->min_attr = 0;
    1049         9185 :     joinrel->max_attr = 0;
    1050         9185 :     joinrel->attr_needed = NULL;
    1051         9185 :     joinrel->attr_widths = NULL;
    1052         9185 :     joinrel->notnullattnums = NULL;
    1053         9185 :     joinrel->nulling_relids = NULL;
    1054         9185 :     joinrel->lateral_vars = NIL;
    1055         9185 :     joinrel->lateral_referencers = NULL;
    1056         9185 :     joinrel->indexlist = NIL;
    1057         9185 :     joinrel->pages = 0;
    1058         9185 :     joinrel->tuples = 0;
    1059         9185 :     joinrel->allvisfrac = 0;
    1060         9185 :     joinrel->eclass_indexes = NULL;
    1061         9185 :     joinrel->subroot = NULL;
    1062         9185 :     joinrel->subplan_params = NIL;
    1063         9185 :     joinrel->amflags = 0;
    1064         9185 :     joinrel->serverid = InvalidOid;
    1065         9185 :     joinrel->userid = InvalidOid;
    1066         9185 :     joinrel->useridiscurrent = false;
    1067         9185 :     joinrel->fdwroutine = NULL;
    1068         9185 :     joinrel->fdw_private = NULL;
    1069         9185 :     joinrel->unique_rel = NULL;
    1070         9185 :     joinrel->unique_pathkeys = NIL;
    1071         9185 :     joinrel->unique_groupclause = NIL;
    1072         9185 :     joinrel->baserestrictinfo = NIL;
    1073         9185 :     joinrel->baserestrictcost.startup = 0;
    1074         9185 :     joinrel->baserestrictcost.per_tuple = 0;
    1075         9185 :     joinrel->joininfo = NIL;
    1076         9185 :     joinrel->has_eclass_joins = false;
    1077         9185 :     joinrel->consider_partitionwise_join = false;    /* might get changed later */
    1078         9185 :     joinrel->agg_info = NULL;
    1079         9185 :     joinrel->grouped_rel = NULL;
    1080         9185 :     joinrel->parent = parent_joinrel;
    1081         9185 :     joinrel->top_parent = parent_joinrel->top_parent ? parent_joinrel->top_parent : parent_joinrel;
    1082         9185 :     joinrel->top_parent_relids = joinrel->top_parent->relids;
    1083         9185 :     joinrel->part_scheme = NULL;
    1084         9185 :     joinrel->nparts = -1;
    1085         9185 :     joinrel->boundinfo = NULL;
    1086         9185 :     joinrel->partbounds_merged = false;
    1087         9185 :     joinrel->partition_qual = NIL;
    1088         9185 :     joinrel->part_rels = NULL;
    1089         9185 :     joinrel->live_parts = NULL;
    1090         9185 :     joinrel->all_partrels = NULL;
    1091         9185 :     joinrel->partexprs = NULL;
    1092         9185 :     joinrel->nullable_partexprs = NULL;
    1093              : 
    1094              :     /* Compute information relevant to foreign relations. */
    1095         9185 :     set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
    1096              : 
    1097              :     /* Set up reltarget struct */
    1098         9185 :     build_child_join_reltarget(root, parent_joinrel, joinrel,
    1099              :                                nappinfos, appinfos);
    1100              : 
    1101              :     /* Construct joininfo list. */
    1102        18370 :     joinrel->joininfo = (List *) adjust_appendrel_attrs(root,
    1103         9185 :                                                         (Node *) parent_joinrel->joininfo,
    1104              :                                                         nappinfos,
    1105              :                                                         appinfos);
    1106              : 
    1107              :     /*
    1108              :      * Lateral relids referred in child join will be same as that referred in
    1109              :      * the parent relation.
    1110              :      */
    1111         9185 :     joinrel->direct_lateral_relids = (Relids) bms_copy(parent_joinrel->direct_lateral_relids);
    1112         9185 :     joinrel->lateral_relids = (Relids) bms_copy(parent_joinrel->lateral_relids);
    1113              : 
    1114              :     /*
    1115              :      * If the parent joinrel has pending equivalence classes, so does the
    1116              :      * child.
    1117              :      */
    1118         9185 :     joinrel->has_eclass_joins = parent_joinrel->has_eclass_joins;
    1119              : 
    1120              :     /* Child joinrel is parallel safe if parent is parallel safe. */
    1121         9185 :     joinrel->consider_parallel = parent_joinrel->consider_parallel;
    1122              : 
    1123              :     /* Set estimates of the child-joinrel's size. */
    1124         9185 :     set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
    1125              :                                sjinfo, restrictlist);
    1126              : 
    1127              :     /*
    1128              :      * Allow a plugin to editorialize on the new joinrel's properties. Actions
    1129              :      * might include altering the size estimate, clearing consider_parallel,
    1130              :      * or adjusting pgs_mask. (However, note that clearing consider_parallel
    1131              :      * would be better done in the parent joinrel rather than here.)
    1132              :      */
    1133         9185 :     if (joinrel_setup_hook)
    1134            0 :         (*joinrel_setup_hook) (root, joinrel, outer_rel, inner_rel, sjinfo,
    1135              :                                restrictlist);
    1136              : 
    1137              :     /* Is the join between partitions itself partitioned? */
    1138         9185 :     build_joinrel_partition_info(root, joinrel, outer_rel, inner_rel, sjinfo,
    1139              :                                  restrictlist);
    1140              : 
    1141              :     /* We build the join only once. */
    1142              :     Assert(!find_join_rel(root, joinrel->relids));
    1143              : 
    1144              :     /* Add the relation to the PlannerInfo. */
    1145         9185 :     add_join_rel(root, joinrel);
    1146              : 
    1147              :     /*
    1148              :      * We might need EquivalenceClass members corresponding to the child join,
    1149              :      * so that we can represent sort pathkeys for it.  As with children of
    1150              :      * baserels, we shouldn't need this unless there are relevant eclass joins
    1151              :      * (implying that a merge join might be possible) or pathkeys to sort by.
    1152              :      */
    1153         9185 :     if (joinrel->has_eclass_joins || has_useful_pathkeys(root, parent_joinrel))
    1154         8909 :         add_child_join_rel_equivalences(root,
    1155              :                                         nappinfos, appinfos,
    1156              :                                         parent_joinrel, joinrel);
    1157              : 
    1158         9185 :     return joinrel;
    1159              : }
    1160              : 
    1161              : /*
    1162              :  * min_join_parameterization
    1163              :  *
    1164              :  * Determine the minimum possible parameterization of a joinrel, that is, the
    1165              :  * set of other rels it contains LATERAL references to.  We save this value in
    1166              :  * the join's RelOptInfo.  This function is split out of build_join_rel()
    1167              :  * because join_is_legal() needs the value to check a prospective join.
    1168              :  */
    1169              : Relids
    1170       136726 : min_join_parameterization(PlannerInfo *root,
    1171              :                           Relids joinrelids,
    1172              :                           RelOptInfo *outer_rel,
    1173              :                           RelOptInfo *inner_rel)
    1174              : {
    1175              :     Relids      result;
    1176              : 
    1177              :     /*
    1178              :      * Basically we just need the union of the inputs' lateral_relids, less
    1179              :      * whatever is already in the join.
    1180              :      *
    1181              :      * It's not immediately obvious that this is a valid way to compute the
    1182              :      * result, because it might seem that we're ignoring possible lateral refs
    1183              :      * of PlaceHolderVars that are due to be computed at the join but not in
    1184              :      * either input.  However, because create_lateral_join_info() already
    1185              :      * charged all such PHV refs to each member baserel of the join, they'll
    1186              :      * be accounted for already in the inputs' lateral_relids.  Likewise, we
    1187              :      * do not need to worry about doing transitive closure here, because that
    1188              :      * was already accounted for in the original baserel lateral_relids.
    1189              :      */
    1190       136726 :     result = bms_union(outer_rel->lateral_relids, inner_rel->lateral_relids);
    1191       136726 :     result = bms_del_members(result, joinrelids);
    1192       136726 :     return result;
    1193              : }
    1194              : 
    1195              : /*
    1196              :  * build_joinrel_tlist
    1197              :  *    Builds a join relation's target list from an input relation.
    1198              :  *    (This is invoked twice to handle the two input relations.)
    1199              :  *
    1200              :  * The join's targetlist includes all Vars of its member relations that
    1201              :  * will still be needed above the join.  This subroutine adds all such
    1202              :  * Vars from the specified input rel's tlist to the join rel's tlist.
    1203              :  * Likewise for any PlaceHolderVars emitted by the input rel.
    1204              :  *
    1205              :  * We also compute the expected width of the join's output, making use
    1206              :  * of data that was cached at the baserel level by set_rel_width().
    1207              :  *
    1208              :  * Pass can_null as true if the join is an outer join that can null Vars
    1209              :  * from this input relation.  If so, we will (normally) add the join's relid
    1210              :  * to the nulling bitmaps of Vars and PHVs bubbled up from the input.
    1211              :  *
    1212              :  * When forming an outer join's target list, special handling is needed in
    1213              :  * case the outer join was commuted with another one per outer join identity 3
    1214              :  * (see optimizer/README).  We must take steps to ensure that the output Vars
    1215              :  * have the same nulling bitmaps that they would if the two joins had been
    1216              :  * done in syntactic order; else they won't match Vars appearing higher in
    1217              :  * the query tree.  An exception to the match-the-syntactic-order rule is
    1218              :  * that when an outer join is pushed down into another one's RHS per identity
    1219              :  * 3, we can't mark its Vars as nulled until the now-upper outer join is also
    1220              :  * completed.  So we need to do three things:
    1221              :  *
    1222              :  * First, we add the outer join's relid to the nulling bitmap only if the
    1223              :  * outer join has been completely performed and the Var or PHV actually
    1224              :  * comes from within the syntactically nullable side(s) of the outer join.
    1225              :  * This takes care of the possibility that we have transformed
    1226              :  *      (A leftjoin B on (Pab)) leftjoin C on (Pbc)
    1227              :  * to
    1228              :  *      A leftjoin (B leftjoin C on (Pbc)) on (Pab)
    1229              :  * Here the pushed-down B/C join cannot mark C columns as nulled yet,
    1230              :  * while the now-upper A/B join must not mark C columns as nulled by itself.
    1231              :  *
    1232              :  * Second, perform the same operation for each SpecialJoinInfo listed in
    1233              :  * pushed_down_joins (which, in this example, would be the B/C join when
    1234              :  * we are at the now-upper A/B join).  This allows the now-upper join to
    1235              :  * complete the marking of "C" Vars that now have fully valid values.
    1236              :  *
    1237              :  * Third, any relid in sjinfo->commute_above_r that is already part of
    1238              :  * the joinrel is added to the nulling bitmaps of nullable Vars and PHVs.
    1239              :  * This takes care of the reverse case where we implement
    1240              :  *      A leftjoin (B leftjoin C on (Pbc)) on (Pab)
    1241              :  * as
    1242              :  *      (A leftjoin B on (Pab)) leftjoin C on (Pbc)
    1243              :  * The C columns emitted by the B/C join need to be shown as nulled by both
    1244              :  * the B/C and A/B joins, even though they've not physically traversed the
    1245              :  * A/B join.
    1246              :  */
    1247              : static void
    1248       243206 : build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
    1249              :                     RelOptInfo *input_rel,
    1250              :                     SpecialJoinInfo *sjinfo,
    1251              :                     List *pushed_down_joins,
    1252              :                     bool can_null)
    1253              : {
    1254       243206 :     Relids      relids = joinrel->relids;
    1255       243206 :     int64       tuple_width = joinrel->reltarget->width;
    1256              :     ListCell   *vars;
    1257              :     ListCell   *lc;
    1258              : 
    1259      1258995 :     foreach(vars, input_rel->reltarget->exprs)
    1260              :     {
    1261      1015789 :         Var        *var = (Var *) lfirst(vars);
    1262              : 
    1263              :         /*
    1264              :          * For a PlaceHolderVar, we have to look up the PlaceHolderInfo.
    1265              :          */
    1266      1015789 :         if (IsA(var, PlaceHolderVar))
    1267         1055 :         {
    1268         1055 :             PlaceHolderVar *phv = (PlaceHolderVar *) var;
    1269         1055 :             PlaceHolderInfo *phinfo = find_placeholder_info(root, phv);
    1270              : 
    1271              :             /* Is it still needed above this joinrel? */
    1272         1055 :             if (bms_nonempty_difference(phinfo->ph_needed, relids))
    1273              :             {
    1274              :                 /*
    1275              :                  * Yup, add it to the output.  If this join potentially nulls
    1276              :                  * this input, we have to update the PHV's phnullingrels,
    1277              :                  * which means making a copy.
    1278              :                  */
    1279          797 :                 if (can_null)
    1280              :                 {
    1281          512 :                     phv = copyObject(phv);
    1282              :                     /* See comments above to understand this logic */
    1283         1024 :                     if (sjinfo->ojrelid != 0 &&
    1284         1012 :                         bms_is_member(sjinfo->ojrelid, relids) &&
    1285          500 :                         (bms_is_subset(phv->phrels, sjinfo->syn_righthand) ||
    1286          120 :                          (sjinfo->jointype == JOIN_FULL &&
    1287           57 :                           bms_is_subset(phv->phrels, sjinfo->syn_lefthand))))
    1288          494 :                         phv->phnullingrels = bms_add_member(phv->phnullingrels,
    1289          494 :                                                             sjinfo->ojrelid);
    1290          521 :                     foreach(lc, pushed_down_joins)
    1291              :                     {
    1292            9 :                         SpecialJoinInfo *othersj = (SpecialJoinInfo *) lfirst(lc);
    1293              : 
    1294              :                         Assert(bms_is_member(othersj->ojrelid, relids));
    1295            9 :                         if (bms_is_subset(phv->phrels, othersj->syn_righthand))
    1296            6 :                             phv->phnullingrels = bms_add_member(phv->phnullingrels,
    1297            6 :                                                                 othersj->ojrelid);
    1298              :                     }
    1299          512 :                     phv->phnullingrels =
    1300          512 :                         bms_join(phv->phnullingrels,
    1301          512 :                                  bms_intersect(sjinfo->commute_above_r,
    1302              :                                                relids));
    1303              :                 }
    1304              : 
    1305          797 :                 joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs,
    1306              :                                                     phv);
    1307              :                 /* Bubbling up the precomputed result has cost zero */
    1308          797 :                 tuple_width += phinfo->ph_width;
    1309              :             }
    1310         1055 :             continue;
    1311              :         }
    1312              : 
    1313              :         /*
    1314              :          * Otherwise, anything in a baserel or joinrel targetlist ought to be
    1315              :          * a Var.  (More general cases can only appear in appendrel child
    1316              :          * rels, which will never be seen here.)
    1317              :          */
    1318      1014734 :         if (!IsA(var, Var))
    1319            0 :             elog(ERROR, "unexpected node type in rel targetlist: %d",
    1320              :                  (int) nodeTag(var));
    1321              : 
    1322      1014734 :         if (var->varno == ROWID_VAR)
    1323              :         {
    1324              :             /* UPDATE/DELETE/MERGE row identity vars are always needed */
    1325              :             RowIdentityVarInfo *ridinfo = (RowIdentityVarInfo *)
    1326          628 :                 list_nth(root->row_identity_vars, var->varattno - 1);
    1327              : 
    1328              :             /* Update reltarget width estimate from RowIdentityVarInfo */
    1329          628 :             tuple_width += ridinfo->rowidwidth;
    1330              :         }
    1331              :         else
    1332              :         {
    1333              :             RelOptInfo *baserel;
    1334              :             int         ndx;
    1335              : 
    1336              :             /* Get the Var's original base rel */
    1337      1014106 :             baserel = find_base_rel(root, var->varno);
    1338              : 
    1339              :             /* Is it still needed above this joinrel? */
    1340      1014106 :             ndx = var->varattno - baserel->min_attr;
    1341      1014106 :             if (!bms_nonempty_difference(baserel->attr_needed[ndx], relids))
    1342       181909 :                 continue;       /* nope, skip it */
    1343              : 
    1344              :             /* Update reltarget width estimate from baserel's attr_widths */
    1345       832197 :             tuple_width += baserel->attr_widths[ndx];
    1346              :         }
    1347              : 
    1348              :         /*
    1349              :          * Add the Var to the output.  If this join potentially nulls this
    1350              :          * input, we have to update the Var's varnullingrels, which means
    1351              :          * making a copy.  But note that we don't ever add nullingrel bits to
    1352              :          * row identity Vars (cf. comments in setrefs.c).
    1353              :          */
    1354       832825 :         if (can_null && var->varno != ROWID_VAR)
    1355              :         {
    1356        81209 :             var = copyObject(var);
    1357              :             /* See comments above to understand this logic */
    1358       162059 :             if (sjinfo->ojrelid != 0 &&
    1359       158962 :                 bms_is_member(sjinfo->ojrelid, relids) &&
    1360        78112 :                 (bms_is_member(var->varno, sjinfo->syn_righthand) ||
    1361         1948 :                  (sjinfo->jointype == JOIN_FULL &&
    1362          908 :                   bms_is_member(var->varno, sjinfo->syn_lefthand))))
    1363        77980 :                 var->varnullingrels = bms_add_member(var->varnullingrels,
    1364        77980 :                                                      sjinfo->ojrelid);
    1365        81548 :             foreach(lc, pushed_down_joins)
    1366              :             {
    1367          339 :                 SpecialJoinInfo *othersj = (SpecialJoinInfo *) lfirst(lc);
    1368              : 
    1369              :                 Assert(bms_is_member(othersj->ojrelid, relids));
    1370          339 :                 if (bms_is_member(var->varno, othersj->syn_righthand))
    1371          132 :                     var->varnullingrels = bms_add_member(var->varnullingrels,
    1372          132 :                                                          othersj->ojrelid);
    1373              :             }
    1374        81209 :             var->varnullingrels =
    1375        81209 :                 bms_join(var->varnullingrels,
    1376        81209 :                          bms_intersect(sjinfo->commute_above_r,
    1377              :                                        relids));
    1378              :         }
    1379              : 
    1380       832825 :         joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs,
    1381              :                                             var);
    1382              : 
    1383              :         /* Vars have cost zero, so no need to adjust reltarget->cost */
    1384              :     }
    1385              : 
    1386       243206 :     joinrel->reltarget->width = clamp_width_est(tuple_width);
    1387       243206 : }
    1388              : 
    1389              : /*
    1390              :  * build_joinrel_restrictlist
    1391              :  * build_joinrel_joinlist
    1392              :  *    These routines build lists of restriction and join clauses for a
    1393              :  *    join relation from the joininfo lists of the relations it joins.
    1394              :  *
    1395              :  *    These routines are separate because the restriction list must be
    1396              :  *    built afresh for each pair of input sub-relations we consider, whereas
    1397              :  *    the join list need only be computed once for any join RelOptInfo.
    1398              :  *    The join list is fully determined by the set of rels making up the
    1399              :  *    joinrel, so we should get the same results (up to ordering) from any
    1400              :  *    candidate pair of sub-relations.  But the restriction list is whatever
    1401              :  *    is not handled in the sub-relations, so it depends on which
    1402              :  *    sub-relations are considered.
    1403              :  *
    1404              :  *    If a join clause from an input relation refers to base+OJ rels still not
    1405              :  *    present in the joinrel, then it is still a join clause for the joinrel;
    1406              :  *    we put it into the joininfo list for the joinrel.  Otherwise,
    1407              :  *    the clause is now a restrict clause for the joined relation, and we
    1408              :  *    return it to the caller of build_joinrel_restrictlist() to be stored in
    1409              :  *    join paths made from this pair of sub-relations.  (It will not need to
    1410              :  *    be considered further up the join tree.)
    1411              :  *
    1412              :  *    In many cases we will find the same RestrictInfos in both input
    1413              :  *    relations' joinlists, so be careful to eliminate duplicates.
    1414              :  *    Pointer equality should be a sufficient test for dups, since all
    1415              :  *    the various joinlist entries ultimately refer to RestrictInfos
    1416              :  *    pushed into them by distribute_restrictinfo_to_rels().
    1417              :  *
    1418              :  * 'joinrel' is a join relation node
    1419              :  * 'outer_rel' and 'inner_rel' are a pair of relations that can be joined
    1420              :  *      to form joinrel.
    1421              :  * 'sjinfo': join context info
    1422              :  *
    1423              :  * build_joinrel_restrictlist() returns a list of relevant restrictinfos,
    1424              :  * whereas build_joinrel_joinlist() stores its results in the joinrel's
    1425              :  * joininfo list.  One or the other must accept each given clause!
    1426              :  *
    1427              :  * NB: Formerly, we made deep(!) copies of each input RestrictInfo to pass
    1428              :  * up to the join relation.  I believe this is no longer necessary, because
    1429              :  * RestrictInfo nodes are no longer context-dependent.  Instead, just include
    1430              :  * the original nodes in the lists made for the join relation.
    1431              :  */
    1432              : static List *
    1433       191117 : build_joinrel_restrictlist(PlannerInfo *root,
    1434              :                            RelOptInfo *joinrel,
    1435              :                            RelOptInfo *outer_rel,
    1436              :                            RelOptInfo *inner_rel,
    1437              :                            SpecialJoinInfo *sjinfo)
    1438              : {
    1439              :     List       *result;
    1440              :     Relids      both_input_relids;
    1441              : 
    1442       191117 :     both_input_relids = bms_union(outer_rel->relids, inner_rel->relids);
    1443              : 
    1444              :     /*
    1445              :      * Collect all the clauses that syntactically belong at this level,
    1446              :      * eliminating any duplicates (important since we will see many of the
    1447              :      * same clauses arriving from both input relations).
    1448              :      */
    1449       191117 :     result = subbuild_joinrel_restrictlist(root, joinrel, outer_rel,
    1450              :                                            both_input_relids, NIL);
    1451       191117 :     result = subbuild_joinrel_restrictlist(root, joinrel, inner_rel,
    1452              :                                            both_input_relids, result);
    1453              : 
    1454              :     /*
    1455              :      * Add on any clauses derived from EquivalenceClasses.  These cannot be
    1456              :      * redundant with the clauses in the joininfo lists, so don't bother
    1457              :      * checking.
    1458              :      */
    1459       191117 :     result = list_concat(result,
    1460       191117 :                          generate_join_implied_equalities(root,
    1461              :                                                           joinrel->relids,
    1462              :                                                           outer_rel->relids,
    1463              :                                                           inner_rel,
    1464              :                                                           sjinfo));
    1465              : 
    1466       191117 :     return result;
    1467              : }
    1468              : 
    1469              : static void
    1470       121603 : build_joinrel_joinlist(RelOptInfo *joinrel,
    1471              :                        RelOptInfo *outer_rel,
    1472              :                        RelOptInfo *inner_rel)
    1473              : {
    1474              :     List       *result;
    1475              : 
    1476              :     /*
    1477              :      * Collect all the clauses that syntactically belong above this level,
    1478              :      * eliminating any duplicates (important since we will see many of the
    1479              :      * same clauses arriving from both input relations).
    1480              :      */
    1481       121603 :     result = subbuild_joinrel_joinlist(joinrel, outer_rel->joininfo, NIL);
    1482       121603 :     result = subbuild_joinrel_joinlist(joinrel, inner_rel->joininfo, result);
    1483              : 
    1484       121603 :     joinrel->joininfo = result;
    1485       121603 : }
    1486              : 
    1487              : static List *
    1488       382234 : subbuild_joinrel_restrictlist(PlannerInfo *root,
    1489              :                               RelOptInfo *joinrel,
    1490              :                               RelOptInfo *input_rel,
    1491              :                               Relids both_input_relids,
    1492              :                               List *new_restrictlist)
    1493              : {
    1494              :     ListCell   *l;
    1495              : 
    1496       731483 :     foreach(l, input_rel->joininfo)
    1497              :     {
    1498       349249 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
    1499              : 
    1500       349249 :         if (bms_is_subset(rinfo->required_relids, joinrel->relids))
    1501              :         {
    1502              :             /*
    1503              :              * This clause should become a restriction clause for the joinrel,
    1504              :              * since it refers to no outside rels.  However, if it's a clone
    1505              :              * clause then it might be too late to evaluate it, so we have to
    1506              :              * check.  (If it is too late, just ignore the clause, taking it
    1507              :              * on faith that another clone was or will be selected.)  Clone
    1508              :              * clauses should always be outer-join clauses, so we compare
    1509              :              * against both_input_relids.
    1510              :              */
    1511       206773 :             if (rinfo->has_clone || rinfo->is_clone)
    1512              :             {
    1513              :                 Assert(!RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids));
    1514        34689 :                 if (!bms_is_subset(rinfo->required_relids, both_input_relids))
    1515         5847 :                     continue;
    1516        28842 :                 if (bms_overlap(rinfo->incompatible_relids, both_input_relids))
    1517        11552 :                     continue;
    1518              :             }
    1519              :             else
    1520              :             {
    1521              :                 /*
    1522              :                  * For non-clone clauses, we just Assert it's OK.  These might
    1523              :                  * be either join or filter clauses; if it's a join clause
    1524              :                  * then it should not refer to the current join's output.
    1525              :                  * (There is little point in checking incompatible_relids,
    1526              :                  * because it'll be NULL.)
    1527              :                  */
    1528              :                 Assert(RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids) ||
    1529              :                        bms_is_subset(rinfo->required_relids,
    1530              :                                      both_input_relids));
    1531              :             }
    1532              : 
    1533              :             /*
    1534              :              * OK, so add it to the list, being careful to eliminate
    1535              :              * duplicates.  (Since RestrictInfo nodes in different joinlists
    1536              :              * will have been multiply-linked rather than copied, pointer
    1537              :              * equality should be a sufficient test.)
    1538              :              */
    1539       189374 :             new_restrictlist = list_append_unique_ptr(new_restrictlist, rinfo);
    1540              :         }
    1541              :         else
    1542              :         {
    1543              :             /*
    1544              :              * This clause is still a join clause at this level, so we ignore
    1545              :              * it in this routine.
    1546              :              */
    1547              :         }
    1548              :     }
    1549              : 
    1550       382234 :     return new_restrictlist;
    1551              : }
    1552              : 
    1553              : static List *
    1554       243206 : subbuild_joinrel_joinlist(RelOptInfo *joinrel,
    1555              :                           List *joininfo_list,
    1556              :                           List *new_joininfo)
    1557              : {
    1558              :     ListCell   *l;
    1559              : 
    1560              :     /* Expected to be called only for join between parent relations. */
    1561              :     Assert(joinrel->reloptkind == RELOPT_JOINREL);
    1562              : 
    1563       458786 :     foreach(l, joininfo_list)
    1564              :     {
    1565       215580 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
    1566              : 
    1567       215580 :         if (bms_is_subset(rinfo->required_relids, joinrel->relids))
    1568              :         {
    1569              :             /*
    1570              :              * This clause becomes a restriction clause for the joinrel, since
    1571              :              * it refers to no outside rels.  So we can ignore it in this
    1572              :              * routine.
    1573              :              */
    1574              :         }
    1575              :         else
    1576              :         {
    1577              :             /*
    1578              :              * This clause is still a join clause at this level, so add it to
    1579              :              * the new joininfo list, being careful to eliminate duplicates.
    1580              :              * (Since RestrictInfo nodes in different joinlists will have been
    1581              :              * multiply-linked rather than copied, pointer equality should be
    1582              :              * a sufficient test.)
    1583              :              */
    1584        85321 :             new_joininfo = list_append_unique_ptr(new_joininfo, rinfo);
    1585              :         }
    1586              :     }
    1587              : 
    1588       243206 :     return new_joininfo;
    1589              : }
    1590              : 
    1591              : 
    1592              : /*
    1593              :  * fetch_upper_rel
    1594              :  *      Build a RelOptInfo describing some post-scan/join query processing,
    1595              :  *      or return a pre-existing one if somebody already built it.
    1596              :  *
    1597              :  * An "upper" relation is identified by an UpperRelationKind and a Relids set.
    1598              :  * The meaning of the Relids set is not specified here, and very likely will
    1599              :  * vary for different relation kinds.
    1600              :  *
    1601              :  * Most of the fields in an upper-level RelOptInfo are not used and are not
    1602              :  * set here (though makeNode should ensure they're zeroes).  We basically only
    1603              :  * care about fields that are of interest to add_path() and set_cheapest().
    1604              :  */
    1605              : RelOptInfo *
    1606       955552 : fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
    1607              : {
    1608              :     RelOptInfo *upperrel;
    1609              :     ListCell   *lc;
    1610              : 
    1611              :     /*
    1612              :      * For the moment, our indexing data structure is just a List for each
    1613              :      * relation kind.  If we ever get so many of one kind that this stops
    1614              :      * working well, we can improve it.  No code outside this function should
    1615              :      * assume anything about how to find a particular upperrel.
    1616              :      */
    1617              : 
    1618              :     /* If we already made this upperrel for the query, return it */
    1619       961174 :     foreach(lc, root->upper_rels[kind])
    1620              :     {
    1621       608930 :         upperrel = (RelOptInfo *) lfirst(lc);
    1622              : 
    1623       608930 :         if (bms_equal(upperrel->relids, relids))
    1624       603308 :             return upperrel;
    1625              :     }
    1626              : 
    1627       352244 :     upperrel = makeNode(RelOptInfo);
    1628       352244 :     upperrel->reloptkind = RELOPT_UPPER_REL;
    1629       352244 :     upperrel->relids = bms_copy(relids);
    1630       352244 :     upperrel->pgs_mask = root->glob->default_pgs_mask;
    1631              : 
    1632              :     /* cheap startup cost is interesting iff not all tuples to be retrieved */
    1633       352244 :     upperrel->consider_startup = (root->tuple_fraction > 0);
    1634       352244 :     upperrel->consider_param_startup = false;
    1635       352244 :     upperrel->consider_parallel = false; /* might get changed later */
    1636       352244 :     upperrel->reltarget = create_empty_pathtarget();
    1637       352244 :     upperrel->pathlist = NIL;
    1638       352244 :     upperrel->cheapest_startup_path = NULL;
    1639       352244 :     upperrel->cheapest_total_path = NULL;
    1640       352244 :     upperrel->cheapest_parameterized_paths = NIL;
    1641              : 
    1642       352244 :     root->upper_rels[kind] = lappend(root->upper_rels[kind], upperrel);
    1643              : 
    1644       352244 :     return upperrel;
    1645              : }
    1646              : 
    1647              : 
    1648              : /*
    1649              :  * find_childrel_parents
    1650              :  *      Compute the set of parent relids of an appendrel child rel.
    1651              :  *
    1652              :  * Since appendrels can be nested, a child could have multiple levels of
    1653              :  * appendrel ancestors.  This function computes a Relids set of all the
    1654              :  * parent relation IDs.
    1655              :  */
    1656              : Relids
    1657         6737 : find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
    1658              : {
    1659         6737 :     Relids      result = NULL;
    1660              : 
    1661              :     Assert(rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
    1662              :     Assert(rel->relid > 0 && rel->relid < root->simple_rel_array_size);
    1663              : 
    1664              :     do
    1665              :     {
    1666         8115 :         AppendRelInfo *appinfo = root->append_rel_array[rel->relid];
    1667         8115 :         Index       prelid = appinfo->parent_relid;
    1668              : 
    1669         8115 :         result = bms_add_member(result, prelid);
    1670              : 
    1671              :         /* traverse up to the parent rel, loop if it's also a child rel */
    1672         8115 :         rel = find_base_rel(root, prelid);
    1673         8115 :     } while (rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
    1674              : 
    1675              :     Assert(rel->reloptkind == RELOPT_BASEREL);
    1676              : 
    1677         6737 :     return result;
    1678              : }
    1679              : 
    1680              : 
    1681              : /*
    1682              :  * get_baserel_parampathinfo
    1683              :  *      Get the ParamPathInfo for a parameterized path for a base relation,
    1684              :  *      constructing one if we don't have one already.
    1685              :  *
    1686              :  * This centralizes estimating the rowcounts for parameterized paths.
    1687              :  * We need to cache those to be sure we use the same rowcount for all paths
    1688              :  * of the same parameterization for a given rel.  This is also a convenient
    1689              :  * place to determine which movable join clauses the parameterized path will
    1690              :  * be responsible for evaluating.
    1691              :  */
    1692              : ParamPathInfo *
    1693      1008577 : get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel,
    1694              :                           Relids required_outer)
    1695              : {
    1696              :     ParamPathInfo *ppi;
    1697              :     Relids      joinrelids;
    1698              :     List       *pclauses;
    1699              :     List       *eqclauses;
    1700              :     Bitmapset  *pserials;
    1701              :     double      rows;
    1702              :     ListCell   *lc;
    1703              : 
    1704              :     /* If rel has LATERAL refs, every path for it should account for them */
    1705              :     Assert(bms_is_subset(baserel->lateral_relids, required_outer));
    1706              : 
    1707              :     /* Unparameterized paths have no ParamPathInfo */
    1708      1008577 :     if (bms_is_empty(required_outer))
    1709       821943 :         return NULL;
    1710              : 
    1711              :     Assert(!bms_overlap(baserel->relids, required_outer));
    1712              : 
    1713              :     /* If we already have a PPI for this parameterization, just return it */
    1714       186634 :     if ((ppi = find_param_path_info(baserel, required_outer)))
    1715        98426 :         return ppi;
    1716              : 
    1717              :     /*
    1718              :      * Identify all joinclauses that are movable to this base rel given this
    1719              :      * parameterization.
    1720              :      */
    1721        88208 :     joinrelids = bms_union(baserel->relids, required_outer);
    1722        88208 :     pclauses = NIL;
    1723       141612 :     foreach(lc, baserel->joininfo)
    1724              :     {
    1725        53404 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    1726              : 
    1727        53404 :         if (join_clause_is_movable_into(rinfo,
    1728              :                                         baserel->relids,
    1729              :                                         joinrelids))
    1730        22544 :             pclauses = lappend(pclauses, rinfo);
    1731              :     }
    1732              : 
    1733              :     /*
    1734              :      * Add in joinclauses generated by EquivalenceClasses, too.  (These
    1735              :      * necessarily satisfy join_clause_is_movable_into; but in assert-enabled
    1736              :      * builds, let's verify that.)
    1737              :      */
    1738        88208 :     eqclauses = generate_join_implied_equalities(root,
    1739              :                                                  joinrelids,
    1740              :                                                  required_outer,
    1741              :                                                  baserel,
    1742              :                                                  NULL);
    1743              : #ifdef USE_ASSERT_CHECKING
    1744              :     foreach(lc, eqclauses)
    1745              :     {
    1746              :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    1747              : 
    1748              :         Assert(join_clause_is_movable_into(rinfo,
    1749              :                                            baserel->relids,
    1750              :                                            joinrelids));
    1751              :     }
    1752              : #endif
    1753        88208 :     pclauses = list_concat(pclauses, eqclauses);
    1754              : 
    1755              :     /* Compute set of serial numbers of the enforced clauses */
    1756        88208 :     pserials = NULL;
    1757       184784 :     foreach(lc, pclauses)
    1758              :     {
    1759        96576 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    1760              : 
    1761        96576 :         pserials = bms_add_member(pserials, rinfo->rinfo_serial);
    1762              :     }
    1763              : 
    1764              :     /* Estimate the number of rows returned by the parameterized scan */
    1765        88208 :     rows = get_parameterized_baserel_size(root, baserel, pclauses);
    1766              : 
    1767              :     /* And now we can build the ParamPathInfo */
    1768        88208 :     ppi = makeNode(ParamPathInfo);
    1769        88208 :     ppi->ppi_req_outer = required_outer;
    1770        88208 :     ppi->ppi_rows = rows;
    1771        88208 :     ppi->ppi_clauses = pclauses;
    1772        88208 :     ppi->ppi_serials = pserials;
    1773        88208 :     baserel->ppilist = lappend(baserel->ppilist, ppi);
    1774              : 
    1775        88208 :     return ppi;
    1776              : }
    1777              : 
    1778              : /*
    1779              :  * get_joinrel_parampathinfo
    1780              :  *      Get the ParamPathInfo for a parameterized path for a join relation,
    1781              :  *      constructing one if we don't have one already.
    1782              :  *
    1783              :  * This centralizes estimating the rowcounts for parameterized paths.
    1784              :  * We need to cache those to be sure we use the same rowcount for all paths
    1785              :  * of the same parameterization for a given rel.  This is also a convenient
    1786              :  * place to determine which movable join clauses the parameterized path will
    1787              :  * be responsible for evaluating.
    1788              :  *
    1789              :  * outer_path and inner_path are a pair of input paths that can be used to
    1790              :  * construct the join, and restrict_clauses is the list of regular join
    1791              :  * clauses (including clauses derived from EquivalenceClasses) that must be
    1792              :  * applied at the join node when using these inputs.
    1793              :  *
    1794              :  * Unlike the situation for base rels, the set of movable join clauses to be
    1795              :  * enforced at a join varies with the selected pair of input paths, so we
    1796              :  * must calculate that and pass it back, even if we already have a matching
    1797              :  * ParamPathInfo.  We handle this by adding any clauses moved down to this
    1798              :  * join to *restrict_clauses, which is an in/out parameter.  (The addition
    1799              :  * is done in such a way as to not modify the passed-in List structure.)
    1800              :  *
    1801              :  * Note: when considering a nestloop join, the caller must have removed from
    1802              :  * restrict_clauses any movable clauses that are themselves scheduled to be
    1803              :  * pushed into the right-hand path.  We do not do that here since it's
    1804              :  * unnecessary for other join types.
    1805              :  */
    1806              : ParamPathInfo *
    1807      1322437 : get_joinrel_parampathinfo(PlannerInfo *root, RelOptInfo *joinrel,
    1808              :                           Path *outer_path,
    1809              :                           Path *inner_path,
    1810              :                           SpecialJoinInfo *sjinfo,
    1811              :                           Relids required_outer,
    1812              :                           List **restrict_clauses)
    1813              : {
    1814              :     ParamPathInfo *ppi;
    1815              :     Relids      join_and_req;
    1816              :     Relids      outer_and_req;
    1817              :     Relids      inner_and_req;
    1818              :     List       *pclauses;
    1819              :     List       *eclauses;
    1820              :     List       *dropped_ecs;
    1821              :     double      rows;
    1822              :     ListCell   *lc;
    1823              : 
    1824              :     /* If rel has LATERAL refs, every path for it should account for them */
    1825              :     Assert(bms_is_subset(joinrel->lateral_relids, required_outer));
    1826              : 
    1827              :     /* Unparameterized paths have no ParamPathInfo or extra join clauses */
    1828      1322437 :     if (bms_is_empty(required_outer))
    1829      1303117 :         return NULL;
    1830              : 
    1831              :     Assert(!bms_overlap(joinrel->relids, required_outer));
    1832              : 
    1833              :     /*
    1834              :      * Identify all joinclauses that are movable to this join rel given this
    1835              :      * parameterization.  These are the clauses that are movable into this
    1836              :      * join, but not movable into either input path.  Treat an unparameterized
    1837              :      * input path as not accepting parameterized clauses (because it won't,
    1838              :      * per the shortcut exit above), even though the joinclause movement rules
    1839              :      * might allow the same clauses to be moved into a parameterized path for
    1840              :      * that rel.
    1841              :      */
    1842        19320 :     join_and_req = bms_union(joinrel->relids, required_outer);
    1843        19320 :     if (outer_path->param_info)
    1844        16766 :         outer_and_req = bms_union(outer_path->parent->relids,
    1845        16766 :                                   PATH_REQ_OUTER(outer_path));
    1846              :     else
    1847         2554 :         outer_and_req = NULL;   /* outer path does not accept parameters */
    1848        19320 :     if (inner_path->param_info)
    1849         9955 :         inner_and_req = bms_union(inner_path->parent->relids,
    1850         9955 :                                   PATH_REQ_OUTER(inner_path));
    1851              :     else
    1852         9365 :         inner_and_req = NULL;   /* inner path does not accept parameters */
    1853              : 
    1854        19320 :     pclauses = NIL;
    1855        45241 :     foreach(lc, joinrel->joininfo)
    1856              :     {
    1857        25921 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    1858              : 
    1859        25921 :         if (join_clause_is_movable_into(rinfo,
    1860              :                                         joinrel->relids,
    1861        12694 :                                         join_and_req) &&
    1862        12694 :             !join_clause_is_movable_into(rinfo,
    1863        12694 :                                          outer_path->parent->relids,
    1864          358 :                                          outer_and_req) &&
    1865          358 :             !join_clause_is_movable_into(rinfo,
    1866          358 :                                          inner_path->parent->relids,
    1867              :                                          inner_and_req))
    1868           48 :             pclauses = lappend(pclauses, rinfo);
    1869              :     }
    1870              : 
    1871              :     /* Consider joinclauses generated by EquivalenceClasses, too */
    1872        19320 :     eclauses = generate_join_implied_equalities(root,
    1873              :                                                 join_and_req,
    1874              :                                                 required_outer,
    1875              :                                                 joinrel,
    1876              :                                                 NULL);
    1877              :     /* We only want ones that aren't movable to lower levels */
    1878        19320 :     dropped_ecs = NIL;
    1879        23486 :     foreach(lc, eclauses)
    1880              :     {
    1881         4166 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    1882              : 
    1883              :         Assert(join_clause_is_movable_into(rinfo,
    1884              :                                            joinrel->relids,
    1885              :                                            join_and_req));
    1886         4166 :         if (join_clause_is_movable_into(rinfo,
    1887         4166 :                                         outer_path->parent->relids,
    1888              :                                         outer_and_req))
    1889         1645 :             continue;           /* drop if movable into LHS */
    1890         2521 :         if (join_clause_is_movable_into(rinfo,
    1891         2521 :                                         inner_path->parent->relids,
    1892              :                                         inner_and_req))
    1893              :         {
    1894              :             /* drop if movable into RHS, but remember EC for use below */
    1895              :             Assert(rinfo->left_ec == rinfo->right_ec);
    1896         1822 :             dropped_ecs = lappend(dropped_ecs, rinfo->left_ec);
    1897         1822 :             continue;
    1898              :         }
    1899          699 :         pclauses = lappend(pclauses, rinfo);
    1900              :     }
    1901              : 
    1902              :     /*
    1903              :      * EquivalenceClasses are harder to deal with than we could wish, because
    1904              :      * of the fact that a given EC can generate different clauses depending on
    1905              :      * context.  Suppose we have an EC {X.X, Y.Y, Z.Z} where X and Y are the
    1906              :      * LHS and RHS of the current join and Z is in required_outer, and further
    1907              :      * suppose that the inner_path is parameterized by both X and Z.  The code
    1908              :      * above will have produced either Z.Z = X.X or Z.Z = Y.Y from that EC,
    1909              :      * and in the latter case will have discarded it as being movable into the
    1910              :      * RHS.  However, the EC machinery might have produced either Y.Y = X.X or
    1911              :      * Y.Y = Z.Z as the EC enforcement clause within the inner_path; it will
    1912              :      * not have produced both, and we can't readily tell from here which one
    1913              :      * it did pick.  If we add no clause to this join, we'll end up with
    1914              :      * insufficient enforcement of the EC; either Z.Z or X.X will fail to be
    1915              :      * constrained to be equal to the other members of the EC.  (When we come
    1916              :      * to join Z to this X/Y path, we will certainly drop whichever EC clause
    1917              :      * is generated at that join, so this omission won't get fixed later.)
    1918              :      *
    1919              :      * To handle this, for each EC we discarded such a clause from, try to
    1920              :      * generate a clause connecting the required_outer rels to the join's LHS
    1921              :      * ("Z.Z = X.X" in the terms of the above example).  If successful, and if
    1922              :      * the clause can't be moved to the LHS, add it to the current join's
    1923              :      * restriction clauses.  (If an EC cannot generate such a clause then it
    1924              :      * has nothing that needs to be enforced here, while if the clause can be
    1925              :      * moved into the LHS then it should have been enforced within that path.)
    1926              :      *
    1927              :      * Note that we don't need similar processing for ECs whose clause was
    1928              :      * considered to be movable into the LHS, because the LHS can't refer to
    1929              :      * the RHS so there is no comparable ambiguity about what it might
    1930              :      * actually be enforcing internally.
    1931              :      */
    1932        19320 :     if (dropped_ecs)
    1933              :     {
    1934              :         Relids      real_outer_and_req;
    1935              : 
    1936         1789 :         real_outer_and_req = bms_union(outer_path->parent->relids,
    1937              :                                        required_outer);
    1938              :         eclauses =
    1939         1789 :             generate_join_implied_equalities_for_ecs(root,
    1940              :                                                      dropped_ecs,
    1941              :                                                      real_outer_and_req,
    1942              :                                                      required_outer,
    1943              :                                                      outer_path->parent);
    1944         1939 :         foreach(lc, eclauses)
    1945              :         {
    1946          150 :             RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    1947              : 
    1948              :             Assert(join_clause_is_movable_into(rinfo,
    1949              :                                                outer_path->parent->relids,
    1950              :                                                real_outer_and_req));
    1951          150 :             if (!join_clause_is_movable_into(rinfo,
    1952          150 :                                              outer_path->parent->relids,
    1953              :                                              outer_and_req))
    1954          135 :                 pclauses = lappend(pclauses, rinfo);
    1955              :         }
    1956              :     }
    1957              : 
    1958              :     /*
    1959              :      * Now, attach the identified moved-down clauses to the caller's
    1960              :      * restrict_clauses list.  By using list_concat in this order, we leave
    1961              :      * the original list structure of restrict_clauses undamaged.
    1962              :      */
    1963        19320 :     *restrict_clauses = list_concat(pclauses, *restrict_clauses);
    1964              : 
    1965              :     /* If we already have a PPI for this parameterization, just return it */
    1966        19320 :     if ((ppi = find_param_path_info(joinrel, required_outer)))
    1967        14199 :         return ppi;
    1968              : 
    1969              :     /* Estimate the number of rows returned by the parameterized join */
    1970         5121 :     rows = get_parameterized_joinrel_size(root, joinrel,
    1971              :                                           outer_path,
    1972              :                                           inner_path,
    1973              :                                           sjinfo,
    1974              :                                           *restrict_clauses);
    1975              : 
    1976              :     /*
    1977              :      * And now we can build the ParamPathInfo.  No point in saving the
    1978              :      * input-pair-dependent clause list, though.
    1979              :      *
    1980              :      * Note: in GEQO mode, we'll be called in a temporary memory context, but
    1981              :      * the joinrel structure is there too, so no problem.
    1982              :      */
    1983         5121 :     ppi = makeNode(ParamPathInfo);
    1984         5121 :     ppi->ppi_req_outer = required_outer;
    1985         5121 :     ppi->ppi_rows = rows;
    1986         5121 :     ppi->ppi_clauses = NIL;
    1987         5121 :     ppi->ppi_serials = NULL;
    1988         5121 :     joinrel->ppilist = lappend(joinrel->ppilist, ppi);
    1989              : 
    1990         5121 :     return ppi;
    1991              : }
    1992              : 
    1993              : /*
    1994              :  * get_appendrel_parampathinfo
    1995              :  *      Get the ParamPathInfo for a parameterized path for an append relation.
    1996              :  *
    1997              :  * For an append relation, the rowcount estimate will just be the sum of
    1998              :  * the estimates for its children.  However, we still need a ParamPathInfo
    1999              :  * to flag the fact that the path requires parameters.  So this just creates
    2000              :  * a suitable struct with zero ppi_rows (and no ppi_clauses either, since
    2001              :  * the Append node isn't responsible for checking quals).
    2002              :  */
    2003              : ParamPathInfo *
    2004        26319 : get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer)
    2005              : {
    2006              :     ParamPathInfo *ppi;
    2007              : 
    2008              :     /* If rel has LATERAL refs, every path for it should account for them */
    2009              :     Assert(bms_is_subset(appendrel->lateral_relids, required_outer));
    2010              : 
    2011              :     /* Unparameterized paths have no ParamPathInfo */
    2012        26319 :     if (bms_is_empty(required_outer))
    2013        26035 :         return NULL;
    2014              : 
    2015              :     Assert(!bms_overlap(appendrel->relids, required_outer));
    2016              : 
    2017              :     /* If we already have a PPI for this parameterization, just return it */
    2018          284 :     if ((ppi = find_param_path_info(appendrel, required_outer)))
    2019           66 :         return ppi;
    2020              : 
    2021              :     /* Else build the ParamPathInfo */
    2022          218 :     ppi = makeNode(ParamPathInfo);
    2023          218 :     ppi->ppi_req_outer = required_outer;
    2024          218 :     ppi->ppi_rows = 0;
    2025          218 :     ppi->ppi_clauses = NIL;
    2026          218 :     ppi->ppi_serials = NULL;
    2027          218 :     appendrel->ppilist = lappend(appendrel->ppilist, ppi);
    2028              : 
    2029          218 :     return ppi;
    2030              : }
    2031              : 
    2032              : /*
    2033              :  * Returns a ParamPathInfo for the parameterization given by required_outer, if
    2034              :  * already available in the given rel. Returns NULL otherwise.
    2035              :  */
    2036              : ParamPathInfo *
    2037       206739 : find_param_path_info(RelOptInfo *rel, Relids required_outer)
    2038              : {
    2039              :     ListCell   *lc;
    2040              : 
    2041       242866 :     foreach(lc, rel->ppilist)
    2042              :     {
    2043       148890 :         ParamPathInfo *ppi = (ParamPathInfo *) lfirst(lc);
    2044              : 
    2045       148890 :         if (bms_equal(ppi->ppi_req_outer, required_outer))
    2046       112763 :             return ppi;
    2047              :     }
    2048              : 
    2049        93976 :     return NULL;
    2050              : }
    2051              : 
    2052              : /*
    2053              :  * get_param_path_clause_serials
    2054              :  *      Given a parameterized Path, return the set of pushed-down clauses
    2055              :  *      (identified by rinfo_serial numbers) enforced within the Path.
    2056              :  */
    2057              : Bitmapset *
    2058       244236 : get_param_path_clause_serials(Path *path)
    2059              : {
    2060       244236 :     if (path->param_info == NULL)
    2061         1674 :         return NULL;            /* not parameterized */
    2062              : 
    2063              :     /*
    2064              :      * We don't currently support parameterized MergeAppend paths, as
    2065              :      * explained in the comments for generate_orderedappend_paths.
    2066              :      */
    2067              :     Assert(!IsA(path, MergeAppendPath));
    2068              : 
    2069       242562 :     if (IsA(path, NestPath) ||
    2070       237945 :         IsA(path, MergePath) ||
    2071       237942 :         IsA(path, HashPath))
    2072              :     {
    2073              :         /*
    2074              :          * For a join path, combine clauses enforced within either input path
    2075              :          * with those enforced as joinrestrictinfo in this path.  Note that
    2076              :          * joinrestrictinfo may include some non-pushed-down clauses, but for
    2077              :          * current purposes it's okay if we include those in the result. (To
    2078              :          * be more careful, we could check for clause_relids overlapping the
    2079              :          * path parameterization, but it's not worth the cycles for now.)
    2080              :          */
    2081         5941 :         JoinPath   *jpath = (JoinPath *) path;
    2082              :         Bitmapset  *pserials;
    2083              :         ListCell   *lc;
    2084              : 
    2085         5941 :         pserials = NULL;
    2086         5941 :         pserials = bms_add_members(pserials,
    2087         5941 :                                    get_param_path_clause_serials(jpath->outerjoinpath));
    2088         5941 :         pserials = bms_add_members(pserials,
    2089         5941 :                                    get_param_path_clause_serials(jpath->innerjoinpath));
    2090         7822 :         foreach(lc, jpath->joinrestrictinfo)
    2091              :         {
    2092         1881 :             RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    2093              : 
    2094         1881 :             pserials = bms_add_member(pserials, rinfo->rinfo_serial);
    2095              :         }
    2096         5941 :         return pserials;
    2097              :     }
    2098       236621 :     else if (IsA(path, AppendPath))
    2099              :     {
    2100              :         /*
    2101              :          * For an appendrel, take the intersection of the sets of clauses
    2102              :          * enforced in each input path.
    2103              :          */
    2104         1198 :         AppendPath *apath = (AppendPath *) path;
    2105              :         Bitmapset  *pserials;
    2106              :         ListCell   *lc;
    2107              : 
    2108         1198 :         pserials = NULL;
    2109         4948 :         foreach(lc, apath->subpaths)
    2110              :         {
    2111         3750 :             Path       *subpath = (Path *) lfirst(lc);
    2112              :             Bitmapset  *subserials;
    2113              : 
    2114         3750 :             subserials = get_param_path_clause_serials(subpath);
    2115         3750 :             if (lc == list_head(apath->subpaths))
    2116         1186 :                 pserials = bms_copy(subserials);
    2117              :             else
    2118         2564 :                 pserials = bms_int_members(pserials, subserials);
    2119              :         }
    2120         1198 :         return pserials;
    2121              :     }
    2122              :     else
    2123              :     {
    2124              :         /*
    2125              :          * Otherwise, it's a baserel path and we can use the
    2126              :          * previously-computed set of serial numbers.
    2127              :          */
    2128       235423 :         return path->param_info->ppi_serials;
    2129              :     }
    2130              : }
    2131              : 
    2132              : /*
    2133              :  * build_joinrel_partition_info
    2134              :  *      Checks if the two relations being joined can use partitionwise join
    2135              :  *      and if yes, initialize partitioning information of the resulting
    2136              :  *      partitioned join relation.
    2137              :  */
    2138              : static void
    2139       130788 : build_joinrel_partition_info(PlannerInfo *root,
    2140              :                              RelOptInfo *joinrel, RelOptInfo *outer_rel,
    2141              :                              RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo,
    2142              :                              List *restrictlist)
    2143              : {
    2144              :     PartitionScheme part_scheme;
    2145              : 
    2146              :     /* Nothing to do if partitionwise join technique is disabled. */
    2147       130788 :     if ((joinrel->pgs_mask & PGS_CONSIDER_PARTITIONWISE) == 0)
    2148              :     {
    2149              :         Assert(!IS_PARTITIONED_REL(joinrel));
    2150       119223 :         return;
    2151              :     }
    2152              : 
    2153              :     /*
    2154              :      * We can only consider this join as an input to further partitionwise
    2155              :      * joins if (a) the input relations are partitioned and have
    2156              :      * consider_partitionwise_join=true, (b) the partition schemes match, and
    2157              :      * (c) we can identify an equi-join between the partition keys.  Note that
    2158              :      * if it were possible for have_partkey_equi_join to return different
    2159              :      * answers for the same joinrel depending on which join ordering we try
    2160              :      * first, this logic would break.  That shouldn't happen, though, because
    2161              :      * of the way the query planner deduces implied equalities and reorders
    2162              :      * the joins.  Please see optimizer/README for details.
    2163              :      */
    2164        11565 :     if (outer_rel->part_scheme == NULL || inner_rel->part_scheme == NULL ||
    2165         3829 :         !outer_rel->consider_partitionwise_join ||
    2166         3807 :         !inner_rel->consider_partitionwise_join ||
    2167         3789 :         outer_rel->part_scheme != inner_rel->part_scheme ||
    2168         3777 :         !have_partkey_equi_join(root, joinrel, outer_rel, inner_rel,
    2169              :                                 sjinfo->jointype, restrictlist))
    2170              :     {
    2171              :         Assert(!IS_PARTITIONED_REL(joinrel));
    2172         7872 :         return;
    2173              :     }
    2174              : 
    2175         3693 :     part_scheme = outer_rel->part_scheme;
    2176              : 
    2177              :     /*
    2178              :      * This function will be called only once for each joinrel, hence it
    2179              :      * should not have partitioning fields filled yet.
    2180              :      */
    2181              :     Assert(!joinrel->part_scheme && !joinrel->partexprs &&
    2182              :            !joinrel->nullable_partexprs && !joinrel->part_rels &&
    2183              :            !joinrel->boundinfo);
    2184              : 
    2185              :     /*
    2186              :      * If the join relation is partitioned, it uses the same partitioning
    2187              :      * scheme as the joining relations.
    2188              :      *
    2189              :      * Note: we calculate the partition bounds, number of partitions, and
    2190              :      * child-join relations of the join relation in try_partitionwise_join().
    2191              :      */
    2192         3693 :     joinrel->part_scheme = part_scheme;
    2193         3693 :     set_joinrel_partition_key_exprs(joinrel, outer_rel, inner_rel,
    2194              :                                     sjinfo->jointype);
    2195              : 
    2196              :     /*
    2197              :      * Set the consider_partitionwise_join flag.
    2198              :      */
    2199              :     Assert(outer_rel->consider_partitionwise_join);
    2200              :     Assert(inner_rel->consider_partitionwise_join);
    2201         3693 :     joinrel->consider_partitionwise_join = true;
    2202              : }
    2203              : 
    2204              : /*
    2205              :  * have_partkey_equi_join
    2206              :  *
    2207              :  * Returns true if there exist equi-join conditions involving pairs
    2208              :  * of matching partition keys of the relations being joined for all
    2209              :  * partition keys.
    2210              :  */
    2211              : static bool
    2212         3777 : have_partkey_equi_join(PlannerInfo *root, RelOptInfo *joinrel,
    2213              :                        RelOptInfo *rel1, RelOptInfo *rel2,
    2214              :                        JoinType jointype, List *restrictlist)
    2215              : {
    2216         3777 :     PartitionScheme part_scheme = rel1->part_scheme;
    2217              :     bool        pk_known_equal[PARTITION_MAX_KEYS];
    2218              :     int         num_equal_pks;
    2219              :     ListCell   *lc;
    2220              : 
    2221              :     /*
    2222              :      * This function must only be called when the joined relations have same
    2223              :      * partitioning scheme.
    2224              :      */
    2225              :     Assert(rel1->part_scheme == rel2->part_scheme);
    2226              :     Assert(part_scheme);
    2227              : 
    2228              :     /* We use a bool array to track which partkey columns are known equal */
    2229         3777 :     memset(pk_known_equal, 0, sizeof(pk_known_equal));
    2230              :     /* ... as well as a count of how many are known equal */
    2231         3777 :     num_equal_pks = 0;
    2232              : 
    2233              :     /* First, look through the join's restriction clauses */
    2234         4398 :     foreach(lc, restrictlist)
    2235              :     {
    2236         4293 :         RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
    2237              :         OpExpr     *opexpr;
    2238              :         Expr       *expr1;
    2239              :         Expr       *expr2;
    2240              :         bool        strict_op;
    2241              :         int         ipk1;
    2242              :         int         ipk2;
    2243              : 
    2244              :         /* If processing an outer join, only use its own join clauses. */
    2245         4293 :         if (IS_OUTER_JOIN(jointype) &&
    2246          841 :             RINFO_IS_PUSHED_DOWN(rinfo, joinrel->relids))
    2247          123 :             continue;
    2248              : 
    2249              :         /* Skip clauses which can not be used for a join. */
    2250         4170 :         if (!rinfo->can_join)
    2251            9 :             continue;
    2252              : 
    2253              :         /* Skip clauses which are not equality conditions. */
    2254         4161 :         if (!rinfo->mergeopfamilies && !OidIsValid(rinfo->hashjoinoperator))
    2255            3 :             continue;
    2256              : 
    2257              :         /* Should be OK to assume it's an OpExpr. */
    2258         4158 :         opexpr = castNode(OpExpr, rinfo->clause);
    2259              : 
    2260              :         /* Match the operands to the relation. */
    2261         7041 :         if (bms_is_subset(rinfo->left_relids, rel1->relids) &&
    2262         2883 :             bms_is_subset(rinfo->right_relids, rel2->relids))
    2263              :         {
    2264         2883 :             expr1 = linitial(opexpr->args);
    2265         2883 :             expr2 = lsecond(opexpr->args);
    2266              :         }
    2267         2550 :         else if (bms_is_subset(rinfo->left_relids, rel2->relids) &&
    2268         1275 :                  bms_is_subset(rinfo->right_relids, rel1->relids))
    2269              :         {
    2270         1275 :             expr1 = lsecond(opexpr->args);
    2271         1275 :             expr2 = linitial(opexpr->args);
    2272              :         }
    2273              :         else
    2274            0 :             continue;
    2275              : 
    2276              :         /*
    2277              :          * Now we need to know whether the join operator is strict; see
    2278              :          * comments in pathnodes.h.
    2279              :          */
    2280         4158 :         strict_op = op_strict(opexpr->opno);
    2281              : 
    2282              :         /*
    2283              :          * Vars appearing in the relation's partition keys will not have any
    2284              :          * varnullingrels, but those in expr1 and expr2 will if we're above
    2285              :          * outer joins that could null the respective rels.  It's okay to
    2286              :          * match anyway, if the join operator is strict.
    2287              :          */
    2288         4158 :         if (strict_op)
    2289              :         {
    2290         4158 :             if (bms_overlap(rel1->relids, root->outer_join_rels))
    2291           96 :                 expr1 = (Expr *) remove_nulling_relids((Node *) expr1,
    2292           96 :                                                        root->outer_join_rels,
    2293              :                                                        NULL);
    2294         4158 :             if (bms_overlap(rel2->relids, root->outer_join_rels))
    2295            0 :                 expr2 = (Expr *) remove_nulling_relids((Node *) expr2,
    2296            0 :                                                        root->outer_join_rels,
    2297              :                                                        NULL);
    2298              :         }
    2299              : 
    2300              :         /*
    2301              :          * Only clauses referencing the partition keys are useful for
    2302              :          * partitionwise join.
    2303              :          */
    2304         4158 :         ipk1 = match_expr_to_partition_keys(expr1, rel1, strict_op);
    2305         4158 :         if (ipk1 < 0)
    2306          450 :             continue;
    2307         3708 :         ipk2 = match_expr_to_partition_keys(expr2, rel2, strict_op);
    2308         3708 :         if (ipk2 < 0)
    2309           24 :             continue;
    2310              : 
    2311              :         /*
    2312              :          * If the clause refers to keys at different ordinal positions, it can
    2313              :          * not be used for partitionwise join.
    2314              :          */
    2315         3684 :         if (ipk1 != ipk2)
    2316            3 :             continue;
    2317              : 
    2318              :         /* Ignore clause if we already proved these keys equal. */
    2319         3681 :         if (pk_known_equal[ipk1])
    2320            0 :             continue;
    2321              : 
    2322              :         /* Reject if the partition key collation differs from the clause's. */
    2323         3681 :         if (rel1->part_scheme->partcollation[ipk1] != opexpr->inputcollid)
    2324         3672 :             return false;
    2325              : 
    2326              :         /*
    2327              :          * The clause allows partitionwise join only if it uses the same
    2328              :          * operator family as that specified by the partition key.
    2329              :          */
    2330         3675 :         if (part_scheme->strategy == PARTITION_STRATEGY_HASH)
    2331              :         {
    2332           36 :             if (!OidIsValid(rinfo->hashjoinoperator) ||
    2333           36 :                 !op_in_opfamily(rinfo->hashjoinoperator,
    2334           36 :                                 part_scheme->partopfamily[ipk1]))
    2335            0 :                 continue;
    2336              :         }
    2337         3639 :         else if (!list_member_oid(rinfo->mergeopfamilies,
    2338         3639 :                                   part_scheme->partopfamily[ipk1]))
    2339            0 :             continue;
    2340              : 
    2341              :         /* Mark the partition key as having an equi-join clause. */
    2342         3675 :         pk_known_equal[ipk1] = true;
    2343              : 
    2344              :         /* We can stop examining clauses once we prove all keys equal. */
    2345         3675 :         if (++num_equal_pks == part_scheme->partnatts)
    2346         3666 :             return true;
    2347              :     }
    2348              : 
    2349              :     /*
    2350              :      * Also check to see if any keys are known equal by equivclass.c.  In most
    2351              :      * cases there would have been a join restriction clause generated from
    2352              :      * any EC that had such knowledge, but there might be no such clause, or
    2353              :      * it might happen to constrain other members of the ECs than the ones we
    2354              :      * are looking for.
    2355              :      */
    2356          108 :     for (int ipk = 0; ipk < part_scheme->partnatts; ipk++)
    2357              :     {
    2358              :         Oid         btree_opfamily;
    2359              : 
    2360              :         /* Ignore if we already proved these keys equal. */
    2361          108 :         if (pk_known_equal[ipk])
    2362            3 :             continue;
    2363              : 
    2364              :         /*
    2365              :          * We need a btree opfamily to ask equivclass.c about.  If the
    2366              :          * partopfamily is a hash opfamily, look up its equality operator, and
    2367              :          * select some btree opfamily that that operator is part of.  (Any
    2368              :          * such opfamily should be good enough, since equivclass.c will track
    2369              :          * multiple opfamilies as appropriate.)
    2370              :          */
    2371          105 :         if (part_scheme->strategy == PARTITION_STRATEGY_HASH)
    2372              :         {
    2373              :             Oid         eq_op;
    2374              :             List       *eq_opfamilies;
    2375              : 
    2376            0 :             eq_op = get_opfamily_member(part_scheme->partopfamily[ipk],
    2377            0 :                                         part_scheme->partopcintype[ipk],
    2378            0 :                                         part_scheme->partopcintype[ipk],
    2379              :                                         HTEqualStrategyNumber);
    2380            0 :             if (!OidIsValid(eq_op))
    2381            0 :                 break;          /* we're not going to succeed */
    2382            0 :             eq_opfamilies = get_mergejoin_opfamilies(eq_op);
    2383            0 :             if (eq_opfamilies == NIL)
    2384            0 :                 break;          /* we're not going to succeed */
    2385            0 :             btree_opfamily = linitial_oid(eq_opfamilies);
    2386              :         }
    2387              :         else
    2388          105 :             btree_opfamily = part_scheme->partopfamily[ipk];
    2389              : 
    2390              :         /*
    2391              :          * We consider only non-nullable partition keys here; nullable ones
    2392              :          * would not be treated as part of the same equivalence classes as
    2393              :          * non-nullable ones.
    2394              :          */
    2395          183 :         foreach(lc, rel1->partexprs[ipk])
    2396              :         {
    2397          105 :             Node       *expr1 = (Node *) lfirst(lc);
    2398              :             ListCell   *lc2;
    2399          105 :             Oid         partcoll1 = rel1->part_scheme->partcollation[ipk];
    2400          105 :             Oid         exprcoll1 = exprCollation(expr1);
    2401              : 
    2402          189 :             foreach(lc2, rel2->partexprs[ipk])
    2403              :             {
    2404          111 :                 Node       *expr2 = (Node *) lfirst(lc2);
    2405              : 
    2406          111 :                 if (exprs_known_equal(root, expr1, expr2, btree_opfamily))
    2407              :                 {
    2408              :                     /*
    2409              :                      * Ensure that the collation of the expression matches
    2410              :                      * that of the partition key. Checking just one collation
    2411              :                      * (partcoll1 and exprcoll1) suffices because partcoll1
    2412              :                      * and partcoll2, as well as exprcoll1 and exprcoll2,
    2413              :                      * should be identical. This holds because both rel1 and
    2414              :                      * rel2 use the same PartitionScheme and expr1 and expr2
    2415              :                      * are equal.
    2416              :                      */
    2417           33 :                     if (partcoll1 == exprcoll1)
    2418              :                     {
    2419           27 :                         Oid         partcoll2 PG_USED_FOR_ASSERTS_ONLY =
    2420           27 :                             rel2->part_scheme->partcollation[ipk];
    2421              :                         Oid         exprcoll2 PG_USED_FOR_ASSERTS_ONLY =
    2422           27 :                             exprCollation(expr2);
    2423              : 
    2424              :                         Assert(partcoll2 == exprcoll2);
    2425           27 :                         pk_known_equal[ipk] = true;
    2426           27 :                         break;
    2427              :                     }
    2428              :                 }
    2429              :             }
    2430          105 :             if (pk_known_equal[ipk])
    2431           27 :                 break;
    2432              :         }
    2433              : 
    2434          105 :         if (pk_known_equal[ipk])
    2435              :         {
    2436              :             /* We can stop examining keys once we prove all keys equal. */
    2437           27 :             if (++num_equal_pks == part_scheme->partnatts)
    2438           27 :                 return true;
    2439              :         }
    2440              :         else
    2441           78 :             break;              /* no chance to succeed, give up */
    2442              :     }
    2443              : 
    2444           78 :     return false;
    2445              : }
    2446              : 
    2447              : /*
    2448              :  * match_expr_to_partition_keys
    2449              :  *
    2450              :  * Tries to match an expression to one of the nullable or non-nullable
    2451              :  * partition keys of "rel".  Returns the matched key's ordinal position,
    2452              :  * or -1 if the expression could not be matched to any of the keys.
    2453              :  *
    2454              :  * strict_op must be true if the expression will be compared with the
    2455              :  * partition key using a strict operator.  This allows us to consider
    2456              :  * nullable as well as nonnullable partition keys.
    2457              :  */
    2458              : static int
    2459         7866 : match_expr_to_partition_keys(Expr *expr, RelOptInfo *rel, bool strict_op)
    2460              : {
    2461              :     int         cnt;
    2462              : 
    2463              :     /* This function should be called only for partitioned relations. */
    2464              :     Assert(rel->part_scheme);
    2465              :     Assert(rel->partexprs);
    2466              :     Assert(rel->nullable_partexprs);
    2467              : 
    2468              :     /* Remove any relabel decorations. */
    2469         8010 :     while (IsA(expr, RelabelType))
    2470          144 :         expr = (Expr *) (castNode(RelabelType, expr))->arg;
    2471              : 
    2472         8358 :     for (cnt = 0; cnt < rel->part_scheme->partnatts; cnt++)
    2473              :     {
    2474              :         ListCell   *lc;
    2475              : 
    2476              :         /* We can always match to the non-nullable partition keys. */
    2477         8394 :         foreach(lc, rel->partexprs[cnt])
    2478              :         {
    2479         7860 :             if (equal(lfirst(lc), expr))
    2480         7350 :                 return cnt;
    2481              :         }
    2482              : 
    2483          534 :         if (!strict_op)
    2484            0 :             continue;
    2485              : 
    2486              :         /*
    2487              :          * If it's a strict join operator then a NULL partition key on one
    2488              :          * side will not join to any partition key on the other side, and in
    2489              :          * particular such a row can't join to a row from a different
    2490              :          * partition on the other side.  So, it's okay to search the nullable
    2491              :          * partition keys as well.
    2492              :          */
    2493          612 :         foreach(lc, rel->nullable_partexprs[cnt])
    2494              :         {
    2495          120 :             if (equal(lfirst(lc), expr))
    2496           42 :                 return cnt;
    2497              :         }
    2498              :     }
    2499              : 
    2500          474 :     return -1;
    2501              : }
    2502              : 
    2503              : /*
    2504              :  * set_joinrel_partition_key_exprs
    2505              :  *      Initialize partition key expressions for a partitioned joinrel.
    2506              :  */
    2507              : static void
    2508         3693 : set_joinrel_partition_key_exprs(RelOptInfo *joinrel,
    2509              :                                 RelOptInfo *outer_rel, RelOptInfo *inner_rel,
    2510              :                                 JoinType jointype)
    2511              : {
    2512         3693 :     PartitionScheme part_scheme = joinrel->part_scheme;
    2513         3693 :     int         partnatts = part_scheme->partnatts;
    2514              : 
    2515         3693 :     joinrel->partexprs = palloc0_array(List *, partnatts);
    2516         3693 :     joinrel->nullable_partexprs = palloc0_array(List *, partnatts);
    2517              : 
    2518              :     /*
    2519              :      * The joinrel's partition expressions are the same as those of the input
    2520              :      * rels, but we must properly classify them as nullable or not in the
    2521              :      * joinrel's output.  (Also, we add some more partition expressions if
    2522              :      * it's a FULL JOIN.)
    2523              :      */
    2524         7392 :     for (int cnt = 0; cnt < partnatts; cnt++)
    2525              :     {
    2526              :         /* mark these const to enforce that we copy them properly */
    2527         3699 :         const List *outer_expr = outer_rel->partexprs[cnt];
    2528         3699 :         const List *outer_null_expr = outer_rel->nullable_partexprs[cnt];
    2529         3699 :         const List *inner_expr = inner_rel->partexprs[cnt];
    2530         3699 :         const List *inner_null_expr = inner_rel->nullable_partexprs[cnt];
    2531         3699 :         List       *partexpr = NIL;
    2532         3699 :         List       *nullable_partexpr = NIL;
    2533              :         ListCell   *lc;
    2534              : 
    2535         3699 :         switch (jointype)
    2536              :         {
    2537              :                 /*
    2538              :                  * A join relation resulting from an INNER join may be
    2539              :                  * regarded as partitioned by either of the inner and outer
    2540              :                  * relation keys.  For example, A INNER JOIN B ON A.a = B.b
    2541              :                  * can be regarded as partitioned on either A.a or B.b.  So we
    2542              :                  * add both keys to the joinrel's partexpr lists.  However,
    2543              :                  * anything that was already nullable still has to be treated
    2544              :                  * as nullable.
    2545              :                  */
    2546         3110 :             case JOIN_INNER:
    2547         3110 :                 partexpr = list_concat_copy(outer_expr, inner_expr);
    2548         3110 :                 nullable_partexpr = list_concat_copy(outer_null_expr,
    2549              :                                                      inner_null_expr);
    2550         3110 :                 break;
    2551              : 
    2552              :                 /*
    2553              :                  * A join relation resulting from a SEMI or ANTI join may be
    2554              :                  * regarded as partitioned by the outer relation keys.  The
    2555              :                  * inner relation's keys are no longer interesting; since they
    2556              :                  * aren't visible in the join output, nothing could join to
    2557              :                  * them.
    2558              :                  */
    2559          156 :             case JOIN_SEMI:
    2560              :             case JOIN_ANTI:
    2561          156 :                 partexpr = list_copy(outer_expr);
    2562          156 :                 nullable_partexpr = list_copy(outer_null_expr);
    2563          156 :                 break;
    2564              : 
    2565              :                 /*
    2566              :                  * A join relation resulting from a LEFT OUTER JOIN likewise
    2567              :                  * may be regarded as partitioned on the (non-nullable) outer
    2568              :                  * relation keys.  The inner (nullable) relation keys are okay
    2569              :                  * as partition keys for further joins as long as they involve
    2570              :                  * strict join operators.
    2571              :                  */
    2572          290 :             case JOIN_LEFT:
    2573          290 :                 partexpr = list_copy(outer_expr);
    2574          290 :                 nullable_partexpr = list_concat_copy(inner_expr,
    2575              :                                                      outer_null_expr);
    2576          290 :                 nullable_partexpr = list_concat(nullable_partexpr,
    2577              :                                                 inner_null_expr);
    2578          290 :                 break;
    2579              : 
    2580              :                 /*
    2581              :                  * For FULL OUTER JOINs, both relations are nullable, so the
    2582              :                  * resulting join relation may be regarded as partitioned on
    2583              :                  * either of inner and outer relation keys, but only for joins
    2584              :                  * that involve strict join operators.
    2585              :                  */
    2586          143 :             case JOIN_FULL:
    2587          143 :                 nullable_partexpr = list_concat_copy(outer_expr,
    2588              :                                                      inner_expr);
    2589          143 :                 nullable_partexpr = list_concat(nullable_partexpr,
    2590              :                                                 outer_null_expr);
    2591          143 :                 nullable_partexpr = list_concat(nullable_partexpr,
    2592              :                                                 inner_null_expr);
    2593              : 
    2594              :                 /*
    2595              :                  * Also add CoalesceExprs corresponding to each possible
    2596              :                  * full-join output variable (that is, left side coalesced to
    2597              :                  * right side), so that we can match equijoin expressions
    2598              :                  * using those variables.  We really only need these for
    2599              :                  * columns merged by JOIN USING, and only with the pairs of
    2600              :                  * input items that correspond to the data structures that
    2601              :                  * parse analysis would build for such variables.  But it's
    2602              :                  * hard to tell which those are, so just make all the pairs.
    2603              :                  * Extra items in the nullable_partexprs list won't cause big
    2604              :                  * problems.  (It's possible that such items will get matched
    2605              :                  * to user-written COALESCEs, but it should still be valid to
    2606              :                  * partition on those, since they're going to be either the
    2607              :                  * partition column or NULL; it's the same argument as for
    2608              :                  * partitionwise nesting of any outer join.)  We assume no
    2609              :                  * type coercions are needed to make the coalesce expressions,
    2610              :                  * since columns of different types won't have gotten
    2611              :                  * classified as the same PartitionScheme.  Note that we
    2612              :                  * intentionally leave out the varnullingrels decoration that
    2613              :                  * would ordinarily appear on the Vars inside these
    2614              :                  * CoalesceExprs, because have_partkey_equi_join will strip
    2615              :                  * varnullingrels from the expressions it will compare to the
    2616              :                  * partexprs.
    2617              :                  */
    2618          364 :                 foreach(lc, list_concat_copy(outer_expr, outer_null_expr))
    2619              :                 {
    2620          221 :                     Node       *larg = (Node *) lfirst(lc);
    2621              :                     ListCell   *lc2;
    2622              : 
    2623          442 :                     foreach(lc2, list_concat_copy(inner_expr, inner_null_expr))
    2624              :                     {
    2625          221 :                         Node       *rarg = (Node *) lfirst(lc2);
    2626          221 :                         CoalesceExpr *c = makeNode(CoalesceExpr);
    2627              : 
    2628          221 :                         c->coalescetype = exprType(larg);
    2629          221 :                         c->coalescecollid = exprCollation(larg);
    2630          221 :                         c->args = list_make2(larg, rarg);
    2631          221 :                         c->location = -1;
    2632          221 :                         nullable_partexpr = lappend(nullable_partexpr, c);
    2633              :                     }
    2634              :                 }
    2635          143 :                 break;
    2636              : 
    2637            0 :             default:
    2638            0 :                 elog(ERROR, "unrecognized join type: %d", (int) jointype);
    2639              :         }
    2640              : 
    2641         3699 :         joinrel->partexprs[cnt] = partexpr;
    2642         3699 :         joinrel->nullable_partexprs[cnt] = nullable_partexpr;
    2643              :     }
    2644         3693 : }
    2645              : 
    2646              : /*
    2647              :  * build_child_join_reltarget
    2648              :  *    Set up a child-join relation's reltarget from a parent-join relation.
    2649              :  */
    2650              : static void
    2651         9185 : build_child_join_reltarget(PlannerInfo *root,
    2652              :                            RelOptInfo *parentrel,
    2653              :                            RelOptInfo *childrel,
    2654              :                            int nappinfos,
    2655              :                            AppendRelInfo **appinfos)
    2656              : {
    2657              :     /* Build the targetlist */
    2658        18370 :     childrel->reltarget->exprs = (List *)
    2659         9185 :         adjust_appendrel_attrs(root,
    2660         9185 :                                (Node *) parentrel->reltarget->exprs,
    2661              :                                nappinfos, appinfos);
    2662              : 
    2663              :     /* Set the cost and width fields */
    2664         9185 :     childrel->reltarget->cost.startup = parentrel->reltarget->cost.startup;
    2665         9185 :     childrel->reltarget->cost.per_tuple = parentrel->reltarget->cost.per_tuple;
    2666         9185 :     childrel->reltarget->width = parentrel->reltarget->width;
    2667         9185 : }
    2668              : 
    2669              : /*
    2670              :  * create_rel_agg_info
    2671              :  *    Create the RelAggInfo structure for the given relation if it can produce
    2672              :  *    grouped paths.  The given relation is the non-grouped one which has the
    2673              :  *    reltarget already constructed.
    2674              :  *
    2675              :  * calculate_grouped_rows: if true, calculate the estimated number of grouped
    2676              :  * rows for the relation.  If false, skip the estimation to avoid unnecessary
    2677              :  * planning overhead.
    2678              :  */
    2679              : RelAggInfo *
    2680        10521 : create_rel_agg_info(PlannerInfo *root, RelOptInfo *rel,
    2681              :                     bool calculate_grouped_rows)
    2682              : {
    2683              :     ListCell   *lc;
    2684              :     RelAggInfo *result;
    2685              :     PathTarget *agg_input;
    2686              :     PathTarget *target;
    2687        10521 :     List       *group_clauses = NIL;
    2688        10521 :     List       *group_exprs = NIL;
    2689              : 
    2690              :     /*
    2691              :      * The lists of aggregate expressions and grouping expressions should have
    2692              :      * been constructed.
    2693              :      */
    2694              :     Assert(root->agg_clause_list != NIL);
    2695              :     Assert(root->group_expr_list != NIL);
    2696              : 
    2697              :     /*
    2698              :      * If this is a child rel, the grouped rel for its parent rel must have
    2699              :      * been created if it can.  So we can just use parent's RelAggInfo if
    2700              :      * there is one, with appropriate variable substitutions.
    2701              :      */
    2702        10521 :     if (IS_OTHER_REL(rel))
    2703              :     {
    2704              :         RelOptInfo *grouped_rel;
    2705              :         RelAggInfo *agg_info;
    2706              : 
    2707         7566 :         grouped_rel = rel->top_parent->grouped_rel;
    2708         7566 :         if (grouped_rel == NULL)
    2709          906 :             return NULL;
    2710              : 
    2711              :         Assert(IS_GROUPED_REL(grouped_rel));
    2712              : 
    2713              :         /* Must do multi-level transformation */
    2714              :         agg_info = (RelAggInfo *)
    2715         6660 :             adjust_appendrel_attrs_multilevel(root,
    2716         6660 :                                               (Node *) grouped_rel->agg_info,
    2717              :                                               rel,
    2718         6660 :                                               rel->top_parent);
    2719              : 
    2720         6660 :         agg_info->apply_agg_at = NULL;   /* caller will change this later */
    2721              : 
    2722         6660 :         if (calculate_grouped_rows)
    2723              :         {
    2724          462 :             agg_info->grouped_rows =
    2725          462 :                 estimate_num_groups(root, agg_info->group_exprs,
    2726              :                                     rel->rows, NULL, NULL);
    2727              : 
    2728              :             /*
    2729              :              * The grouped paths for the given relation are considered useful
    2730              :              * iff the average group size is no less than
    2731              :              * min_eager_agg_group_size.
    2732              :              */
    2733          462 :             agg_info->agg_useful =
    2734          462 :                 (rel->rows / agg_info->grouped_rows) >= min_eager_agg_group_size;
    2735              :         }
    2736              : 
    2737         6660 :         return agg_info;
    2738              :     }
    2739              : 
    2740              :     /* Check if it's possible to produce grouped paths for this relation. */
    2741         2955 :     if (!eager_aggregation_possible_for_relation(root, rel))
    2742          542 :         return NULL;
    2743              : 
    2744              :     /*
    2745              :      * Create targets for the grouped paths and for the input paths of the
    2746              :      * grouped paths.
    2747              :      */
    2748         2413 :     target = create_empty_pathtarget();
    2749         2413 :     agg_input = create_empty_pathtarget();
    2750              : 
    2751              :     /* ... and initialize these targets */
    2752         2413 :     if (!init_grouping_targets(root, rel, target, agg_input,
    2753              :                                &group_clauses, &group_exprs))
    2754           75 :         return NULL;
    2755              : 
    2756              :     /*
    2757              :      * Eager aggregation is not applicable if there are no available grouping
    2758              :      * expressions.
    2759              :      */
    2760         2338 :     if (group_clauses == NIL)
    2761            9 :         return NULL;
    2762              : 
    2763              :     /* Add aggregates to the grouping target */
    2764         5996 :     foreach(lc, root->agg_clause_list)
    2765              :     {
    2766         3667 :         AggClauseInfo *ac_info = lfirst_node(AggClauseInfo, lc);
    2767              :         Aggref     *aggref;
    2768              : 
    2769              :         Assert(IsA(ac_info->aggref, Aggref));
    2770              : 
    2771         3667 :         aggref = (Aggref *) copyObject(ac_info->aggref);
    2772         3667 :         mark_partial_aggref(aggref, AGGSPLIT_INITIAL_SERIAL);
    2773              : 
    2774         3667 :         add_column_to_pathtarget(target, (Expr *) aggref, 0);
    2775              :     }
    2776              : 
    2777              :     /* Set the estimated eval cost and output width for both targets */
    2778         2329 :     set_pathtarget_cost_width(root, target);
    2779         2329 :     set_pathtarget_cost_width(root, agg_input);
    2780              : 
    2781              :     /* build the RelAggInfo result */
    2782         2329 :     result = makeNode(RelAggInfo);
    2783         2329 :     result->target = target;
    2784         2329 :     result->agg_input = agg_input;
    2785         2329 :     result->group_clauses = group_clauses;
    2786         2329 :     result->group_exprs = group_exprs;
    2787         2329 :     result->apply_agg_at = NULL; /* caller will change this later */
    2788              : 
    2789         2329 :     if (calculate_grouped_rows)
    2790              :     {
    2791          422 :         result->grouped_rows = estimate_num_groups(root, result->group_exprs,
    2792              :                                                    rel->rows, NULL, NULL);
    2793              : 
    2794              :         /*
    2795              :          * The grouped paths for the given relation are considered useful iff
    2796              :          * the average group size is no less than min_eager_agg_group_size.
    2797              :          */
    2798          422 :         result->agg_useful =
    2799          422 :             (rel->rows / result->grouped_rows) >= min_eager_agg_group_size;
    2800              :     }
    2801              : 
    2802         2329 :     return result;
    2803              : }
    2804              : 
    2805              : /*
    2806              :  * eager_aggregation_possible_for_relation
    2807              :  *    Check if it's possible to produce grouped paths for the given relation.
    2808              :  */
    2809              : static bool
    2810         2955 : eager_aggregation_possible_for_relation(PlannerInfo *root, RelOptInfo *rel)
    2811              : {
    2812              :     ListCell   *lc;
    2813              :     int         cur_relid;
    2814              : 
    2815              :     /*
    2816              :      * Check to see if the given relation is in the nullable side of an outer
    2817              :      * join.  In this case, we cannot push a partial aggregation down to the
    2818              :      * relation, because the NULL-extended rows produced by the outer join
    2819              :      * would not be available when we perform the partial aggregation, while
    2820              :      * with a non-eager-aggregation plan these rows are available for the
    2821              :      * top-level aggregation.  Doing so may result in the rows being grouped
    2822              :      * differently than expected, or produce incorrect values from the
    2823              :      * aggregate functions.
    2824              :      */
    2825         2955 :     cur_relid = -1;
    2826         8421 :     while ((cur_relid = bms_next_member(rel->relids, cur_relid)) >= 0)
    2827              :     {
    2828         5566 :         RelOptInfo *baserel = find_base_rel_ignore_join(root, cur_relid);
    2829              : 
    2830         5566 :         if (baserel == NULL)
    2831          208 :             continue;           /* ignore outer joins in rel->relids */
    2832              : 
    2833         5358 :         if (!bms_is_subset(baserel->nulling_relids, rel->relids))
    2834          100 :             return false;
    2835              :     }
    2836              : 
    2837              :     /*
    2838              :      * For now we don't try to support PlaceHolderVars.
    2839              :      */
    2840         8812 :     foreach(lc, rel->reltarget->exprs)
    2841              :     {
    2842         5963 :         Expr       *expr = lfirst(lc);
    2843              : 
    2844         5963 :         if (IsA(expr, PlaceHolderVar))
    2845            6 :             return false;
    2846              :     }
    2847              : 
    2848              :     /* Caller should only pass base relations or joins. */
    2849              :     Assert(rel->reloptkind == RELOPT_BASEREL ||
    2850              :            rel->reloptkind == RELOPT_JOINREL);
    2851              : 
    2852              :     /*
    2853              :      * Check if all aggregate expressions can be evaluated on this relation
    2854              :      * level.
    2855              :      */
    2856         6627 :     foreach(lc, root->agg_clause_list)
    2857              :     {
    2858         4214 :         AggClauseInfo *ac_info = lfirst_node(AggClauseInfo, lc);
    2859              : 
    2860              :         Assert(IsA(ac_info->aggref, Aggref));
    2861              : 
    2862              :         /*
    2863              :          * Give up if any aggregate requires relations other than the current
    2864              :          * one.  If the aggregate requires the current relation plus
    2865              :          * additional relations, grouping the current relation could make some
    2866              :          * input rows unavailable for the higher aggregate and may reduce the
    2867              :          * number of input rows it receives.  If the aggregate does not
    2868              :          * require the current relation at all, it should not be grouped, as
    2869              :          * we do not support joining two grouped relations.
    2870              :          */
    2871         4214 :         if (!bms_is_subset(ac_info->agg_eval_at, rel->relids))
    2872          436 :             return false;
    2873              :     }
    2874              : 
    2875         2413 :     return true;
    2876              : }
    2877              : 
    2878              : /*
    2879              :  * init_grouping_targets
    2880              :  *    Initialize the target for grouped paths (target) as well as the target
    2881              :  *    for paths that generate input for the grouped paths (agg_input).
    2882              :  *
    2883              :  * We also construct the list of SortGroupClauses and the list of grouping
    2884              :  * expressions for the partial aggregation, and return them in *group_clause
    2885              :  * and *group_exprs.
    2886              :  *
    2887              :  * Return true if the targets could be initialized, false otherwise.
    2888              :  */
    2889              : static bool
    2890         2413 : init_grouping_targets(PlannerInfo *root, RelOptInfo *rel,
    2891              :                       PathTarget *target, PathTarget *agg_input,
    2892              :                       List **group_clauses, List **group_exprs)
    2893              : {
    2894              :     ListCell   *lc;
    2895         2413 :     List       *possibly_dependent = NIL;
    2896              :     Index       maxSortGroupRef;
    2897              : 
    2898              :     /* Identify the max sortgroupref */
    2899         2413 :     maxSortGroupRef = 0;
    2900        11357 :     foreach(lc, root->processed_tlist)
    2901              :     {
    2902         8944 :         Index       ref = ((TargetEntry *) lfirst(lc))->ressortgroupref;
    2903              : 
    2904         8944 :         if (ref > maxSortGroupRef)
    2905         2640 :             maxSortGroupRef = ref;
    2906              :     }
    2907              : 
    2908              :     /*
    2909              :      * At this point, all Vars from this relation that are needed by upper
    2910              :      * joins or are required in the final targetlist should already be present
    2911              :      * in its reltarget.  Therefore, we can safely iterate over this
    2912              :      * relation's reltarget->exprs to construct the PathTarget and grouping
    2913              :      * clauses for the grouped paths.
    2914              :      */
    2915         7463 :     foreach(lc, rel->reltarget->exprs)
    2916              :     {
    2917         5053 :         Expr       *expr = (Expr *) lfirst(lc);
    2918              :         Index       sortgroupref;
    2919              : 
    2920              :         /*
    2921              :          * Given that PlaceHolderVar currently prevents us from doing eager
    2922              :          * aggregation, the source target cannot contain anything more complex
    2923              :          * than a Var.
    2924              :          */
    2925              :         Assert(IsA(expr, Var));
    2926              : 
    2927              :         /*
    2928              :          * Get the sortgroupref of the expr if it is found among, or can be
    2929              :          * deduced from, the original grouping expressions.
    2930              :          */
    2931         5053 :         sortgroupref = get_expression_sortgroupref(root, expr);
    2932         5053 :         if (sortgroupref > 0)
    2933              :         {
    2934              :             SortGroupClause *sgc;
    2935              : 
    2936              :             /* Find the matching SortGroupClause */
    2937         2368 :             sgc = get_sortgroupref_clause(sortgroupref, root->processed_groupClause);
    2938              :             Assert(sgc->tleSortGroupRef <= maxSortGroupRef);
    2939              : 
    2940              :             /*
    2941              :              * If the target expression is to be used as a grouping key, it
    2942              :              * should be emitted by the grouped paths that have been pushed
    2943              :              * down to this relation level.
    2944              :              */
    2945         2368 :             add_column_to_pathtarget(target, expr, sortgroupref);
    2946              : 
    2947              :             /*
    2948              :              * ... and it also should be emitted by the input paths.
    2949              :              */
    2950         2368 :             add_column_to_pathtarget(agg_input, expr, sortgroupref);
    2951              : 
    2952              :             /*
    2953              :              * Record this SortGroupClause and grouping expression.  Note that
    2954              :              * this SortGroupClause might have already been recorded.
    2955              :              */
    2956         2368 :             if (!list_member(*group_clauses, sgc))
    2957              :             {
    2958         2302 :                 *group_clauses = lappend(*group_clauses, sgc);
    2959         2302 :                 *group_exprs = lappend(*group_exprs, expr);
    2960              :             }
    2961              :         }
    2962         2685 :         else if (is_var_needed_by_join(root, (Var *) expr, rel))
    2963              :         {
    2964              :             /*
    2965              :              * The expression is needed for an upper join but is neither in
    2966              :              * the GROUP BY clause nor derivable from it using EC (otherwise,
    2967              :              * it would have already been included in the targets above).  We
    2968              :              * need to create a special SortGroupClause for this expression.
    2969              :              *
    2970              :              * It is important to include such expressions in the grouping
    2971              :              * keys.  This is essential to ensure that an aggregated row from
    2972              :              * the partial aggregation matches the other side of the join if
    2973              :              * and only if each row in the partial group does.  This ensures
    2974              :              * that all rows within the same partial group share the same
    2975              :              * 'destiny', which is crucial for maintaining correctness.
    2976              :              */
    2977              :             SortGroupClause *sgc;
    2978              :             TypeCacheEntry *tce;
    2979              :             Oid         equalimageproc;
    2980              : 
    2981              :             /*
    2982              :              * But first, check if equality implies image equality for this
    2983              :              * expression.  If not, we cannot use it as a grouping key.  See
    2984              :              * comments in create_grouping_expr_infos().
    2985              :              */
    2986          193 :             tce = lookup_type_cache(exprType((Node *) expr),
    2987              :                                     TYPECACHE_BTREE_OPFAMILY);
    2988          193 :             if (!OidIsValid(tce->btree_opf) ||
    2989          193 :                 !OidIsValid(tce->btree_opintype))
    2990            3 :                 return false;
    2991              : 
    2992          193 :             equalimageproc = get_opfamily_proc(tce->btree_opf,
    2993              :                                                tce->btree_opintype,
    2994              :                                                tce->btree_opintype,
    2995              :                                                BTEQUALIMAGE_PROC);
    2996          193 :             if (!OidIsValid(equalimageproc) ||
    2997          190 :                 !DatumGetBool(OidFunctionCall1Coll(equalimageproc,
    2998              :                                                    tce->typcollation,
    2999              :                                                    ObjectIdGetDatum(tce->btree_opintype))))
    3000            3 :                 return false;
    3001              : 
    3002              :             /* Create the SortGroupClause. */
    3003          190 :             sgc = makeNode(SortGroupClause);
    3004              : 
    3005              :             /* Initialize the SortGroupClause. */
    3006          190 :             sgc->tleSortGroupRef = ++maxSortGroupRef;
    3007          190 :             get_sort_group_operators(exprType((Node *) expr),
    3008              :                                      false, true, false,
    3009              :                                      &sgc->sortop, &sgc->eqop, NULL,
    3010              :                                      &sgc->hashable);
    3011              : 
    3012              :             /* This expression should be emitted by the grouped paths */
    3013          190 :             add_column_to_pathtarget(target, expr, sgc->tleSortGroupRef);
    3014              : 
    3015              :             /* ... and it also should be emitted by the input paths. */
    3016          190 :             add_column_to_pathtarget(agg_input, expr, sgc->tleSortGroupRef);
    3017              : 
    3018              :             /* Record this SortGroupClause and grouping expression */
    3019          190 :             *group_clauses = lappend(*group_clauses, sgc);
    3020          190 :             *group_exprs = lappend(*group_exprs, expr);
    3021              :         }
    3022         2492 :         else if (is_var_in_aggref_only(root, (Var *) expr))
    3023              :         {
    3024              :             /*
    3025              :              * The expression is referenced by an aggregate function pushed
    3026              :              * down to this relation and does not appear elsewhere in the
    3027              :              * targetlist or havingQual.  Add it to 'agg_input' but not to
    3028              :              * 'target'.
    3029              :              */
    3030         2324 :             add_new_column_to_pathtarget(agg_input, expr);
    3031              :         }
    3032              :         else
    3033              :         {
    3034              :             /*
    3035              :              * The expression may be functionally dependent on other
    3036              :              * expressions in the target, but we cannot verify this until all
    3037              :              * target expressions have been constructed.
    3038              :              */
    3039          168 :             possibly_dependent = lappend(possibly_dependent, expr);
    3040              :         }
    3041              :     }
    3042              : 
    3043              :     /*
    3044              :      * Now we can verify whether an expression is functionally dependent on
    3045              :      * others.
    3046              :      */
    3047         2434 :     foreach(lc, possibly_dependent)
    3048              :     {
    3049              :         Var        *tvar;
    3050           96 :         List       *deps = NIL;
    3051              :         RangeTblEntry *rte;
    3052              : 
    3053           96 :         tvar = lfirst_node(Var, lc);
    3054           96 :         rte = root->simple_rte_array[tvar->varno];
    3055              : 
    3056           96 :         if (check_functional_grouping(rte->relid, tvar->varno,
    3057              :                                       tvar->varlevelsup,
    3058              :                                       target->exprs, &deps))
    3059              :         {
    3060              :             /*
    3061              :              * The expression is functionally dependent on other target
    3062              :              * expressions, so it can be included in the targets.  Since it
    3063              :              * will not be used as a grouping key, a sortgroupref is not
    3064              :              * needed for it.
    3065              :              */
    3066           24 :             add_new_column_to_pathtarget(target, (Expr *) tvar);
    3067           24 :             add_new_column_to_pathtarget(agg_input, (Expr *) tvar);
    3068              :         }
    3069              :         else
    3070              :         {
    3071              :             /*
    3072              :              * We may arrive here with a grouping expression that is proven
    3073              :              * redundant by EquivalenceClass processing, such as 't1.a' in the
    3074              :              * query below.
    3075              :              *
    3076              :              * select max(t1.c) from t t1, t t2 where t1.a = 1 group by t1.a,
    3077              :              * t1.b;
    3078              :              *
    3079              :              * For now we just give up in this case.
    3080              :              */
    3081           72 :             return false;
    3082              :         }
    3083              :     }
    3084              : 
    3085         2338 :     return true;
    3086              : }
    3087              : 
    3088              : /*
    3089              :  * is_var_in_aggref_only
    3090              :  *    Check whether the given Var appears in aggregate expressions and not
    3091              :  *    elsewhere in the targetlist or havingQual.
    3092              :  */
    3093              : static bool
    3094         2492 : is_var_in_aggref_only(PlannerInfo *root, Var *var)
    3095              : {
    3096              :     ListCell   *lc;
    3097              : 
    3098              :     /*
    3099              :      * Search the list of aggregate expressions for the Var.
    3100              :      */
    3101         2732 :     foreach(lc, root->agg_clause_list)
    3102              :     {
    3103         2564 :         AggClauseInfo *ac_info = lfirst_node(AggClauseInfo, lc);
    3104              :         List       *vars;
    3105              : 
    3106              :         Assert(IsA(ac_info->aggref, Aggref));
    3107              : 
    3108         2564 :         if (!bms_is_member(var->varno, ac_info->agg_eval_at))
    3109          240 :             continue;
    3110              : 
    3111         2324 :         vars = pull_var_clause((Node *) ac_info->aggref,
    3112              :                                PVC_RECURSE_AGGREGATES |
    3113              :                                PVC_RECURSE_WINDOWFUNCS |
    3114              :                                PVC_RECURSE_PLACEHOLDERS);
    3115              : 
    3116         2324 :         if (list_member(vars, var))
    3117              :         {
    3118         2324 :             list_free(vars);
    3119         2324 :             break;
    3120              :         }
    3121              : 
    3122            0 :         list_free(vars);
    3123              :     }
    3124              : 
    3125         2492 :     return (lc != NULL && !list_member(root->tlist_vars, var));
    3126              : }
    3127              : 
    3128              : /*
    3129              :  * is_var_needed_by_join
    3130              :  *    Check if the given Var is needed by joins above the current rel.
    3131              :  */
    3132              : static bool
    3133         2685 : is_var_needed_by_join(PlannerInfo *root, Var *var, RelOptInfo *rel)
    3134              : {
    3135              :     Relids      relids;
    3136              :     int         attno;
    3137              :     RelOptInfo *baserel;
    3138              : 
    3139              :     /*
    3140              :      * Note that when checking if the Var is needed by joins above, we want to
    3141              :      * exclude cases where the Var is only needed in the final targetlist.  So
    3142              :      * include "relation 0" in the check.
    3143              :      */
    3144         2685 :     relids = bms_copy(rel->relids);
    3145         2685 :     relids = bms_add_member(relids, 0);
    3146              : 
    3147         2685 :     baserel = find_base_rel(root, var->varno);
    3148         2685 :     attno = var->varattno - baserel->min_attr;
    3149              : 
    3150         2685 :     return bms_nonempty_difference(baserel->attr_needed[attno], relids);
    3151              : }
    3152              : 
    3153              : /*
    3154              :  * get_expression_sortgroupref
    3155              :  *    Return the sortgroupref of the given "expr" if it is found among the
    3156              :  *    original grouping expressions, or is known equal to any of the original
    3157              :  *    grouping expressions due to equivalence relationships.  Return 0 if no
    3158              :  *    match is found.
    3159              :  */
    3160              : static Index
    3161         5053 : get_expression_sortgroupref(PlannerInfo *root, Expr *expr)
    3162              : {
    3163              :     ListCell   *lc;
    3164              : 
    3165              :     Assert(IsA(expr, Var));
    3166              : 
    3167         7833 :     foreach(lc, root->group_expr_list)
    3168              :     {
    3169         5148 :         GroupingExprInfo *ge_info = lfirst_node(GroupingExprInfo, lc);
    3170              :         ListCell   *lc1;
    3171              : 
    3172              :         Assert(IsA(ge_info->expr, Var));
    3173              :         Assert(ge_info->sortgroupref > 0);
    3174              : 
    3175         5148 :         if (equal(expr, ge_info->expr))
    3176         2368 :             return ge_info->sortgroupref;
    3177              : 
    3178         2924 :         if (ge_info->ec == NULL ||
    3179         2924 :             !bms_is_member(((Var *) expr)->varno, ge_info->ec->ec_relids))
    3180         1368 :             continue;
    3181              : 
    3182              :         /*
    3183              :          * Scan the EquivalenceClass, looking for a match to the given
    3184              :          * expression.  We ignore child members here.
    3185              :          */
    3186         4531 :         foreach(lc1, ge_info->ec->ec_members)
    3187              :         {
    3188         3119 :             EquivalenceMember *em = (EquivalenceMember *) lfirst(lc1);
    3189              : 
    3190              :             /* Child members should not exist in ec_members */
    3191              :             Assert(!em->em_is_child);
    3192              : 
    3193         3119 :             if (equal(expr, em->em_expr))
    3194          144 :                 return ge_info->sortgroupref;
    3195              :         }
    3196              :     }
    3197              : 
    3198              :     /* no match is found */
    3199         2685 :     return 0;
    3200              : }
        

Generated by: LCOV version 2.0-1