LCOV - code coverage report
Current view: top level - src/backend/optimizer/plan - initsplan.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 95.6 % 1171 1119
Test Date: 2026-02-17 17:20:33 Functions: 100.0 % 38 38
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * initsplan.c
       4              :  *    Target list, group by, qualification, joininfo initialization 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/plan/initsplan.c
      12              :  *
      13              :  *-------------------------------------------------------------------------
      14              :  */
      15              : #include "postgres.h"
      16              : 
      17              : #include "access/nbtree.h"
      18              : #include "catalog/pg_constraint.h"
      19              : #include "catalog/pg_type.h"
      20              : #include "nodes/makefuncs.h"
      21              : #include "nodes/nodeFuncs.h"
      22              : #include "optimizer/clauses.h"
      23              : #include "optimizer/cost.h"
      24              : #include "optimizer/inherit.h"
      25              : #include "optimizer/joininfo.h"
      26              : #include "optimizer/optimizer.h"
      27              : #include "optimizer/pathnode.h"
      28              : #include "optimizer/paths.h"
      29              : #include "optimizer/placeholder.h"
      30              : #include "optimizer/planmain.h"
      31              : #include "optimizer/planner.h"
      32              : #include "optimizer/restrictinfo.h"
      33              : #include "parser/analyze.h"
      34              : #include "rewrite/rewriteManip.h"
      35              : #include "utils/lsyscache.h"
      36              : #include "utils/rel.h"
      37              : #include "utils/typcache.h"
      38              : 
      39              : /* These parameters are set by GUC */
      40              : int         from_collapse_limit;
      41              : int         join_collapse_limit;
      42              : 
      43              : 
      44              : /*
      45              :  * deconstruct_jointree requires multiple passes over the join tree, because we
      46              :  * need to finish computing JoinDomains before we start distributing quals.
      47              :  * As long as we have to do that, other information such as the relevant
      48              :  * qualscopes might as well be computed in the first pass too.
      49              :  *
      50              :  * deconstruct_recurse recursively examines the join tree and builds a List
      51              :  * (in depth-first traversal order) of JoinTreeItem structs, which are then
      52              :  * processed iteratively by deconstruct_distribute.  If there are outer
      53              :  * joins, non-degenerate outer join clauses are processed in a third pass
      54              :  * deconstruct_distribute_oj_quals.
      55              :  *
      56              :  * The JoinTreeItem structs themselves can be freed at the end of
      57              :  * deconstruct_jointree, but do not modify or free their substructure,
      58              :  * as the relid sets may also be pointed to by RestrictInfo and
      59              :  * SpecialJoinInfo nodes.
      60              :  */
      61              : typedef struct JoinTreeItem
      62              : {
      63              :     /* Fields filled during deconstruct_recurse: */
      64              :     Node       *jtnode;         /* jointree node to examine */
      65              :     JoinDomain *jdomain;        /* join domain for its ON/WHERE clauses */
      66              :     struct JoinTreeItem *jti_parent;    /* JoinTreeItem for this node's
      67              :                                          * parent, or NULL if it's the top */
      68              :     Relids      qualscope;      /* base+OJ Relids syntactically included in
      69              :                                  * this jointree node */
      70              :     Relids      inner_join_rels;    /* base+OJ Relids syntactically included
      71              :                                      * in inner joins appearing at or below
      72              :                                      * this jointree node */
      73              :     Relids      left_rels;      /* if join node, Relids of the left side */
      74              :     Relids      right_rels;     /* if join node, Relids of the right side */
      75              :     Relids      nonnullable_rels;   /* if outer join, Relids of the
      76              :                                      * non-nullable side */
      77              :     /* Fields filled during deconstruct_distribute: */
      78              :     SpecialJoinInfo *sjinfo;    /* if outer join, its SpecialJoinInfo */
      79              :     List       *oj_joinclauses; /* outer join quals not yet distributed */
      80              :     List       *lateral_clauses;    /* quals postponed from children due to
      81              :                                      * lateral references */
      82              : } JoinTreeItem;
      83              : 
      84              : 
      85              : static bool is_partial_agg_memory_risky(PlannerInfo *root);
      86              : static void create_agg_clause_infos(PlannerInfo *root);
      87              : static void create_grouping_expr_infos(PlannerInfo *root);
      88              : static EquivalenceClass *get_eclass_for_sortgroupclause(PlannerInfo *root,
      89              :                                                         SortGroupClause *sgc,
      90              :                                                         Expr *expr);
      91              : static void extract_lateral_references(PlannerInfo *root, RelOptInfo *brel,
      92              :                                        Index rtindex);
      93              : static List *deconstruct_recurse(PlannerInfo *root, Node *jtnode,
      94              :                                  JoinDomain *parent_domain,
      95              :                                  JoinTreeItem *parent_jtitem,
      96              :                                  List **item_list);
      97              : static void deconstruct_distribute(PlannerInfo *root, JoinTreeItem *jtitem);
      98              : static void process_security_barrier_quals(PlannerInfo *root,
      99              :                                            int rti, JoinTreeItem *jtitem);
     100              : static void mark_rels_nulled_by_join(PlannerInfo *root, Index ojrelid,
     101              :                                      Relids lower_rels);
     102              : static SpecialJoinInfo *make_outerjoininfo(PlannerInfo *root,
     103              :                                            Relids left_rels, Relids right_rels,
     104              :                                            Relids inner_join_rels,
     105              :                                            JoinType jointype, Index ojrelid,
     106              :                                            List *clause);
     107              : static void compute_semijoin_info(PlannerInfo *root, SpecialJoinInfo *sjinfo,
     108              :                                   List *clause);
     109              : static void deconstruct_distribute_oj_quals(PlannerInfo *root,
     110              :                                             List *jtitems,
     111              :                                             JoinTreeItem *jtitem);
     112              : static void distribute_quals_to_rels(PlannerInfo *root, List *clauses,
     113              :                                      JoinTreeItem *jtitem,
     114              :                                      SpecialJoinInfo *sjinfo,
     115              :                                      Index security_level,
     116              :                                      Relids qualscope,
     117              :                                      Relids ojscope,
     118              :                                      Relids outerjoin_nonnullable,
     119              :                                      Relids incompatible_relids,
     120              :                                      bool allow_equivalence,
     121              :                                      bool has_clone,
     122              :                                      bool is_clone,
     123              :                                      List **postponed_oj_qual_list);
     124              : static void distribute_qual_to_rels(PlannerInfo *root, Node *clause,
     125              :                                     JoinTreeItem *jtitem,
     126              :                                     SpecialJoinInfo *sjinfo,
     127              :                                     Index security_level,
     128              :                                     Relids qualscope,
     129              :                                     Relids ojscope,
     130              :                                     Relids outerjoin_nonnullable,
     131              :                                     Relids incompatible_relids,
     132              :                                     bool allow_equivalence,
     133              :                                     bool has_clone,
     134              :                                     bool is_clone,
     135              :                                     List **postponed_oj_qual_list);
     136              : static bool check_redundant_nullability_qual(PlannerInfo *root, Node *clause);
     137              : static Relids get_join_domain_min_rels(PlannerInfo *root, Relids domain_relids);
     138              : static void check_mergejoinable(RestrictInfo *restrictinfo);
     139              : static void check_hashjoinable(RestrictInfo *restrictinfo);
     140              : static void check_memoizable(RestrictInfo *restrictinfo);
     141              : 
     142              : 
     143              : /*****************************************************************************
     144              :  *
     145              :  *   JOIN TREES
     146              :  *
     147              :  *****************************************************************************/
     148              : 
     149              : /*
     150              :  * add_base_rels_to_query
     151              :  *
     152              :  *    Scan the query's jointree and create baserel RelOptInfos for all
     153              :  *    the base relations (e.g., table, subquery, and function RTEs)
     154              :  *    appearing in the jointree.
     155              :  *
     156              :  * The initial invocation must pass root->parse->jointree as the value of
     157              :  * jtnode.  Internally, the function recurses through the jointree.
     158              :  *
     159              :  * At the end of this process, there should be one baserel RelOptInfo for
     160              :  * every non-join RTE that is used in the query.  Some of the baserels
     161              :  * may be appendrel parents, which will require additional "otherrel"
     162              :  * RelOptInfos for their member rels, but those are added later.
     163              :  */
     164              : void
     165       480813 : add_base_rels_to_query(PlannerInfo *root, Node *jtnode)
     166              : {
     167       480813 :     if (jtnode == NULL)
     168            0 :         return;
     169       480813 :     if (IsA(jtnode, RangeTblRef))
     170              :     {
     171       249986 :         int         varno = ((RangeTblRef *) jtnode)->rtindex;
     172              : 
     173       249986 :         (void) build_simple_rel(root, varno, NULL);
     174              :     }
     175       230827 :     else if (IsA(jtnode, FromExpr))
     176              :     {
     177       178774 :         FromExpr   *f = (FromExpr *) jtnode;
     178              :         ListCell   *l;
     179              : 
     180       383027 :         foreach(l, f->fromlist)
     181       204262 :             add_base_rels_to_query(root, lfirst(l));
     182              :     }
     183        52053 :     else if (IsA(jtnode, JoinExpr))
     184              :     {
     185        52053 :         JoinExpr   *j = (JoinExpr *) jtnode;
     186              : 
     187        52053 :         add_base_rels_to_query(root, j->larg);
     188        52053 :         add_base_rels_to_query(root, j->rarg);
     189              :     }
     190              :     else
     191            0 :         elog(ERROR, "unrecognized node type: %d",
     192              :              (int) nodeTag(jtnode));
     193              : }
     194              : 
     195              : /*
     196              :  * add_other_rels_to_query
     197              :  *    create "otherrel" RelOptInfos for the children of appendrel baserels
     198              :  *
     199              :  * At the end of this process, there should be RelOptInfos for all relations
     200              :  * that will be scanned by the query.
     201              :  */
     202              : void
     203       172436 : add_other_rels_to_query(PlannerInfo *root)
     204              : {
     205              :     int         rti;
     206              : 
     207       529909 :     for (rti = 1; rti < root->simple_rel_array_size; rti++)
     208              :     {
     209       357474 :         RelOptInfo *rel = root->simple_rel_array[rti];
     210       357474 :         RangeTblEntry *rte = root->simple_rte_array[rti];
     211              : 
     212              :         /* there may be empty slots corresponding to non-baserel RTEs */
     213       357474 :         if (rel == NULL)
     214        84000 :             continue;
     215              : 
     216              :         /* Ignore any "otherrels" that were already added. */
     217       273474 :         if (rel->reloptkind != RELOPT_BASEREL)
     218        29757 :             continue;
     219              : 
     220              :         /* If it's marked as inheritable, look for children. */
     221       243717 :         if (rte->inh)
     222        11279 :             expand_inherited_rtentry(root, rel, rte, rti);
     223              :     }
     224       172435 : }
     225              : 
     226              : 
     227              : /*****************************************************************************
     228              :  *
     229              :  *   TARGET LISTS
     230              :  *
     231              :  *****************************************************************************/
     232              : 
     233              : /*
     234              :  * build_base_rel_tlists
     235              :  *    Add targetlist entries for each var needed in the query's final tlist
     236              :  *    (and HAVING clause, if any) to the appropriate base relations.
     237              :  *
     238              :  * We mark such vars as needed by "relation 0" to ensure that they will
     239              :  * propagate up through all join plan steps.
     240              :  */
     241              : void
     242       172454 : build_base_rel_tlists(PlannerInfo *root, List *final_tlist)
     243              : {
     244       172454 :     List       *tlist_vars = pull_var_clause((Node *) final_tlist,
     245              :                                              PVC_RECURSE_AGGREGATES |
     246              :                                              PVC_RECURSE_WINDOWFUNCS |
     247              :                                              PVC_INCLUDE_PLACEHOLDERS);
     248              : 
     249       172454 :     if (tlist_vars != NIL)
     250              :     {
     251       160445 :         add_vars_to_targetlist(root, tlist_vars, bms_make_singleton(0));
     252       160445 :         list_free(tlist_vars);
     253              :     }
     254              : 
     255              :     /*
     256              :      * If there's a HAVING clause, we'll need the Vars it uses, too.  Note
     257              :      * that HAVING can contain Aggrefs but not WindowFuncs.
     258              :      */
     259       172454 :     if (root->parse->havingQual)
     260              :     {
     261          466 :         List       *having_vars = pull_var_clause(root->parse->havingQual,
     262              :                                                   PVC_RECURSE_AGGREGATES |
     263              :                                                   PVC_INCLUDE_PLACEHOLDERS);
     264              : 
     265          466 :         if (having_vars != NIL)
     266              :         {
     267          406 :             add_vars_to_targetlist(root, having_vars,
     268              :                                    bms_make_singleton(0));
     269          406 :             list_free(having_vars);
     270              :         }
     271              :     }
     272       172454 : }
     273              : 
     274              : /*
     275              :  * add_vars_to_targetlist
     276              :  *    For each variable appearing in the list, add it to the owning
     277              :  *    relation's targetlist if not already present, and mark the variable
     278              :  *    as being needed for the indicated join (or for final output if
     279              :  *    where_needed includes "relation 0").
     280              :  *
     281              :  *    The list may also contain PlaceHolderVars.  These don't necessarily
     282              :  *    have a single owning relation; we keep their attr_needed info in
     283              :  *    root->placeholder_list instead.  Find or create the associated
     284              :  *    PlaceHolderInfo entry, and update its ph_needed.
     285              :  *
     286              :  *    See also add_vars_to_attr_needed.
     287              :  */
     288              : void
     289       332063 : add_vars_to_targetlist(PlannerInfo *root, List *vars,
     290              :                        Relids where_needed)
     291              : {
     292              :     ListCell   *temp;
     293              : 
     294              :     Assert(!bms_is_empty(where_needed));
     295              : 
     296      1164337 :     foreach(temp, vars)
     297              :     {
     298       832274 :         Node       *node = (Node *) lfirst(temp);
     299              : 
     300       832274 :         if (IsA(node, Var))
     301              :         {
     302       830606 :             Var        *var = (Var *) node;
     303       830606 :             RelOptInfo *rel = find_base_rel(root, var->varno);
     304       830606 :             int         attno = var->varattno;
     305              : 
     306       830606 :             if (bms_is_subset(where_needed, rel->relids))
     307          770 :                 continue;
     308              :             Assert(attno >= rel->min_attr && attno <= rel->max_attr);
     309       829836 :             attno -= rel->min_attr;
     310       829836 :             if (rel->attr_needed[attno] == NULL)
     311              :             {
     312              :                 /*
     313              :                  * Variable not yet requested, so add to rel's targetlist.
     314              :                  *
     315              :                  * The value available at the rel's scan level has not been
     316              :                  * nulled by any outer join, so drop its varnullingrels.
     317              :                  * (We'll put those back as we climb up the join tree.)
     318              :                  */
     319       624572 :                 var = copyObject(var);
     320       624572 :                 var->varnullingrels = NULL;
     321       624572 :                 rel->reltarget->exprs = lappend(rel->reltarget->exprs, var);
     322              :                 /* reltarget cost and width will be computed later */
     323              :             }
     324       829836 :             rel->attr_needed[attno] = bms_add_members(rel->attr_needed[attno],
     325              :                                                       where_needed);
     326              :         }
     327         1668 :         else if (IsA(node, PlaceHolderVar))
     328              :         {
     329         1668 :             PlaceHolderVar *phv = (PlaceHolderVar *) node;
     330         1668 :             PlaceHolderInfo *phinfo = find_placeholder_info(root, phv);
     331              : 
     332         1668 :             phinfo->ph_needed = bms_add_members(phinfo->ph_needed,
     333              :                                                 where_needed);
     334              :         }
     335              :         else
     336            0 :             elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
     337              :     }
     338       332063 : }
     339              : 
     340              : /*
     341              :  * add_vars_to_attr_needed
     342              :  *    This does a subset of what add_vars_to_targetlist does: it just
     343              :  *    updates attr_needed for Vars and ph_needed for PlaceHolderVars.
     344              :  *    We assume the Vars are already in their relations' targetlists.
     345              :  *
     346              :  *    This is used to rebuild attr_needed/ph_needed sets after removal
     347              :  *    of a useless outer join.  The removed join clause might have been
     348              :  *    the only upper-level use of some other relation's Var, in which
     349              :  *    case we can reduce that Var's attr_needed and thereby possibly
     350              :  *    open the door to further join removals.  But we can't tell that
     351              :  *    without tedious reconstruction of the attr_needed data.
     352              :  *
     353              :  *    Note that if a Var's attr_needed is successfully reduced to empty,
     354              :  *    it will still be in the relation's targetlist even though we do
     355              :  *    not really need the scan plan node to emit it.  The extra plan
     356              :  *    inefficiency seems tiny enough to not be worth spending planner
     357              :  *    cycles to get rid of it.
     358              :  */
     359              : void
     360         8455 : add_vars_to_attr_needed(PlannerInfo *root, List *vars,
     361              :                         Relids where_needed)
     362              : {
     363              :     ListCell   *temp;
     364              : 
     365              :     Assert(!bms_is_empty(where_needed));
     366              : 
     367        19180 :     foreach(temp, vars)
     368              :     {
     369        10725 :         Node       *node = (Node *) lfirst(temp);
     370              : 
     371        10725 :         if (IsA(node, Var))
     372              :         {
     373        10677 :             Var        *var = (Var *) node;
     374        10677 :             RelOptInfo *rel = find_base_rel(root, var->varno);
     375        10677 :             int         attno = var->varattno;
     376              : 
     377        10677 :             if (bms_is_subset(where_needed, rel->relids))
     378          428 :                 continue;
     379              :             Assert(attno >= rel->min_attr && attno <= rel->max_attr);
     380        10249 :             attno -= rel->min_attr;
     381        10249 :             rel->attr_needed[attno] = bms_add_members(rel->attr_needed[attno],
     382              :                                                       where_needed);
     383              :         }
     384           48 :         else if (IsA(node, PlaceHolderVar))
     385              :         {
     386           48 :             PlaceHolderVar *phv = (PlaceHolderVar *) node;
     387           48 :             PlaceHolderInfo *phinfo = find_placeholder_info(root, phv);
     388              : 
     389           48 :             phinfo->ph_needed = bms_add_members(phinfo->ph_needed,
     390              :                                                 where_needed);
     391              :         }
     392              :         else
     393            0 :             elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
     394              :     }
     395         8455 : }
     396              : 
     397              : /*****************************************************************************
     398              :  *
     399              :  *    GROUP BY
     400              :  *
     401              :  *****************************************************************************/
     402              : 
     403              : /*
     404              :  * remove_useless_groupby_columns
     405              :  *      Remove any columns in the GROUP BY clause that are redundant due to
     406              :  *      being functionally dependent on other GROUP BY columns.
     407              :  *
     408              :  * Since some other DBMSes do not allow references to ungrouped columns, it's
     409              :  * not unusual to find all columns listed in GROUP BY even though listing the
     410              :  * primary-key columns, or columns of a unique constraint would be sufficient.
     411              :  * Deleting such excess columns avoids redundant sorting or hashing work, so
     412              :  * it's worth doing.
     413              :  *
     414              :  * Relcache invalidations will ensure that cached plans become invalidated
     415              :  * when the underlying supporting indexes are dropped or if a column's NOT
     416              :  * NULL attribute is removed.
     417              :  */
     418              : void
     419       172436 : remove_useless_groupby_columns(PlannerInfo *root)
     420              : {
     421       172436 :     Query      *parse = root->parse;
     422              :     Bitmapset **groupbyattnos;
     423              :     Bitmapset **surplusvars;
     424       172436 :     bool        tryremove = false;
     425              :     ListCell   *lc;
     426              :     int         relid;
     427              : 
     428              :     /* No chance to do anything if there are less than two GROUP BY items */
     429       172436 :     if (list_length(root->processed_groupClause) < 2)
     430       171348 :         return;
     431              : 
     432              :     /* Don't fiddle with the GROUP BY clause if the query has grouping sets */
     433         1088 :     if (parse->groupingSets)
     434          367 :         return;
     435              : 
     436              :     /*
     437              :      * Scan the GROUP BY clause to find GROUP BY items that are simple Vars.
     438              :      * Fill groupbyattnos[k] with a bitmapset of the column attnos of RTE k
     439              :      * that are GROUP BY items.
     440              :      */
     441          721 :     groupbyattnos = palloc0_array(Bitmapset *, list_length(parse->rtable) + 1);
     442         2609 :     foreach(lc, root->processed_groupClause)
     443              :     {
     444         1888 :         SortGroupClause *sgc = lfirst_node(SortGroupClause, lc);
     445         1888 :         TargetEntry *tle = get_sortgroupclause_tle(sgc, parse->targetList);
     446         1888 :         Var        *var = (Var *) tle->expr;
     447              : 
     448              :         /*
     449              :          * Ignore non-Vars and Vars from other query levels.
     450              :          *
     451              :          * XXX in principle, stable expressions containing Vars could also be
     452              :          * removed, if all the Vars are functionally dependent on other GROUP
     453              :          * BY items.  But it's not clear that such cases occur often enough to
     454              :          * be worth troubling over.
     455              :          */
     456         1888 :         if (!IsA(var, Var) ||
     457         1483 :             var->varlevelsup > 0)
     458          405 :             continue;
     459              : 
     460              :         /* OK, remember we have this Var */
     461         1483 :         relid = var->varno;
     462              :         Assert(relid <= list_length(parse->rtable));
     463              : 
     464              :         /*
     465              :          * If this isn't the first column for this relation then we now have
     466              :          * multiple columns.  That means there might be some that can be
     467              :          * removed.
     468              :          */
     469         1483 :         tryremove |= !bms_is_empty(groupbyattnos[relid]);
     470         1483 :         groupbyattnos[relid] = bms_add_member(groupbyattnos[relid],
     471         1483 :                                               var->varattno - FirstLowInvalidHeapAttributeNumber);
     472              :     }
     473              : 
     474              :     /*
     475              :      * No Vars or didn't find multiple Vars for any relation in the GROUP BY?
     476              :      * If so, nothing can be removed, so don't waste more effort trying.
     477              :      */
     478          721 :     if (!tryremove)
     479          226 :         return;
     480              : 
     481              :     /*
     482              :      * Consider each relation and see if it is possible to remove some of its
     483              :      * Vars from GROUP BY.  For simplicity and speed, we do the actual removal
     484              :      * in a separate pass.  Here, we just fill surplusvars[k] with a bitmapset
     485              :      * of the column attnos of RTE k that are removable GROUP BY items.
     486              :      */
     487          495 :     surplusvars = NULL;         /* don't allocate array unless required */
     488          495 :     relid = 0;
     489         2074 :     foreach(lc, parse->rtable)
     490              :     {
     491         1579 :         RangeTblEntry *rte = lfirst_node(RangeTblEntry, lc);
     492              :         RelOptInfo *rel;
     493              :         Bitmapset  *relattnos;
     494         1579 :         Bitmapset  *best_keycolumns = NULL;
     495         1579 :         int32       best_nkeycolumns = PG_INT32_MAX;
     496              : 
     497         1579 :         relid++;
     498              : 
     499              :         /* Only plain relations could have primary-key constraints */
     500         1579 :         if (rte->rtekind != RTE_RELATION)
     501          803 :             continue;
     502              : 
     503              :         /*
     504              :          * We must skip inheritance parent tables as some of the child rels
     505              :          * may cause duplicate rows.  This cannot happen with partitioned
     506              :          * tables, however.
     507              :          */
     508          776 :         if (rte->inh && rte->relkind != RELKIND_PARTITIONED_TABLE)
     509            9 :             continue;
     510              : 
     511              :         /* Nothing to do unless this rel has multiple Vars in GROUP BY */
     512          767 :         relattnos = groupbyattnos[relid];
     513          767 :         if (bms_membership(relattnos) != BMS_MULTIPLE)
     514          290 :             continue;
     515              : 
     516          477 :         rel = root->simple_rel_array[relid];
     517              : 
     518              :         /*
     519              :          * Now check each index for this relation to see if there are any with
     520              :          * columns which are a proper subset of the grouping columns for this
     521              :          * relation.
     522              :          */
     523         1477 :         foreach_node(IndexOptInfo, index, rel->indexlist)
     524              :         {
     525              :             Bitmapset  *ind_attnos;
     526              :             bool        nulls_check_ok;
     527              : 
     528              :             /*
     529              :              * Skip any non-unique and deferrable indexes.  Predicate indexes
     530              :              * have not been checked yet, so we must skip those too as the
     531              :              * predOK check that's done later might fail.
     532              :              */
     533          523 :             if (!index->unique || !index->immediate || index->indpred != NIL)
     534          205 :                 continue;
     535              : 
     536              :             /* For simplicity, we currently don't support expression indexes */
     537          318 :             if (index->indexprs != NIL)
     538            0 :                 continue;
     539              : 
     540          318 :             ind_attnos = NULL;
     541          318 :             nulls_check_ok = true;
     542          802 :             for (int i = 0; i < index->nkeycolumns; i++)
     543              :             {
     544              :                 /*
     545              :                  * We must insist that the index columns are all defined NOT
     546              :                  * NULL otherwise duplicate NULLs could exist.  However, we
     547              :                  * can relax this check when the index is defined with NULLS
     548              :                  * NOT DISTINCT as there can only be 1 NULL row, therefore
     549              :                  * functional dependency on the unique columns is maintained,
     550              :                  * despite the NULL.
     551              :                  */
     552          487 :                 if (!index->nullsnotdistinct &&
     553          484 :                     !bms_is_member(index->indexkeys[i],
     554          484 :                                    rel->notnullattnums))
     555              :                 {
     556            3 :                     nulls_check_ok = false;
     557            3 :                     break;
     558              :                 }
     559              : 
     560              :                 ind_attnos =
     561          484 :                     bms_add_member(ind_attnos,
     562          484 :                                    index->indexkeys[i] -
     563              :                                    FirstLowInvalidHeapAttributeNumber);
     564              :             }
     565              : 
     566          318 :             if (!nulls_check_ok)
     567            3 :                 continue;
     568              : 
     569              :             /*
     570              :              * Skip any indexes where the indexed columns aren't a proper
     571              :              * subset of the GROUP BY.
     572              :              */
     573          315 :             if (bms_subset_compare(ind_attnos, relattnos) != BMS_SUBSET1)
     574          145 :                 continue;
     575              : 
     576              :             /*
     577              :              * Record the attribute numbers from the index with the fewest
     578              :              * columns.  This allows the largest number of columns to be
     579              :              * removed from the GROUP BY clause.  In the future, we may wish
     580              :              * to consider using the narrowest set of columns and looking at
     581              :              * pg_statistic.stawidth as it might be better to use an index
     582              :              * with, say two INT4s, rather than, say, one long varlena column.
     583              :              */
     584          170 :             if (index->nkeycolumns < best_nkeycolumns)
     585              :             {
     586          161 :                 best_keycolumns = ind_attnos;
     587          161 :                 best_nkeycolumns = index->nkeycolumns;
     588              :             }
     589              :         }
     590              : 
     591              :         /* Did we find a suitable index? */
     592          477 :         if (!bms_is_empty(best_keycolumns))
     593              :         {
     594              :             /*
     595              :              * To easily remember whether we've found anything to do, we don't
     596              :              * allocate the surplusvars[] array until we find something.
     597              :              */
     598          161 :             if (surplusvars == NULL)
     599          158 :                 surplusvars = palloc0_array(Bitmapset *, list_length(parse->rtable) + 1);
     600              : 
     601              :             /* Remember the attnos of the removable columns */
     602          161 :             surplusvars[relid] = bms_difference(relattnos, best_keycolumns);
     603              :         }
     604              :     }
     605              : 
     606              :     /*
     607              :      * If we found any surplus Vars, build a new GROUP BY clause without them.
     608              :      * (Note: this may leave some TLEs with unreferenced ressortgroupref
     609              :      * markings, but that's harmless.)
     610              :      */
     611          495 :     if (surplusvars != NULL)
     612              :     {
     613          158 :         List       *new_groupby = NIL;
     614              : 
     615          649 :         foreach(lc, root->processed_groupClause)
     616              :         {
     617          491 :             SortGroupClause *sgc = lfirst_node(SortGroupClause, lc);
     618          491 :             TargetEntry *tle = get_sortgroupclause_tle(sgc, parse->targetList);
     619          491 :             Var        *var = (Var *) tle->expr;
     620              : 
     621              :             /*
     622              :              * New list must include non-Vars, outer Vars, and anything not
     623              :              * marked as surplus.
     624              :              */
     625          491 :             if (!IsA(var, Var) ||
     626          491 :                 var->varlevelsup > 0 ||
     627          491 :                 !bms_is_member(var->varattno - FirstLowInvalidHeapAttributeNumber,
     628          491 :                                surplusvars[var->varno]))
     629          309 :                 new_groupby = lappend(new_groupby, sgc);
     630              :         }
     631              : 
     632          158 :         root->processed_groupClause = new_groupby;
     633              :     }
     634              : }
     635              : 
     636              : /*
     637              :  * setup_eager_aggregation
     638              :  *    Check if eager aggregation is applicable, and if so collect suitable
     639              :  *    aggregate expressions and grouping expressions in the query.
     640              :  */
     641              : void
     642       172436 : setup_eager_aggregation(PlannerInfo *root)
     643              : {
     644              :     /*
     645              :      * Don't apply eager aggregation if disabled by user.
     646              :      */
     647       172436 :     if (!enable_eager_aggregate)
     648          240 :         return;
     649              : 
     650              :     /*
     651              :      * Don't apply eager aggregation if there are no available GROUP BY
     652              :      * clauses.
     653              :      */
     654       172196 :     if (!root->processed_groupClause)
     655       169997 :         return;
     656              : 
     657              :     /*
     658              :      * For now we don't try to support grouping sets.
     659              :      */
     660         2199 :     if (root->parse->groupingSets)
     661          419 :         return;
     662              : 
     663              :     /*
     664              :      * For now we don't try to support DISTINCT or ORDER BY aggregates.
     665              :      */
     666         1780 :     if (root->numOrderedAggs > 0)
     667           96 :         return;
     668              : 
     669              :     /*
     670              :      * If there are any aggregates that do not support partial mode, or any
     671              :      * partial aggregates that are non-serializable, do not apply eager
     672              :      * aggregation.
     673              :      */
     674         1684 :     if (root->hasNonPartialAggs || root->hasNonSerialAggs)
     675           77 :         return;
     676              : 
     677              :     /*
     678              :      * We don't try to apply eager aggregation if there are set-returning
     679              :      * functions in targetlist.
     680              :      */
     681         1607 :     if (root->parse->hasTargetSRFs)
     682           42 :         return;
     683              : 
     684              :     /*
     685              :      * Eager aggregation only makes sense if there are multiple base rels in
     686              :      * the query.
     687              :      */
     688         1565 :     if (bms_membership(root->all_baserels) != BMS_MULTIPLE)
     689         1072 :         return;
     690              : 
     691              :     /*
     692              :      * Don't apply eager aggregation if any aggregate poses a risk of
     693              :      * excessive memory usage during partial aggregation.
     694              :      */
     695          493 :     if (is_partial_agg_memory_risky(root))
     696            1 :         return;
     697              : 
     698              :     /*
     699              :      * Collect aggregate expressions and plain Vars that appear in the
     700              :      * targetlist and havingQual.
     701              :      */
     702          492 :     create_agg_clause_infos(root);
     703              : 
     704              :     /*
     705              :      * If there are no suitable aggregate expressions, we cannot apply eager
     706              :      * aggregation.
     707              :      */
     708          492 :     if (root->agg_clause_list == NIL)
     709          163 :         return;
     710              : 
     711              :     /*
     712              :      * Collect grouping expressions that appear in grouping clauses.
     713              :      */
     714          329 :     create_grouping_expr_infos(root);
     715              : }
     716              : 
     717              : /*
     718              :  * is_partial_agg_memory_risky
     719              :  *    Check if any aggregate poses a risk of excessive memory usage during
     720              :  *    partial aggregation.
     721              :  *
     722              :  * We check if any aggregate has a negative aggtransspace value, which
     723              :  * indicates that its transition state data can grow unboundedly in size.
     724              :  * Applying eager aggregation in such cases risks high memory usage since
     725              :  * partial aggregation results might be stored in join hash tables or
     726              :  * materialized nodes.
     727              :  */
     728              : static bool
     729          493 : is_partial_agg_memory_risky(PlannerInfo *root)
     730              : {
     731              :     ListCell   *lc;
     732              : 
     733          951 :     foreach(lc, root->aggtransinfos)
     734              :     {
     735          459 :         AggTransInfo *transinfo = lfirst_node(AggTransInfo, lc);
     736              : 
     737          459 :         if (transinfo->aggtransspace < 0)
     738            1 :             return true;
     739              :     }
     740              : 
     741          492 :     return false;
     742              : }
     743              : 
     744              : /*
     745              :  * create_agg_clause_infos
     746              :  *    Search the targetlist and havingQual for Aggrefs and plain Vars, and
     747              :  *    create an AggClauseInfo for each Aggref node.
     748              :  */
     749              : static void
     750          492 : create_agg_clause_infos(PlannerInfo *root)
     751              : {
     752              :     List       *tlist_exprs;
     753          492 :     List       *agg_clause_list = NIL;
     754          492 :     List       *tlist_vars = NIL;
     755          492 :     Relids      aggregate_relids = NULL;
     756          492 :     bool        eager_agg_applicable = true;
     757              :     ListCell   *lc;
     758              : 
     759              :     Assert(root->agg_clause_list == NIL);
     760              :     Assert(root->tlist_vars == NIL);
     761              : 
     762          492 :     tlist_exprs = pull_var_clause((Node *) root->processed_tlist,
     763              :                                   PVC_INCLUDE_AGGREGATES |
     764              :                                   PVC_RECURSE_WINDOWFUNCS |
     765              :                                   PVC_RECURSE_PLACEHOLDERS);
     766              : 
     767              :     /*
     768              :      * Aggregates within the HAVING clause need to be processed in the same
     769              :      * way as those in the targetlist.  Note that HAVING can contain Aggrefs
     770              :      * but not WindowFuncs.
     771              :      */
     772          492 :     if (root->parse->havingQual != NULL)
     773              :     {
     774              :         List       *having_exprs;
     775              : 
     776           29 :         having_exprs = pull_var_clause((Node *) root->parse->havingQual,
     777              :                                        PVC_INCLUDE_AGGREGATES |
     778              :                                        PVC_RECURSE_PLACEHOLDERS);
     779           29 :         if (having_exprs != NIL)
     780              :         {
     781           29 :             tlist_exprs = list_concat(tlist_exprs, having_exprs);
     782           29 :             list_free(having_exprs);
     783              :         }
     784              :     }
     785              : 
     786         2184 :     foreach(lc, tlist_exprs)
     787              :     {
     788         1716 :         Expr       *expr = (Expr *) lfirst(lc);
     789              :         Aggref     *aggref;
     790              :         Relids      agg_eval_at;
     791              :         AggClauseInfo *ac_info;
     792              : 
     793              :         /* For now we don't try to support GROUPING() expressions */
     794         1716 :         if (IsA(expr, GroupingFunc))
     795              :         {
     796            0 :             eager_agg_applicable = false;
     797            0 :             break;
     798              :         }
     799              : 
     800              :         /* Collect plain Vars for future reference */
     801         1716 :         if (IsA(expr, Var))
     802              :         {
     803         1255 :             tlist_vars = list_append_unique(tlist_vars, expr);
     804         1255 :             continue;
     805              :         }
     806              : 
     807          461 :         aggref = castNode(Aggref, expr);
     808              : 
     809              :         Assert(aggref->aggorder == NIL);
     810              :         Assert(aggref->aggdistinct == NIL);
     811              : 
     812              :         /*
     813              :          * If there are any securityQuals, do not try to apply eager
     814              :          * aggregation if any non-leakproof aggregate functions are present.
     815              :          * This is overly strict, but for now...
     816              :          */
     817          461 :         if (root->qual_security_level > 0 &&
     818            0 :             !get_func_leakproof(aggref->aggfnoid))
     819              :         {
     820            0 :             eager_agg_applicable = false;
     821            0 :             break;
     822              :         }
     823              : 
     824          461 :         agg_eval_at = pull_varnos(root, (Node *) aggref);
     825              : 
     826              :         /*
     827              :          * If all base relations in the query are referenced by aggregate
     828              :          * functions, then eager aggregation is not applicable.
     829              :          */
     830          461 :         aggregate_relids = bms_add_members(aggregate_relids, agg_eval_at);
     831          461 :         if (bms_is_subset(root->all_baserels, aggregate_relids))
     832              :         {
     833           24 :             eager_agg_applicable = false;
     834           24 :             break;
     835              :         }
     836              : 
     837              :         /* OK, create the AggClauseInfo node */
     838          437 :         ac_info = makeNode(AggClauseInfo);
     839          437 :         ac_info->aggref = aggref;
     840          437 :         ac_info->agg_eval_at = agg_eval_at;
     841              : 
     842              :         /* ... and add it to the list */
     843          437 :         agg_clause_list = list_append_unique(agg_clause_list, ac_info);
     844              :     }
     845              : 
     846          492 :     list_free(tlist_exprs);
     847              : 
     848          492 :     if (eager_agg_applicable)
     849              :     {
     850          468 :         root->agg_clause_list = agg_clause_list;
     851          468 :         root->tlist_vars = tlist_vars;
     852              :     }
     853              :     else
     854              :     {
     855           24 :         list_free_deep(agg_clause_list);
     856           24 :         list_free(tlist_vars);
     857              :     }
     858          492 : }
     859              : 
     860              : /*
     861              :  * create_grouping_expr_infos
     862              :  *    Create a GroupingExprInfo for each expression usable as grouping key.
     863              :  *
     864              :  * If any grouping expression is not suitable, we will just return with
     865              :  * root->group_expr_list being NIL.
     866              :  */
     867              : static void
     868          329 : create_grouping_expr_infos(PlannerInfo *root)
     869              : {
     870          329 :     List       *exprs = NIL;
     871          329 :     List       *sortgrouprefs = NIL;
     872          329 :     List       *ecs = NIL;
     873              :     ListCell   *lc,
     874              :                *lc1,
     875              :                *lc2,
     876              :                *lc3;
     877              : 
     878              :     Assert(root->group_expr_list == NIL);
     879              : 
     880          653 :     foreach(lc, root->processed_groupClause)
     881              :     {
     882          357 :         SortGroupClause *sgc = lfirst_node(SortGroupClause, lc);
     883          357 :         TargetEntry *tle = get_sortgroupclause_tle(sgc, root->processed_tlist);
     884              :         TypeCacheEntry *tce;
     885              :         Oid         equalimageproc;
     886              : 
     887              :         Assert(tle->ressortgroupref > 0);
     888              : 
     889              :         /*
     890              :          * For now we only support plain Vars as grouping expressions.
     891              :          */
     892          357 :         if (!IsA(tle->expr, Var))
     893           33 :             return;
     894              : 
     895              :         /*
     896              :          * Eager aggregation is only possible if equality implies image
     897              :          * equality for each grouping key.  Otherwise, placing keys with
     898              :          * different byte images into the same group may result in the loss of
     899              :          * information that could be necessary to evaluate upper qual clauses.
     900              :          *
     901              :          * For instance, the NUMERIC data type is not supported, as values
     902              :          * that are considered equal by the equality operator (e.g., 0 and
     903              :          * 0.0) can have different scales.
     904              :          */
     905          327 :         tce = lookup_type_cache(exprType((Node *) tle->expr),
     906              :                                 TYPECACHE_BTREE_OPFAMILY);
     907          327 :         if (!OidIsValid(tce->btree_opf) ||
     908          327 :             !OidIsValid(tce->btree_opintype))
     909            0 :             return;
     910              : 
     911          327 :         equalimageproc = get_opfamily_proc(tce->btree_opf,
     912              :                                            tce->btree_opintype,
     913              :                                            tce->btree_opintype,
     914              :                                            BTEQUALIMAGE_PROC);
     915          327 :         if (!OidIsValid(equalimageproc) ||
     916          324 :             !DatumGetBool(OidFunctionCall1Coll(equalimageproc,
     917              :                                                tce->typcollation,
     918              :                                                ObjectIdGetDatum(tce->btree_opintype))))
     919            3 :             return;
     920              : 
     921          324 :         exprs = lappend(exprs, tle->expr);
     922          324 :         sortgrouprefs = lappend_int(sortgrouprefs, tle->ressortgroupref);
     923          324 :         ecs = lappend(ecs, get_eclass_for_sortgroupclause(root, sgc, tle->expr));
     924              :     }
     925              : 
     926              :     /*
     927              :      * Construct a GroupingExprInfo for each expression.
     928              :      */
     929          614 :     forthree(lc1, exprs, lc2, sortgrouprefs, lc3, ecs)
     930              :     {
     931          318 :         Expr       *expr = (Expr *) lfirst(lc1);
     932          318 :         int         sortgroupref = lfirst_int(lc2);
     933          318 :         EquivalenceClass *ec = (EquivalenceClass *) lfirst(lc3);
     934              :         GroupingExprInfo *ge_info;
     935              : 
     936          318 :         ge_info = makeNode(GroupingExprInfo);
     937          318 :         ge_info->expr = (Expr *) copyObject(expr);
     938          318 :         ge_info->sortgroupref = sortgroupref;
     939          318 :         ge_info->ec = ec;
     940              : 
     941          318 :         root->group_expr_list = lappend(root->group_expr_list, ge_info);
     942              :     }
     943              : }
     944              : 
     945              : /*
     946              :  * get_eclass_for_sortgroupclause
     947              :  *    Given a group clause and an expression, find an existing equivalence
     948              :  *    class that the expression is a member of; return NULL if none.
     949              :  */
     950              : static EquivalenceClass *
     951          324 : get_eclass_for_sortgroupclause(PlannerInfo *root, SortGroupClause *sgc,
     952              :                                Expr *expr)
     953              : {
     954              :     Oid         opfamily,
     955              :                 opcintype,
     956              :                 collation;
     957              :     CompareType cmptype;
     958              :     Oid         equality_op;
     959              :     List       *opfamilies;
     960              : 
     961              :     /* Punt if the group clause is not sortable */
     962          324 :     if (!OidIsValid(sgc->sortop))
     963            0 :         return NULL;
     964              : 
     965              :     /* Find the operator in pg_amop --- failure shouldn't happen */
     966          324 :     if (!get_ordering_op_properties(sgc->sortop,
     967              :                                     &opfamily, &opcintype, &cmptype))
     968            0 :         elog(ERROR, "operator %u is not a valid ordering operator",
     969              :              sgc->sortop);
     970              : 
     971              :     /* Because SortGroupClause doesn't carry collation, consult the expr */
     972          324 :     collation = exprCollation((Node *) expr);
     973              : 
     974              :     /*
     975              :      * EquivalenceClasses need to contain opfamily lists based on the family
     976              :      * membership of mergejoinable equality operators, which could belong to
     977              :      * more than one opfamily.  So we have to look up the opfamily's equality
     978              :      * operator and get its membership.
     979              :      */
     980          324 :     equality_op = get_opfamily_member_for_cmptype(opfamily,
     981              :                                                   opcintype,
     982              :                                                   opcintype,
     983              :                                                   COMPARE_EQ);
     984          324 :     if (!OidIsValid(equality_op))   /* shouldn't happen */
     985            0 :         elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
     986              :              COMPARE_EQ, opcintype, opcintype, opfamily);
     987          324 :     opfamilies = get_mergejoin_opfamilies(equality_op);
     988          324 :     if (!opfamilies)            /* certainly should find some */
     989            0 :         elog(ERROR, "could not find opfamilies for equality operator %u",
     990              :              equality_op);
     991              : 
     992              :     /* Now find a matching EquivalenceClass */
     993          324 :     return get_eclass_for_sort_expr(root, expr, opfamilies, opcintype,
     994              :                                     collation, sgc->tleSortGroupRef,
     995              :                                     NULL, false);
     996              : }
     997              : 
     998              : /*****************************************************************************
     999              :  *
    1000              :  *    LATERAL REFERENCES
    1001              :  *
    1002              :  *****************************************************************************/
    1003              : 
    1004              : /*
    1005              :  * find_lateral_references
    1006              :  *    For each LATERAL subquery, extract all its references to Vars and
    1007              :  *    PlaceHolderVars of the current query level, and make sure those values
    1008              :  *    will be available for evaluation of the subquery.
    1009              :  *
    1010              :  * While later planning steps ensure that the Var/PHV source rels are on the
    1011              :  * outside of nestloops relative to the LATERAL subquery, we also need to
    1012              :  * ensure that the Vars/PHVs propagate up to the nestloop join level; this
    1013              :  * means setting suitable where_needed values for them.
    1014              :  *
    1015              :  * Note that this only deals with lateral references in unflattened LATERAL
    1016              :  * subqueries.  When we flatten a LATERAL subquery, its lateral references
    1017              :  * become plain Vars in the parent query, but they may have to be wrapped in
    1018              :  * PlaceHolderVars if they need to be forced NULL by outer joins that don't
    1019              :  * also null the LATERAL subquery.  That's all handled elsewhere.
    1020              :  *
    1021              :  * This has to run before deconstruct_jointree, since it might result in
    1022              :  * creation of PlaceHolderInfos.
    1023              :  */
    1024              : void
    1025       172436 : find_lateral_references(PlannerInfo *root)
    1026              : {
    1027              :     Index       rti;
    1028              : 
    1029              :     /* We need do nothing if the query contains no LATERAL RTEs */
    1030       172436 :     if (!root->hasLateralRTEs)
    1031       167020 :         return;
    1032              : 
    1033              :     /*
    1034              :      * Examine all baserels (the rel array has been set up by now).
    1035              :      */
    1036        22977 :     for (rti = 1; rti < root->simple_rel_array_size; rti++)
    1037              :     {
    1038        17561 :         RelOptInfo *brel = root->simple_rel_array[rti];
    1039              : 
    1040              :         /* there may be empty slots corresponding to non-baserel RTEs */
    1041        17561 :         if (brel == NULL)
    1042         4497 :             continue;
    1043              : 
    1044              :         Assert(brel->relid == rti); /* sanity check on array */
    1045              : 
    1046              :         /*
    1047              :          * This bit is less obvious than it might look.  We ignore appendrel
    1048              :          * otherrels and consider only their parent baserels.  In a case where
    1049              :          * a LATERAL-containing UNION ALL subquery was pulled up, it is the
    1050              :          * otherrel that is actually going to be in the plan.  However, we
    1051              :          * want to mark all its lateral references as needed by the parent,
    1052              :          * because it is the parent's relid that will be used for join
    1053              :          * planning purposes.  And the parent's RTE will contain all the
    1054              :          * lateral references we need to know, since the pulled-up member is
    1055              :          * nothing but a copy of parts of the original RTE's subquery.  We
    1056              :          * could visit the parent's children instead and transform their
    1057              :          * references back to the parent's relid, but it would be much more
    1058              :          * complicated for no real gain.  (Important here is that the child
    1059              :          * members have not yet received any processing beyond being pulled
    1060              :          * up.)  Similarly, in appendrels created by inheritance expansion,
    1061              :          * it's sufficient to look at the parent relation.
    1062              :          */
    1063              : 
    1064              :         /* ignore RTEs that are "other rels" */
    1065        13064 :         if (brel->reloptkind != RELOPT_BASEREL)
    1066            0 :             continue;
    1067              : 
    1068        13064 :         extract_lateral_references(root, brel, rti);
    1069              :     }
    1070              : }
    1071              : 
    1072              : static void
    1073        13064 : extract_lateral_references(PlannerInfo *root, RelOptInfo *brel, Index rtindex)
    1074              : {
    1075        13064 :     RangeTblEntry *rte = root->simple_rte_array[rtindex];
    1076              :     List       *vars;
    1077              :     List       *newvars;
    1078              :     Relids      where_needed;
    1079              :     ListCell   *lc;
    1080              : 
    1081              :     /* No cross-references are possible if it's not LATERAL */
    1082        13064 :     if (!rte->lateral)
    1083         7969 :         return;
    1084              : 
    1085              :     /* Fetch the appropriate variables */
    1086         5095 :     if (rte->rtekind == RTE_RELATION)
    1087           18 :         vars = pull_vars_of_level((Node *) rte->tablesample, 0);
    1088         5077 :     else if (rte->rtekind == RTE_SUBQUERY)
    1089          594 :         vars = pull_vars_of_level((Node *) rte->subquery, 1);
    1090         4483 :     else if (rte->rtekind == RTE_FUNCTION)
    1091         4330 :         vars = pull_vars_of_level((Node *) rte->functions, 0);
    1092          153 :     else if (rte->rtekind == RTE_TABLEFUNC)
    1093          117 :         vars = pull_vars_of_level((Node *) rte->tablefunc, 0);
    1094           36 :     else if (rte->rtekind == RTE_VALUES)
    1095           36 :         vars = pull_vars_of_level((Node *) rte->values_lists, 0);
    1096              :     else
    1097              :     {
    1098              :         Assert(false);
    1099            0 :         return;                 /* keep compiler quiet */
    1100              :     }
    1101              : 
    1102         5095 :     if (vars == NIL)
    1103           50 :         return;                 /* nothing to do */
    1104              : 
    1105              :     /* Copy each Var (or PlaceHolderVar) and adjust it to match our level */
    1106         5045 :     newvars = NIL;
    1107        10572 :     foreach(lc, vars)
    1108              :     {
    1109         5527 :         Node       *node = (Node *) lfirst(lc);
    1110              : 
    1111         5527 :         node = copyObject(node);
    1112         5527 :         if (IsA(node, Var))
    1113              :         {
    1114         5464 :             Var        *var = (Var *) node;
    1115              : 
    1116              :             /* Adjustment is easy since it's just one node */
    1117         5464 :             var->varlevelsup = 0;
    1118              :         }
    1119           63 :         else if (IsA(node, PlaceHolderVar))
    1120              :         {
    1121           63 :             PlaceHolderVar *phv = (PlaceHolderVar *) node;
    1122           63 :             int         levelsup = phv->phlevelsup;
    1123              : 
    1124              :             /* Have to work harder to adjust the contained expression too */
    1125           63 :             if (levelsup != 0)
    1126           45 :                 IncrementVarSublevelsUp(node, -levelsup, 0);
    1127              : 
    1128              :             /*
    1129              :              * If we pulled the PHV out of a subquery RTE, its expression
    1130              :              * needs to be preprocessed.  subquery_planner() already did this
    1131              :              * for level-zero PHVs in function and values RTEs, though.
    1132              :              */
    1133           63 :             if (levelsup > 0)
    1134           45 :                 phv->phexpr = preprocess_phv_expression(root, phv->phexpr);
    1135              :         }
    1136              :         else
    1137              :             Assert(false);
    1138         5527 :         newvars = lappend(newvars, node);
    1139              :     }
    1140              : 
    1141         5045 :     list_free(vars);
    1142              : 
    1143              :     /*
    1144              :      * We mark the Vars as being "needed" at the LATERAL RTE.  This is a bit
    1145              :      * of a cheat: a more formal approach would be to mark each one as needed
    1146              :      * at the join of the LATERAL RTE with its source RTE.  But it will work,
    1147              :      * and it's much less tedious than computing a separate where_needed for
    1148              :      * each Var.
    1149              :      */
    1150         5045 :     where_needed = bms_make_singleton(rtindex);
    1151              : 
    1152              :     /*
    1153              :      * Push Vars into their source relations' targetlists, and PHVs into
    1154              :      * root->placeholder_list.
    1155              :      */
    1156         5045 :     add_vars_to_targetlist(root, newvars, where_needed);
    1157              : 
    1158              :     /*
    1159              :      * Remember the lateral references for rebuild_lateral_attr_needed and
    1160              :      * create_lateral_join_info.
    1161              :      */
    1162         5045 :     brel->lateral_vars = newvars;
    1163              : }
    1164              : 
    1165              : /*
    1166              :  * rebuild_lateral_attr_needed
    1167              :  *    Put back attr_needed bits for Vars/PHVs needed for lateral references.
    1168              :  *
    1169              :  * This is used to rebuild attr_needed/ph_needed sets after removal of a
    1170              :  * useless outer join.  It should match what find_lateral_references did,
    1171              :  * except that we call add_vars_to_attr_needed not add_vars_to_targetlist.
    1172              :  */
    1173              : void
    1174         6260 : rebuild_lateral_attr_needed(PlannerInfo *root)
    1175              : {
    1176              :     Index       rti;
    1177              : 
    1178              :     /* We need do nothing if the query contains no LATERAL RTEs */
    1179         6260 :     if (!root->hasLateralRTEs)
    1180         5704 :         return;
    1181              : 
    1182              :     /* Examine the same baserels that find_lateral_references did */
    1183         6122 :     for (rti = 1; rti < root->simple_rel_array_size; rti++)
    1184              :     {
    1185         5566 :         RelOptInfo *brel = root->simple_rel_array[rti];
    1186              :         Relids      where_needed;
    1187              : 
    1188         5566 :         if (brel == NULL)
    1189         3582 :             continue;
    1190         1984 :         if (brel->reloptkind != RELOPT_BASEREL)
    1191            0 :             continue;
    1192              : 
    1193              :         /*
    1194              :          * We don't need to repeat all of extract_lateral_references, since it
    1195              :          * kindly saved the extracted Vars/PHVs in lateral_vars.
    1196              :          */
    1197         1984 :         if (brel->lateral_vars == NIL)
    1198         1614 :             continue;
    1199              : 
    1200          370 :         where_needed = bms_make_singleton(rti);
    1201              : 
    1202          370 :         add_vars_to_attr_needed(root, brel->lateral_vars, where_needed);
    1203              :     }
    1204              : }
    1205              : 
    1206              : /*
    1207              :  * create_lateral_join_info
    1208              :  *    Fill in the per-base-relation direct_lateral_relids, lateral_relids
    1209              :  *    and lateral_referencers sets.
    1210              :  */
    1211              : void
    1212       172436 : create_lateral_join_info(PlannerInfo *root)
    1213              : {
    1214       172436 :     bool        found_laterals = false;
    1215              :     Index       rti;
    1216              :     ListCell   *lc;
    1217              : 
    1218              :     /* We need do nothing if the query contains no LATERAL RTEs */
    1219       172436 :     if (!root->hasLateralRTEs)
    1220       167020 :         return;
    1221              : 
    1222              :     /* We'll need to have the ph_eval_at values for PlaceHolderVars */
    1223              :     Assert(root->placeholdersFrozen);
    1224              : 
    1225              :     /*
    1226              :      * Examine all baserels (the rel array has been set up by now).
    1227              :      */
    1228        22977 :     for (rti = 1; rti < root->simple_rel_array_size; rti++)
    1229              :     {
    1230        17561 :         RelOptInfo *brel = root->simple_rel_array[rti];
    1231              :         Relids      lateral_relids;
    1232              : 
    1233              :         /* there may be empty slots corresponding to non-baserel RTEs */
    1234        17561 :         if (brel == NULL)
    1235         5053 :             continue;
    1236              : 
    1237              :         Assert(brel->relid == rti); /* sanity check on array */
    1238              : 
    1239              :         /* ignore RTEs that are "other rels" */
    1240        12508 :         if (brel->reloptkind != RELOPT_BASEREL)
    1241            0 :             continue;
    1242              : 
    1243        12508 :         lateral_relids = NULL;
    1244              : 
    1245              :         /* consider each laterally-referenced Var or PHV */
    1246        17924 :         foreach(lc, brel->lateral_vars)
    1247              :         {
    1248         5416 :             Node       *node = (Node *) lfirst(lc);
    1249              : 
    1250         5416 :             if (IsA(node, Var))
    1251              :             {
    1252         5353 :                 Var        *var = (Var *) node;
    1253              : 
    1254         5353 :                 found_laterals = true;
    1255         5353 :                 lateral_relids = bms_add_member(lateral_relids,
    1256              :                                                 var->varno);
    1257              :             }
    1258           63 :             else if (IsA(node, PlaceHolderVar))
    1259              :             {
    1260           63 :                 PlaceHolderVar *phv = (PlaceHolderVar *) node;
    1261           63 :                 PlaceHolderInfo *phinfo = find_placeholder_info(root, phv);
    1262              : 
    1263           63 :                 found_laterals = true;
    1264           63 :                 lateral_relids = bms_add_members(lateral_relids,
    1265           63 :                                                  phinfo->ph_eval_at);
    1266              :             }
    1267              :             else
    1268              :                 Assert(false);
    1269              :         }
    1270              : 
    1271              :         /* We now have all the simple lateral refs from this rel */
    1272        12508 :         brel->direct_lateral_relids = lateral_relids;
    1273        12508 :         brel->lateral_relids = bms_copy(lateral_relids);
    1274              :     }
    1275              : 
    1276              :     /*
    1277              :      * Now check for lateral references within PlaceHolderVars, and mark their
    1278              :      * eval_at rels as having lateral references to the source rels.
    1279              :      *
    1280              :      * For a PHV that is due to be evaluated at a baserel, mark its source(s)
    1281              :      * as direct lateral dependencies of the baserel (adding onto the ones
    1282              :      * recorded above).  If it's due to be evaluated at a join, mark its
    1283              :      * source(s) as indirect lateral dependencies of each baserel in the join,
    1284              :      * ie put them into lateral_relids but not direct_lateral_relids.  This is
    1285              :      * appropriate because we can't put any such baserel on the outside of a
    1286              :      * join to one of the PHV's lateral dependencies, but on the other hand we
    1287              :      * also can't yet join it directly to the dependency.
    1288              :      */
    1289         5711 :     foreach(lc, root->placeholder_list)
    1290              :     {
    1291          295 :         PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc);
    1292          295 :         Relids      eval_at = phinfo->ph_eval_at;
    1293              :         Relids      lateral_refs;
    1294              :         int         varno;
    1295              : 
    1296          295 :         if (phinfo->ph_lateral == NULL)
    1297          164 :             continue;           /* PHV is uninteresting if no lateral refs */
    1298              : 
    1299          131 :         found_laterals = true;
    1300              : 
    1301              :         /*
    1302              :          * Include only baserels not outer joins in the evaluation sites'
    1303              :          * lateral relids.  This avoids problems when outer join order gets
    1304              :          * rearranged, and it should still ensure that the lateral values are
    1305              :          * available when needed.
    1306              :          */
    1307          131 :         lateral_refs = bms_intersect(phinfo->ph_lateral, root->all_baserels);
    1308              :         Assert(!bms_is_empty(lateral_refs));
    1309              : 
    1310          131 :         if (bms_get_singleton_member(eval_at, &varno))
    1311              :         {
    1312              :             /* Evaluation site is a baserel */
    1313           98 :             RelOptInfo *brel = find_base_rel(root, varno);
    1314              : 
    1315           98 :             brel->direct_lateral_relids =
    1316           98 :                 bms_add_members(brel->direct_lateral_relids,
    1317              :                                 lateral_refs);
    1318           98 :             brel->lateral_relids =
    1319           98 :                 bms_add_members(brel->lateral_relids,
    1320              :                                 lateral_refs);
    1321              :         }
    1322              :         else
    1323              :         {
    1324              :             /* Evaluation site is a join */
    1325           33 :             varno = -1;
    1326           99 :             while ((varno = bms_next_member(eval_at, varno)) >= 0)
    1327              :             {
    1328           66 :                 RelOptInfo *brel = find_base_rel_ignore_join(root, varno);
    1329              : 
    1330           66 :                 if (brel == NULL)
    1331            0 :                     continue;   /* ignore outer joins in eval_at */
    1332           66 :                 brel->lateral_relids = bms_add_members(brel->lateral_relids,
    1333              :                                                        lateral_refs);
    1334              :             }
    1335              :         }
    1336              :     }
    1337              : 
    1338              :     /*
    1339              :      * If we found no actual lateral references, we're done; but reset the
    1340              :      * hasLateralRTEs flag to avoid useless work later.
    1341              :      */
    1342         5416 :     if (!found_laterals)
    1343              :     {
    1344          396 :         root->hasLateralRTEs = false;
    1345          396 :         return;
    1346              :     }
    1347              : 
    1348              :     /*
    1349              :      * Calculate the transitive closure of the lateral_relids sets, so that
    1350              :      * they describe both direct and indirect lateral references.  If relation
    1351              :      * X references Y laterally, and Y references Z laterally, then we will
    1352              :      * have to scan X on the inside of a nestloop with Z, so for all intents
    1353              :      * and purposes X is laterally dependent on Z too.
    1354              :      *
    1355              :      * This code is essentially Warshall's algorithm for transitive closure.
    1356              :      * The outer loop considers each baserel, and propagates its lateral
    1357              :      * dependencies to those baserels that have a lateral dependency on it.
    1358              :      */
    1359        19856 :     for (rti = 1; rti < root->simple_rel_array_size; rti++)
    1360              :     {
    1361        14836 :         RelOptInfo *brel = root->simple_rel_array[rti];
    1362              :         Relids      outer_lateral_relids;
    1363              :         Index       rti2;
    1364              : 
    1365        14836 :         if (brel == NULL || brel->reloptkind != RELOPT_BASEREL)
    1366         3196 :             continue;
    1367              : 
    1368              :         /* need not consider baserel further if it has no lateral refs */
    1369        11640 :         outer_lateral_relids = brel->lateral_relids;
    1370        11640 :         if (outer_lateral_relids == NULL)
    1371         6542 :             continue;
    1372              : 
    1373              :         /* else scan all baserels */
    1374        20426 :         for (rti2 = 1; rti2 < root->simple_rel_array_size; rti2++)
    1375              :         {
    1376        15328 :             RelOptInfo *brel2 = root->simple_rel_array[rti2];
    1377              : 
    1378        15328 :             if (brel2 == NULL || brel2->reloptkind != RELOPT_BASEREL)
    1379         3403 :                 continue;
    1380              : 
    1381              :             /* if brel2 has lateral ref to brel, propagate brel's refs */
    1382        11925 :             if (bms_is_member(rti, brel2->lateral_relids))
    1383           36 :                 brel2->lateral_relids = bms_add_members(brel2->lateral_relids,
    1384              :                                                         outer_lateral_relids);
    1385              :         }
    1386              :     }
    1387              : 
    1388              :     /*
    1389              :      * Now that we've identified all lateral references, mark each baserel
    1390              :      * with the set of relids of rels that reference it laterally (possibly
    1391              :      * indirectly) --- that is, the inverse mapping of lateral_relids.
    1392              :      */
    1393        19856 :     for (rti = 1; rti < root->simple_rel_array_size; rti++)
    1394              :     {
    1395        14836 :         RelOptInfo *brel = root->simple_rel_array[rti];
    1396              :         Relids      lateral_relids;
    1397              :         int         rti2;
    1398              : 
    1399        14836 :         if (brel == NULL || brel->reloptkind != RELOPT_BASEREL)
    1400         3196 :             continue;
    1401              : 
    1402              :         /* Nothing to do at rels with no lateral refs */
    1403        11640 :         lateral_relids = brel->lateral_relids;
    1404        11640 :         if (bms_is_empty(lateral_relids))
    1405         6542 :             continue;
    1406              : 
    1407              :         /* No rel should have a lateral dependency on itself */
    1408              :         Assert(!bms_is_member(rti, lateral_relids));
    1409              : 
    1410              :         /* Mark this rel's referencees */
    1411         5098 :         rti2 = -1;
    1412        10342 :         while ((rti2 = bms_next_member(lateral_relids, rti2)) >= 0)
    1413              :         {
    1414         5244 :             RelOptInfo *brel2 = root->simple_rel_array[rti2];
    1415              : 
    1416         5244 :             if (brel2 == NULL)
    1417            6 :                 continue;       /* must be an OJ */
    1418              : 
    1419              :             Assert(brel2->reloptkind == RELOPT_BASEREL);
    1420         5238 :             brel2->lateral_referencers =
    1421         5238 :                 bms_add_member(brel2->lateral_referencers, rti);
    1422              :         }
    1423              :     }
    1424              : }
    1425              : 
    1426              : 
    1427              : /*****************************************************************************
    1428              :  *
    1429              :  *    JOIN TREE PROCESSING
    1430              :  *
    1431              :  *****************************************************************************/
    1432              : 
    1433              : /*
    1434              :  * deconstruct_jointree
    1435              :  *    Recursively scan the query's join tree for WHERE and JOIN/ON qual
    1436              :  *    clauses, and add these to the appropriate restrictinfo and joininfo
    1437              :  *    lists belonging to base RelOptInfos.  Also, add SpecialJoinInfo nodes
    1438              :  *    to root->join_info_list for any outer joins appearing in the query tree.
    1439              :  *    Return a "joinlist" data structure showing the join order decisions
    1440              :  *    that need to be made by make_one_rel().
    1441              :  *
    1442              :  * The "joinlist" result is a list of items that are either RangeTblRef
    1443              :  * jointree nodes or sub-joinlists.  All the items at the same level of
    1444              :  * joinlist must be joined in an order to be determined by make_one_rel()
    1445              :  * (note that legal orders may be constrained by SpecialJoinInfo nodes).
    1446              :  * A sub-joinlist represents a subproblem to be planned separately. Currently
    1447              :  * sub-joinlists arise only from FULL OUTER JOIN or when collapsing of
    1448              :  * subproblems is stopped by join_collapse_limit or from_collapse_limit.
    1449              :  */
    1450              : List *
    1451       172436 : deconstruct_jointree(PlannerInfo *root)
    1452              : {
    1453              :     List       *result;
    1454              :     JoinDomain *top_jdomain;
    1455       172436 :     List       *item_list = NIL;
    1456              :     ListCell   *lc;
    1457              : 
    1458              :     /*
    1459              :      * After this point, no more PlaceHolderInfos may be made, because
    1460              :      * make_outerjoininfo requires all active placeholders to be present in
    1461              :      * root->placeholder_list while we crawl up the join tree.
    1462              :      */
    1463       172436 :     root->placeholdersFrozen = true;
    1464              : 
    1465              :     /* Fetch the already-created top-level join domain for the query */
    1466       172436 :     top_jdomain = linitial_node(JoinDomain, root->join_domains);
    1467       172436 :     top_jdomain->jd_relids = NULL;   /* filled during deconstruct_recurse */
    1468              : 
    1469              :     /* Start recursion at top of jointree */
    1470              :     Assert(root->parse->jointree != NULL &&
    1471              :            IsA(root->parse->jointree, FromExpr));
    1472              : 
    1473              :     /* These are filled as we scan the jointree */
    1474       172436 :     root->all_baserels = NULL;
    1475       172436 :     root->outer_join_rels = NULL;
    1476              : 
    1477              :     /* Perform the initial scan of the jointree */
    1478       172436 :     result = deconstruct_recurse(root, (Node *) root->parse->jointree,
    1479              :                                  top_jdomain, NULL,
    1480              :                                  &item_list);
    1481              : 
    1482              :     /* Now we can form the value of all_query_rels, too */
    1483       172436 :     root->all_query_rels = bms_union(root->all_baserels, root->outer_join_rels);
    1484              : 
    1485              :     /* ... which should match what we computed for the top join domain */
    1486              :     Assert(bms_equal(root->all_query_rels, top_jdomain->jd_relids));
    1487              : 
    1488              :     /* Now scan all the jointree nodes again, and distribute quals */
    1489       653231 :     foreach(lc, item_list)
    1490              :     {
    1491       480795 :         JoinTreeItem *jtitem = (JoinTreeItem *) lfirst(lc);
    1492              : 
    1493       480795 :         deconstruct_distribute(root, jtitem);
    1494              :     }
    1495              : 
    1496              :     /*
    1497              :      * If there were any special joins then we may have some postponed LEFT
    1498              :      * JOIN clauses to deal with.
    1499              :      */
    1500       172436 :     if (root->join_info_list)
    1501              :     {
    1502       134451 :         foreach(lc, item_list)
    1503              :         {
    1504       114185 :             JoinTreeItem *jtitem = (JoinTreeItem *) lfirst(lc);
    1505              : 
    1506       114185 :             if (jtitem->oj_joinclauses != NIL)
    1507        21981 :                 deconstruct_distribute_oj_quals(root, item_list, jtitem);
    1508              :         }
    1509              :     }
    1510              : 
    1511              :     /* Don't need the JoinTreeItems any more */
    1512       172436 :     list_free_deep(item_list);
    1513              : 
    1514       172436 :     return result;
    1515              : }
    1516              : 
    1517              : /*
    1518              :  * deconstruct_recurse
    1519              :  *    One recursion level of deconstruct_jointree's initial jointree scan.
    1520              :  *
    1521              :  * jtnode is the jointree node to examine, and parent_domain is the
    1522              :  * enclosing join domain.  (We must add all base+OJ relids appearing
    1523              :  * here or below to parent_domain.)  parent_jtitem is the JoinTreeItem
    1524              :  * for the parent jointree node, or NULL at the top of the recursion.
    1525              :  *
    1526              :  * item_list is an in/out parameter: we add a JoinTreeItem struct to
    1527              :  * that list for each jointree node, in depth-first traversal order.
    1528              :  * (Hence, after each call, the last list item corresponds to its jtnode.)
    1529              :  *
    1530              :  * Return value is the appropriate joinlist for this jointree node.
    1531              :  */
    1532              : static List *
    1533       480795 : deconstruct_recurse(PlannerInfo *root, Node *jtnode,
    1534              :                     JoinDomain *parent_domain,
    1535              :                     JoinTreeItem *parent_jtitem,
    1536              :                     List **item_list)
    1537              : {
    1538              :     List       *joinlist;
    1539              :     JoinTreeItem *jtitem;
    1540              : 
    1541              :     Assert(jtnode != NULL);
    1542              : 
    1543              :     /* Make the new JoinTreeItem, but don't add it to item_list yet */
    1544       480795 :     jtitem = palloc0_object(JoinTreeItem);
    1545       480795 :     jtitem->jtnode = jtnode;
    1546       480795 :     jtitem->jti_parent = parent_jtitem;
    1547              : 
    1548       480795 :     if (IsA(jtnode, RangeTblRef))
    1549              :     {
    1550       249977 :         int         varno = ((RangeTblRef *) jtnode)->rtindex;
    1551              : 
    1552              :         /* Fill all_baserels as we encounter baserel jointree nodes */
    1553       249977 :         root->all_baserels = bms_add_member(root->all_baserels, varno);
    1554              :         /* This node belongs to parent_domain */
    1555       249977 :         jtitem->jdomain = parent_domain;
    1556       249977 :         parent_domain->jd_relids = bms_add_member(parent_domain->jd_relids,
    1557              :                                                   varno);
    1558              :         /* qualscope is just the one RTE */
    1559       249977 :         jtitem->qualscope = bms_make_singleton(varno);
    1560              :         /* A single baserel does not create an inner join */
    1561       249977 :         jtitem->inner_join_rels = NULL;
    1562       249977 :         joinlist = list_make1(jtnode);
    1563              :     }
    1564       230818 :     else if (IsA(jtnode, FromExpr))
    1565              :     {
    1566       178765 :         FromExpr   *f = (FromExpr *) jtnode;
    1567              :         int         remaining;
    1568              :         ListCell   *l;
    1569              : 
    1570              :         /* This node belongs to parent_domain, as do its children */
    1571       178765 :         jtitem->jdomain = parent_domain;
    1572              : 
    1573              :         /*
    1574              :          * Recurse to handle child nodes, and compute output joinlist.  We
    1575              :          * collapse subproblems into a single joinlist whenever the resulting
    1576              :          * joinlist wouldn't exceed from_collapse_limit members.  Also, always
    1577              :          * collapse one-element subproblems, since that won't lengthen the
    1578              :          * joinlist anyway.
    1579              :          */
    1580       178765 :         jtitem->qualscope = NULL;
    1581       178765 :         jtitem->inner_join_rels = NULL;
    1582       178765 :         joinlist = NIL;
    1583       178765 :         remaining = list_length(f->fromlist);
    1584       383018 :         foreach(l, f->fromlist)
    1585              :         {
    1586              :             JoinTreeItem *sub_item;
    1587              :             List       *sub_joinlist;
    1588              :             int         sub_members;
    1589              : 
    1590       204253 :             sub_joinlist = deconstruct_recurse(root, lfirst(l),
    1591              :                                                parent_domain,
    1592              :                                                jtitem,
    1593              :                                                item_list);
    1594       204253 :             sub_item = (JoinTreeItem *) llast(*item_list);
    1595       408506 :             jtitem->qualscope = bms_add_members(jtitem->qualscope,
    1596       204253 :                                                 sub_item->qualscope);
    1597       204253 :             jtitem->inner_join_rels = sub_item->inner_join_rels;
    1598       204253 :             sub_members = list_length(sub_joinlist);
    1599       204253 :             remaining--;
    1600       204253 :             if (sub_members <= 1 ||
    1601        33428 :                 list_length(joinlist) + sub_members + remaining <= from_collapse_limit)
    1602       204247 :                 joinlist = list_concat(joinlist, sub_joinlist);
    1603              :             else
    1604            6 :                 joinlist = lappend(joinlist, sub_joinlist);
    1605              :         }
    1606              : 
    1607              :         /*
    1608              :          * A FROM with more than one list element is an inner join subsuming
    1609              :          * all below it, so we should report inner_join_rels = qualscope. If
    1610              :          * there was exactly one element, we should (and already did) report
    1611              :          * whatever its inner_join_rels were.  If there were no elements (is
    1612              :          * that still possible?) the initialization before the loop fixed it.
    1613              :          */
    1614       178765 :         if (list_length(f->fromlist) > 1)
    1615        22979 :             jtitem->inner_join_rels = jtitem->qualscope;
    1616              :     }
    1617        52053 :     else if (IsA(jtnode, JoinExpr))
    1618              :     {
    1619        52053 :         JoinExpr   *j = (JoinExpr *) jtnode;
    1620              :         JoinDomain *child_domain,
    1621              :                    *fj_domain;
    1622              :         JoinTreeItem *left_item,
    1623              :                    *right_item;
    1624              :         List       *leftjoinlist,
    1625              :                    *rightjoinlist;
    1626              : 
    1627        52053 :         switch (j->jointype)
    1628              :         {
    1629        24139 :             case JOIN_INNER:
    1630              :                 /* This node belongs to parent_domain, as do its children */
    1631        24139 :                 jtitem->jdomain = parent_domain;
    1632              :                 /* Recurse */
    1633        24139 :                 leftjoinlist = deconstruct_recurse(root, j->larg,
    1634              :                                                    parent_domain,
    1635              :                                                    jtitem,
    1636              :                                                    item_list);
    1637        24139 :                 left_item = (JoinTreeItem *) llast(*item_list);
    1638        24139 :                 rightjoinlist = deconstruct_recurse(root, j->rarg,
    1639              :                                                     parent_domain,
    1640              :                                                     jtitem,
    1641              :                                                     item_list);
    1642        24139 :                 right_item = (JoinTreeItem *) llast(*item_list);
    1643              :                 /* Compute qualscope etc */
    1644        48278 :                 jtitem->qualscope = bms_union(left_item->qualscope,
    1645        24139 :                                               right_item->qualscope);
    1646        24139 :                 jtitem->inner_join_rels = jtitem->qualscope;
    1647        24139 :                 jtitem->left_rels = left_item->qualscope;
    1648        24139 :                 jtitem->right_rels = right_item->qualscope;
    1649              :                 /* Inner join adds no restrictions for quals */
    1650        24139 :                 jtitem->nonnullable_rels = NULL;
    1651        24139 :                 break;
    1652        24826 :             case JOIN_LEFT:
    1653              :             case JOIN_ANTI:
    1654              :                 /* Make new join domain for my quals and the RHS */
    1655        24826 :                 child_domain = makeNode(JoinDomain);
    1656        24826 :                 child_domain->jd_relids = NULL; /* filled by recursion */
    1657        24826 :                 root->join_domains = lappend(root->join_domains, child_domain);
    1658        24826 :                 jtitem->jdomain = child_domain;
    1659              :                 /* Recurse */
    1660        24826 :                 leftjoinlist = deconstruct_recurse(root, j->larg,
    1661              :                                                    parent_domain,
    1662              :                                                    jtitem,
    1663              :                                                    item_list);
    1664        24826 :                 left_item = (JoinTreeItem *) llast(*item_list);
    1665        24826 :                 rightjoinlist = deconstruct_recurse(root, j->rarg,
    1666              :                                                     child_domain,
    1667              :                                                     jtitem,
    1668              :                                                     item_list);
    1669        24826 :                 right_item = (JoinTreeItem *) llast(*item_list);
    1670              :                 /* Compute join domain contents, qualscope etc */
    1671        24826 :                 parent_domain->jd_relids =
    1672        24826 :                     bms_add_members(parent_domain->jd_relids,
    1673        24826 :                                     child_domain->jd_relids);
    1674        49652 :                 jtitem->qualscope = bms_union(left_item->qualscope,
    1675        24826 :                                               right_item->qualscope);
    1676              :                 /* caution: ANTI join derived from SEMI will lack rtindex */
    1677        24826 :                 if (j->rtindex != 0)
    1678              :                 {
    1679        23429 :                     parent_domain->jd_relids =
    1680        23429 :                         bms_add_member(parent_domain->jd_relids,
    1681              :                                        j->rtindex);
    1682        23429 :                     jtitem->qualscope = bms_add_member(jtitem->qualscope,
    1683              :                                                        j->rtindex);
    1684        23429 :                     root->outer_join_rels = bms_add_member(root->outer_join_rels,
    1685              :                                                            j->rtindex);
    1686        23429 :                     mark_rels_nulled_by_join(root, j->rtindex,
    1687              :                                              right_item->qualscope);
    1688              :                 }
    1689        49652 :                 jtitem->inner_join_rels = bms_union(left_item->inner_join_rels,
    1690        24826 :                                                     right_item->inner_join_rels);
    1691        24826 :                 jtitem->left_rels = left_item->qualscope;
    1692        24826 :                 jtitem->right_rels = right_item->qualscope;
    1693        24826 :                 jtitem->nonnullable_rels = left_item->qualscope;
    1694        24826 :                 break;
    1695         2571 :             case JOIN_SEMI:
    1696              :                 /* This node belongs to parent_domain, as do its children */
    1697         2571 :                 jtitem->jdomain = parent_domain;
    1698              :                 /* Recurse */
    1699         2571 :                 leftjoinlist = deconstruct_recurse(root, j->larg,
    1700              :                                                    parent_domain,
    1701              :                                                    jtitem,
    1702              :                                                    item_list);
    1703         2571 :                 left_item = (JoinTreeItem *) llast(*item_list);
    1704         2571 :                 rightjoinlist = deconstruct_recurse(root, j->rarg,
    1705              :                                                     parent_domain,
    1706              :                                                     jtitem,
    1707              :                                                     item_list);
    1708         2571 :                 right_item = (JoinTreeItem *) llast(*item_list);
    1709              :                 /* Compute qualscope etc */
    1710         5142 :                 jtitem->qualscope = bms_union(left_item->qualscope,
    1711         2571 :                                               right_item->qualscope);
    1712              :                 /* SEMI join never has rtindex, so don't add to anything */
    1713              :                 Assert(j->rtindex == 0);
    1714         5142 :                 jtitem->inner_join_rels = bms_union(left_item->inner_join_rels,
    1715         2571 :                                                     right_item->inner_join_rels);
    1716         2571 :                 jtitem->left_rels = left_item->qualscope;
    1717         2571 :                 jtitem->right_rels = right_item->qualscope;
    1718              :                 /* Semi join adds no restrictions for quals */
    1719         2571 :                 jtitem->nonnullable_rels = NULL;
    1720         2571 :                 break;
    1721          517 :             case JOIN_FULL:
    1722              :                 /* The FULL JOIN's quals need their very own domain */
    1723          517 :                 fj_domain = makeNode(JoinDomain);
    1724          517 :                 root->join_domains = lappend(root->join_domains, fj_domain);
    1725          517 :                 jtitem->jdomain = fj_domain;
    1726              :                 /* Recurse, giving each side its own join domain */
    1727          517 :                 child_domain = makeNode(JoinDomain);
    1728          517 :                 child_domain->jd_relids = NULL; /* filled by recursion */
    1729          517 :                 root->join_domains = lappend(root->join_domains, child_domain);
    1730          517 :                 leftjoinlist = deconstruct_recurse(root, j->larg,
    1731              :                                                    child_domain,
    1732              :                                                    jtitem,
    1733              :                                                    item_list);
    1734          517 :                 left_item = (JoinTreeItem *) llast(*item_list);
    1735          517 :                 fj_domain->jd_relids = bms_copy(child_domain->jd_relids);
    1736          517 :                 child_domain = makeNode(JoinDomain);
    1737          517 :                 child_domain->jd_relids = NULL; /* filled by recursion */
    1738          517 :                 root->join_domains = lappend(root->join_domains, child_domain);
    1739          517 :                 rightjoinlist = deconstruct_recurse(root, j->rarg,
    1740              :                                                     child_domain,
    1741              :                                                     jtitem,
    1742              :                                                     item_list);
    1743          517 :                 right_item = (JoinTreeItem *) llast(*item_list);
    1744              :                 /* Compute qualscope etc */
    1745         1034 :                 fj_domain->jd_relids = bms_add_members(fj_domain->jd_relids,
    1746          517 :                                                        child_domain->jd_relids);
    1747         1034 :                 parent_domain->jd_relids = bms_add_members(parent_domain->jd_relids,
    1748          517 :                                                            fj_domain->jd_relids);
    1749         1034 :                 jtitem->qualscope = bms_union(left_item->qualscope,
    1750          517 :                                               right_item->qualscope);
    1751              :                 Assert(j->rtindex != 0);
    1752          517 :                 parent_domain->jd_relids = bms_add_member(parent_domain->jd_relids,
    1753              :                                                           j->rtindex);
    1754          517 :                 jtitem->qualscope = bms_add_member(jtitem->qualscope,
    1755              :                                                    j->rtindex);
    1756          517 :                 root->outer_join_rels = bms_add_member(root->outer_join_rels,
    1757              :                                                        j->rtindex);
    1758          517 :                 mark_rels_nulled_by_join(root, j->rtindex,
    1759              :                                          left_item->qualscope);
    1760          517 :                 mark_rels_nulled_by_join(root, j->rtindex,
    1761              :                                          right_item->qualscope);
    1762         1034 :                 jtitem->inner_join_rels = bms_union(left_item->inner_join_rels,
    1763          517 :                                                     right_item->inner_join_rels);
    1764          517 :                 jtitem->left_rels = left_item->qualscope;
    1765          517 :                 jtitem->right_rels = right_item->qualscope;
    1766              :                 /* each side is both outer and inner */
    1767          517 :                 jtitem->nonnullable_rels = jtitem->qualscope;
    1768          517 :                 break;
    1769            0 :             default:
    1770              :                 /* JOIN_RIGHT was eliminated during reduce_outer_joins() */
    1771            0 :                 elog(ERROR, "unrecognized join type: %d",
    1772              :                      (int) j->jointype);
    1773              :                 leftjoinlist = rightjoinlist = NIL; /* keep compiler quiet */
    1774              :                 break;
    1775              :         }
    1776              : 
    1777              :         /*
    1778              :          * Compute the output joinlist.  We fold subproblems together except
    1779              :          * at a FULL JOIN or where join_collapse_limit would be exceeded.
    1780              :          */
    1781        52053 :         if (j->jointype == JOIN_FULL)
    1782              :         {
    1783              :             /* force the join order exactly at this node */
    1784          517 :             joinlist = list_make1(list_make2(leftjoinlist, rightjoinlist));
    1785              :         }
    1786        51536 :         else if (list_length(leftjoinlist) + list_length(rightjoinlist) <=
    1787              :                  join_collapse_limit)
    1788              :         {
    1789              :             /* OK to combine subproblems */
    1790        51452 :             joinlist = list_concat(leftjoinlist, rightjoinlist);
    1791              :         }
    1792              :         else
    1793              :         {
    1794              :             /* can't combine, but needn't force join order above here */
    1795              :             Node       *leftpart,
    1796              :                        *rightpart;
    1797              : 
    1798              :             /* avoid creating useless 1-element sublists */
    1799           84 :             if (list_length(leftjoinlist) == 1)
    1800           15 :                 leftpart = (Node *) linitial(leftjoinlist);
    1801              :             else
    1802           69 :                 leftpart = (Node *) leftjoinlist;
    1803           84 :             if (list_length(rightjoinlist) == 1)
    1804           12 :                 rightpart = (Node *) linitial(rightjoinlist);
    1805              :             else
    1806           72 :                 rightpart = (Node *) rightjoinlist;
    1807           84 :             joinlist = list_make2(leftpart, rightpart);
    1808              :         }
    1809              :     }
    1810              :     else
    1811              :     {
    1812            0 :         elog(ERROR, "unrecognized node type: %d",
    1813              :              (int) nodeTag(jtnode));
    1814              :         joinlist = NIL;         /* keep compiler quiet */
    1815              :     }
    1816              : 
    1817              :     /* Finally, we can add the new JoinTreeItem to item_list */
    1818       480795 :     *item_list = lappend(*item_list, jtitem);
    1819              : 
    1820       480795 :     return joinlist;
    1821              : }
    1822              : 
    1823              : /*
    1824              :  * deconstruct_distribute
    1825              :  *    Process one jointree node in phase 2 of deconstruct_jointree processing.
    1826              :  *
    1827              :  * Distribute quals of the node to appropriate restriction and join lists.
    1828              :  * In addition, entries will be added to root->join_info_list for outer joins.
    1829              :  */
    1830              : static void
    1831       480795 : deconstruct_distribute(PlannerInfo *root, JoinTreeItem *jtitem)
    1832              : {
    1833       480795 :     Node       *jtnode = jtitem->jtnode;
    1834              : 
    1835       480795 :     if (IsA(jtnode, RangeTblRef))
    1836              :     {
    1837       249977 :         int         varno = ((RangeTblRef *) jtnode)->rtindex;
    1838              : 
    1839              :         /* Deal with any securityQuals attached to the RTE */
    1840       249977 :         if (root->qual_security_level > 0)
    1841         1545 :             process_security_barrier_quals(root,
    1842              :                                            varno,
    1843              :                                            jtitem);
    1844              :     }
    1845       230818 :     else if (IsA(jtnode, FromExpr))
    1846              :     {
    1847       178765 :         FromExpr   *f = (FromExpr *) jtnode;
    1848              : 
    1849              :         /*
    1850              :          * Process any lateral-referencing quals that were postponed to this
    1851              :          * level by children.
    1852              :          */
    1853       178765 :         distribute_quals_to_rels(root, jtitem->lateral_clauses,
    1854              :                                  jtitem,
    1855              :                                  NULL,
    1856              :                                  root->qual_security_level,
    1857              :                                  jtitem->qualscope,
    1858              :                                  NULL, NULL, NULL,
    1859              :                                  true, false, false,
    1860              :                                  NULL);
    1861              : 
    1862              :         /*
    1863              :          * Now process the top-level quals.
    1864              :          */
    1865       178765 :         distribute_quals_to_rels(root, (List *) f->quals,
    1866              :                                  jtitem,
    1867              :                                  NULL,
    1868              :                                  root->qual_security_level,
    1869              :                                  jtitem->qualscope,
    1870              :                                  NULL, NULL, NULL,
    1871              :                                  true, false, false,
    1872              :                                  NULL);
    1873              :     }
    1874        52053 :     else if (IsA(jtnode, JoinExpr))
    1875              :     {
    1876        52053 :         JoinExpr   *j = (JoinExpr *) jtnode;
    1877              :         Relids      ojscope;
    1878              :         List       *my_quals;
    1879              :         SpecialJoinInfo *sjinfo;
    1880              :         List      **postponed_oj_qual_list;
    1881              : 
    1882              :         /*
    1883              :          * Include lateral-referencing quals postponed from children in
    1884              :          * my_quals, so that they'll be handled properly in
    1885              :          * make_outerjoininfo.  (This is destructive to
    1886              :          * jtitem->lateral_clauses, but we won't use that again.)
    1887              :          */
    1888        52053 :         my_quals = list_concat(jtitem->lateral_clauses,
    1889        52053 :                                (List *) j->quals);
    1890              : 
    1891              :         /*
    1892              :          * For an OJ, form the SpecialJoinInfo now, so that we can pass it to
    1893              :          * distribute_qual_to_rels.  We must compute its ojscope too.
    1894              :          *
    1895              :          * Semijoins are a bit of a hybrid: we build a SpecialJoinInfo, but we
    1896              :          * want ojscope = NULL for distribute_qual_to_rels.
    1897              :          */
    1898        52053 :         if (j->jointype != JOIN_INNER)
    1899              :         {
    1900        27914 :             sjinfo = make_outerjoininfo(root,
    1901              :                                         jtitem->left_rels,
    1902              :                                         jtitem->right_rels,
    1903              :                                         jtitem->inner_join_rels,
    1904              :                                         j->jointype,
    1905        27914 :                                         j->rtindex,
    1906              :                                         my_quals);
    1907        27914 :             jtitem->sjinfo = sjinfo;
    1908        27914 :             if (j->jointype == JOIN_SEMI)
    1909         2571 :                 ojscope = NULL;
    1910              :             else
    1911        25343 :                 ojscope = bms_union(sjinfo->min_lefthand,
    1912        25343 :                                     sjinfo->min_righthand);
    1913              :         }
    1914              :         else
    1915              :         {
    1916        24139 :             sjinfo = NULL;
    1917        24139 :             ojscope = NULL;
    1918              :         }
    1919              : 
    1920              :         /*
    1921              :          * If it's a left join with a join clause that is strict for the LHS,
    1922              :          * then we need to postpone handling of any non-degenerate join
    1923              :          * clauses, in case the join is able to commute with another left join
    1924              :          * per identity 3.  (Degenerate clauses need not be postponed, since
    1925              :          * they will drop down below this join anyway.)
    1926              :          */
    1927        52053 :         if (j->jointype == JOIN_LEFT && sjinfo->lhs_strict)
    1928              :         {
    1929        21981 :             postponed_oj_qual_list = &jtitem->oj_joinclauses;
    1930              : 
    1931              :             /*
    1932              :              * Add back any commutable lower OJ relids that were removed from
    1933              :              * min_lefthand or min_righthand, else the ojscope cross-check in
    1934              :              * distribute_qual_to_rels will complain.  Since we are postponing
    1935              :              * processing of non-degenerate clauses, this addition doesn't
    1936              :              * affect anything except that cross-check.  Real clause
    1937              :              * positioning decisions will be made later, when we revisit the
    1938              :              * postponed clauses.
    1939              :              */
    1940        21981 :             ojscope = bms_add_members(ojscope, sjinfo->commute_below_l);
    1941        21981 :             ojscope = bms_add_members(ojscope, sjinfo->commute_below_r);
    1942              :         }
    1943              :         else
    1944        30072 :             postponed_oj_qual_list = NULL;
    1945              : 
    1946              :         /* Process the JOIN's qual clauses */
    1947        52053 :         distribute_quals_to_rels(root, my_quals,
    1948              :                                  jtitem,
    1949              :                                  sjinfo,
    1950              :                                  root->qual_security_level,
    1951              :                                  jtitem->qualscope,
    1952              :                                  ojscope, jtitem->nonnullable_rels,
    1953              :                                  NULL,  /* incompatible_relids */
    1954              :                                  true,  /* allow_equivalence */
    1955              :                                  false, false,  /* not clones */
    1956              :                                  postponed_oj_qual_list);
    1957              : 
    1958              :         /* And add the SpecialJoinInfo to join_info_list */
    1959        52053 :         if (sjinfo)
    1960        27914 :             root->join_info_list = lappend(root->join_info_list, sjinfo);
    1961              :     }
    1962              :     else
    1963              :     {
    1964            0 :         elog(ERROR, "unrecognized node type: %d",
    1965              :              (int) nodeTag(jtnode));
    1966              :     }
    1967       480795 : }
    1968              : 
    1969              : /*
    1970              :  * process_security_barrier_quals
    1971              :  *    Transfer security-barrier quals into relation's baserestrictinfo list.
    1972              :  *
    1973              :  * The rewriter put any relevant security-barrier conditions into the RTE's
    1974              :  * securityQuals field, but it's now time to copy them into the rel's
    1975              :  * baserestrictinfo.
    1976              :  *
    1977              :  * In inheritance cases, we only consider quals attached to the parent rel
    1978              :  * here; they will be valid for all children too, so it's okay to consider
    1979              :  * them for purposes like equivalence class creation.  Quals attached to
    1980              :  * individual child rels will be dealt with during path creation.
    1981              :  */
    1982              : static void
    1983         1545 : process_security_barrier_quals(PlannerInfo *root,
    1984              :                                int rti, JoinTreeItem *jtitem)
    1985              : {
    1986         1545 :     RangeTblEntry *rte = root->simple_rte_array[rti];
    1987         1545 :     Index       security_level = 0;
    1988              :     ListCell   *lc;
    1989              : 
    1990              :     /*
    1991              :      * Each element of the securityQuals list has been preprocessed into an
    1992              :      * implicitly-ANDed list of clauses.  All the clauses in a given sublist
    1993              :      * should get the same security level, but successive sublists get higher
    1994              :      * levels.
    1995              :      */
    1996         3161 :     foreach(lc, rte->securityQuals)
    1997              :     {
    1998         1616 :         List       *qualset = (List *) lfirst(lc);
    1999              : 
    2000              :         /*
    2001              :          * We cheat to the extent of passing ojscope = qualscope rather than
    2002              :          * its more logical value of NULL.  The only effect this has is to
    2003              :          * force a Var-free qual to be evaluated at the rel rather than being
    2004              :          * pushed up to top of tree, which we don't want.
    2005              :          */
    2006         1616 :         distribute_quals_to_rels(root, qualset,
    2007              :                                  jtitem,
    2008              :                                  NULL,
    2009              :                                  security_level,
    2010              :                                  jtitem->qualscope,
    2011              :                                  jtitem->qualscope,
    2012              :                                  NULL,
    2013              :                                  NULL,
    2014              :                                  true,
    2015              :                                  false, false,  /* not clones */
    2016              :                                  NULL);
    2017         1616 :         security_level++;
    2018              :     }
    2019              : 
    2020              :     /* Assert that qual_security_level is higher than anything we just used */
    2021              :     Assert(security_level <= root->qual_security_level);
    2022         1545 : }
    2023              : 
    2024              : /*
    2025              :  * mark_rels_nulled_by_join
    2026              :  *    Fill RelOptInfo.nulling_relids of baserels nulled by this outer join
    2027              :  *
    2028              :  * Inputs:
    2029              :  *  ojrelid: RT index of the join RTE (must not be 0)
    2030              :  *  lower_rels: the base+OJ Relids syntactically below nullable side of join
    2031              :  */
    2032              : static void
    2033        24463 : mark_rels_nulled_by_join(PlannerInfo *root, Index ojrelid,
    2034              :                          Relids lower_rels)
    2035              : {
    2036        24463 :     int         relid = -1;
    2037              : 
    2038        50314 :     while ((relid = bms_next_member(lower_rels, relid)) > 0)
    2039              :     {
    2040        25851 :         RelOptInfo *rel = root->simple_rel_array[relid];
    2041              : 
    2042              :         /* ignore the RTE_GROUP RTE */
    2043        25851 :         if (relid == root->group_rtindex)
    2044            0 :             continue;
    2045              : 
    2046        25851 :         if (rel == NULL)        /* must be an outer join */
    2047              :         {
    2048              :             Assert(bms_is_member(relid, root->outer_join_rels));
    2049          391 :             continue;
    2050              :         }
    2051        25460 :         rel->nulling_relids = bms_add_member(rel->nulling_relids, ojrelid);
    2052              :     }
    2053        24463 : }
    2054              : 
    2055              : /*
    2056              :  * make_outerjoininfo
    2057              :  *    Build a SpecialJoinInfo for the current outer join
    2058              :  *
    2059              :  * Inputs:
    2060              :  *  left_rels: the base+OJ Relids syntactically on outer side of join
    2061              :  *  right_rels: the base+OJ Relids syntactically on inner side of join
    2062              :  *  inner_join_rels: base+OJ Relids participating in inner joins below this one
    2063              :  *  jointype: what it says (must always be LEFT, FULL, SEMI, or ANTI)
    2064              :  *  ojrelid: RT index of the join RTE (0 for SEMI, which isn't in the RT list)
    2065              :  *  clause: the outer join's join condition (in implicit-AND format)
    2066              :  *
    2067              :  * The node should eventually be appended to root->join_info_list, but we
    2068              :  * do not do that here.
    2069              :  *
    2070              :  * Note: we assume that this function is invoked bottom-up, so that
    2071              :  * root->join_info_list already contains entries for all outer joins that are
    2072              :  * syntactically below this one.
    2073              :  */
    2074              : static SpecialJoinInfo *
    2075        27914 : make_outerjoininfo(PlannerInfo *root,
    2076              :                    Relids left_rels, Relids right_rels,
    2077              :                    Relids inner_join_rels,
    2078              :                    JoinType jointype, Index ojrelid,
    2079              :                    List *clause)
    2080              : {
    2081        27914 :     SpecialJoinInfo *sjinfo = makeNode(SpecialJoinInfo);
    2082              :     Relids      clause_relids;
    2083              :     Relids      strict_relids;
    2084              :     Relids      min_lefthand;
    2085              :     Relids      min_righthand;
    2086              :     Relids      commute_below_l;
    2087              :     Relids      commute_below_r;
    2088              :     ListCell   *l;
    2089              : 
    2090              :     /*
    2091              :      * We should not see RIGHT JOIN here because left/right were switched
    2092              :      * earlier
    2093              :      */
    2094              :     Assert(jointype != JOIN_INNER);
    2095              :     Assert(jointype != JOIN_RIGHT);
    2096              : 
    2097              :     /*
    2098              :      * Presently the executor cannot support FOR [KEY] UPDATE/SHARE marking of
    2099              :      * rels appearing on the nullable side of an outer join. (It's somewhat
    2100              :      * unclear what that would mean, anyway: what should we mark when a result
    2101              :      * row is generated from no element of the nullable relation?)  So,
    2102              :      * complain if any nullable rel is FOR [KEY] UPDATE/SHARE.
    2103              :      *
    2104              :      * You might be wondering why this test isn't made far upstream in the
    2105              :      * parser.  It's because the parser hasn't got enough info --- consider
    2106              :      * FOR UPDATE applied to a view.  Only after rewriting and flattening do
    2107              :      * we know whether the view contains an outer join.
    2108              :      *
    2109              :      * We use the original RowMarkClause list here; the PlanRowMark list would
    2110              :      * list everything.
    2111              :      */
    2112        27936 :     foreach(l, root->parse->rowMarks)
    2113              :     {
    2114           22 :         RowMarkClause *rc = (RowMarkClause *) lfirst(l);
    2115              : 
    2116           22 :         if (bms_is_member(rc->rti, right_rels) ||
    2117            4 :             (jointype == JOIN_FULL && bms_is_member(rc->rti, left_rels)))
    2118            0 :             ereport(ERROR,
    2119              :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2120              :             /*------
    2121              :              translator: %s is a SQL row locking clause such as FOR UPDATE */
    2122              :                      errmsg("%s cannot be applied to the nullable side of an outer join",
    2123              :                             LCS_asString(rc->strength))));
    2124              :     }
    2125              : 
    2126        27914 :     sjinfo->syn_lefthand = left_rels;
    2127        27914 :     sjinfo->syn_righthand = right_rels;
    2128        27914 :     sjinfo->jointype = jointype;
    2129        27914 :     sjinfo->ojrelid = ojrelid;
    2130              :     /* these fields may get added to later: */
    2131        27914 :     sjinfo->commute_above_l = NULL;
    2132        27914 :     sjinfo->commute_above_r = NULL;
    2133        27914 :     sjinfo->commute_below_l = NULL;
    2134        27914 :     sjinfo->commute_below_r = NULL;
    2135              : 
    2136        27914 :     compute_semijoin_info(root, sjinfo, clause);
    2137              : 
    2138              :     /* If it's a full join, no need to be very smart */
    2139        27914 :     if (jointype == JOIN_FULL)
    2140              :     {
    2141          517 :         sjinfo->min_lefthand = bms_copy(left_rels);
    2142          517 :         sjinfo->min_righthand = bms_copy(right_rels);
    2143          517 :         sjinfo->lhs_strict = false; /* don't care about this */
    2144          517 :         return sjinfo;
    2145              :     }
    2146              : 
    2147              :     /*
    2148              :      * Retrieve all relids mentioned within the join clause.
    2149              :      */
    2150        27397 :     clause_relids = pull_varnos(root, (Node *) clause);
    2151              : 
    2152              :     /*
    2153              :      * For which relids is the clause strict, ie, it cannot succeed if the
    2154              :      * rel's columns are all NULL?
    2155              :      */
    2156        27397 :     strict_relids = find_nonnullable_rels((Node *) clause);
    2157              : 
    2158              :     /* Remember whether the clause is strict for any LHS relations */
    2159        27397 :     sjinfo->lhs_strict = bms_overlap(strict_relids, left_rels);
    2160              : 
    2161              :     /*
    2162              :      * Required LHS always includes the LHS rels mentioned in the clause. We
    2163              :      * may have to add more rels based on lower outer joins; see below.
    2164              :      */
    2165        27397 :     min_lefthand = bms_intersect(clause_relids, left_rels);
    2166              : 
    2167              :     /*
    2168              :      * Similarly for required RHS.  But here, we must also include any lower
    2169              :      * inner joins, to ensure we don't try to commute with any of them.
    2170              :      */
    2171        27397 :     min_righthand = bms_int_members(bms_union(clause_relids, inner_join_rels),
    2172              :                                     right_rels);
    2173              : 
    2174              :     /*
    2175              :      * Now check previous outer joins for ordering restrictions.
    2176              :      *
    2177              :      * commute_below_l and commute_below_r accumulate the relids of lower
    2178              :      * outer joins that we think this one can commute with.  These decisions
    2179              :      * are just tentative within this loop, since we might find an
    2180              :      * intermediate outer join that prevents commutation.  Surviving relids
    2181              :      * will get merged into the SpecialJoinInfo structs afterwards.
    2182              :      */
    2183        27397 :     commute_below_l = commute_below_r = NULL;
    2184        36538 :     foreach(l, root->join_info_list)
    2185              :     {
    2186         9141 :         SpecialJoinInfo *otherinfo = (SpecialJoinInfo *) lfirst(l);
    2187              :         bool        have_unsafe_phvs;
    2188              : 
    2189              :         /*
    2190              :          * A full join is an optimization barrier: we can't associate into or
    2191              :          * out of it.  Hence, if it overlaps either LHS or RHS of the current
    2192              :          * rel, expand that side's min relset to cover the whole full join.
    2193              :          */
    2194         9141 :         if (otherinfo->jointype == JOIN_FULL)
    2195              :         {
    2196              :             Assert(otherinfo->ojrelid != 0);
    2197           47 :             if (bms_overlap(left_rels, otherinfo->syn_lefthand) ||
    2198           15 :                 bms_overlap(left_rels, otherinfo->syn_righthand))
    2199              :             {
    2200           17 :                 min_lefthand = bms_add_members(min_lefthand,
    2201           17 :                                                otherinfo->syn_lefthand);
    2202           17 :                 min_lefthand = bms_add_members(min_lefthand,
    2203           17 :                                                otherinfo->syn_righthand);
    2204           17 :                 min_lefthand = bms_add_member(min_lefthand,
    2205           17 :                                               otherinfo->ojrelid);
    2206              :             }
    2207           49 :             if (bms_overlap(right_rels, otherinfo->syn_lefthand) ||
    2208           17 :                 bms_overlap(right_rels, otherinfo->syn_righthand))
    2209              :             {
    2210           15 :                 min_righthand = bms_add_members(min_righthand,
    2211           15 :                                                 otherinfo->syn_lefthand);
    2212           15 :                 min_righthand = bms_add_members(min_righthand,
    2213           15 :                                                 otherinfo->syn_righthand);
    2214           15 :                 min_righthand = bms_add_member(min_righthand,
    2215           15 :                                                otherinfo->ojrelid);
    2216              :             }
    2217              :             /* Needn't do anything else with the full join */
    2218           32 :             continue;
    2219              :         }
    2220              : 
    2221              :         /*
    2222              :          * If our join condition contains any PlaceHolderVars that need to be
    2223              :          * evaluated above the lower OJ, then we can't commute with it.
    2224              :          */
    2225         9109 :         if (otherinfo->ojrelid != 0)
    2226              :             have_unsafe_phvs =
    2227         8932 :                 contain_placeholder_references_to(root,
    2228              :                                                   (Node *) clause,
    2229         8932 :                                                   otherinfo->ojrelid);
    2230              :         else
    2231          177 :             have_unsafe_phvs = false;
    2232              : 
    2233              :         /*
    2234              :          * For a lower OJ in our LHS, if our join condition uses the lower
    2235              :          * join's RHS and is not strict for that rel, we must preserve the
    2236              :          * ordering of the two OJs, so add lower OJ's full syntactic relset to
    2237              :          * min_lefthand.  (We must use its full syntactic relset, not just its
    2238              :          * min_lefthand + min_righthand.  This is because there might be other
    2239              :          * OJs below this one that this one can commute with, but we cannot
    2240              :          * commute with them if we don't with this one.)  Also, if we have
    2241              :          * unsafe PHVs or the current join is a semijoin or antijoin, we must
    2242              :          * preserve ordering regardless of strictness.
    2243              :          *
    2244              :          * Note: I believe we have to insist on being strict for at least one
    2245              :          * rel in the lower OJ's min_righthand, not its whole syn_righthand.
    2246              :          *
    2247              :          * When we don't need to preserve ordering, check to see if outer join
    2248              :          * identity 3 applies, and if so, remove the lower OJ's ojrelid from
    2249              :          * our min_lefthand so that commutation is allowed.
    2250              :          */
    2251         9109 :         if (bms_overlap(left_rels, otherinfo->syn_righthand))
    2252              :         {
    2253         8677 :             if (bms_overlap(clause_relids, otherinfo->syn_righthand) &&
    2254         2448 :                 (have_unsafe_phvs ||
    2255         2448 :                  jointype == JOIN_SEMI || jointype == JOIN_ANTI ||
    2256         2448 :                  !bms_overlap(strict_relids, otherinfo->min_righthand)))
    2257              :             {
    2258              :                 /* Preserve ordering */
    2259           21 :                 min_lefthand = bms_add_members(min_lefthand,
    2260           21 :                                                otherinfo->syn_lefthand);
    2261           21 :                 min_lefthand = bms_add_members(min_lefthand,
    2262           21 :                                                otherinfo->syn_righthand);
    2263           21 :                 if (otherinfo->ojrelid != 0)
    2264           21 :                     min_lefthand = bms_add_member(min_lefthand,
    2265           21 :                                                   otherinfo->ojrelid);
    2266              :             }
    2267         8656 :             else if (jointype == JOIN_LEFT &&
    2268        16657 :                      otherinfo->jointype == JOIN_LEFT &&
    2269         8326 :                      bms_overlap(strict_relids, otherinfo->min_righthand) &&
    2270         2430 :                      !bms_overlap(clause_relids, otherinfo->syn_lefthand))
    2271              :             {
    2272              :                 /* Identity 3 applies, so remove the ordering restriction */
    2273         2403 :                 min_lefthand = bms_del_member(min_lefthand, otherinfo->ojrelid);
    2274              :                 /* Record the (still tentative) commutability relationship */
    2275              :                 commute_below_l =
    2276         2403 :                     bms_add_member(commute_below_l, otherinfo->ojrelid);
    2277              :             }
    2278              :         }
    2279              : 
    2280              :         /*
    2281              :          * For a lower OJ in our RHS, if our join condition does not use the
    2282              :          * lower join's RHS and the lower OJ's join condition is strict, we
    2283              :          * can interchange the ordering of the two OJs; otherwise we must add
    2284              :          * the lower OJ's full syntactic relset to min_righthand.
    2285              :          *
    2286              :          * Also, if our join condition does not use the lower join's LHS
    2287              :          * either, force the ordering to be preserved.  Otherwise we can end
    2288              :          * up with SpecialJoinInfos with identical min_righthands, which can
    2289              :          * confuse join_is_legal (see discussion in backend/optimizer/README).
    2290              :          *
    2291              :          * Also, we must preserve ordering anyway if we have unsafe PHVs, or
    2292              :          * if either this join or the lower OJ is a semijoin or antijoin.
    2293              :          *
    2294              :          * When we don't need to preserve ordering, check to see if outer join
    2295              :          * identity 3 applies, and if so, remove the lower OJ's ojrelid from
    2296              :          * our min_righthand so that commutation is allowed.
    2297              :          */
    2298         9109 :         if (bms_overlap(right_rels, otherinfo->syn_righthand))
    2299              :         {
    2300          389 :             if (bms_overlap(clause_relids, otherinfo->syn_righthand) ||
    2301          365 :                 !bms_overlap(clause_relids, otherinfo->min_lefthand) ||
    2302          209 :                 have_unsafe_phvs ||
    2303          161 :                 jointype == JOIN_SEMI ||
    2304          155 :                 jointype == JOIN_ANTI ||
    2305          155 :                 otherinfo->jointype == JOIN_SEMI ||
    2306          125 :                 otherinfo->jointype == JOIN_ANTI ||
    2307          125 :                 !otherinfo->lhs_strict)
    2308              :             {
    2309              :                 /* Preserve ordering */
    2310          276 :                 min_righthand = bms_add_members(min_righthand,
    2311          276 :                                                 otherinfo->syn_lefthand);
    2312          276 :                 min_righthand = bms_add_members(min_righthand,
    2313          276 :                                                 otherinfo->syn_righthand);
    2314          276 :                 if (otherinfo->ojrelid != 0)
    2315          198 :                     min_righthand = bms_add_member(min_righthand,
    2316          198 :                                                    otherinfo->ojrelid);
    2317              :             }
    2318          113 :             else if (jointype == JOIN_LEFT &&
    2319          113 :                      otherinfo->jointype == JOIN_LEFT &&
    2320          113 :                      otherinfo->lhs_strict)
    2321              :             {
    2322              :                 /* Identity 3 applies, so remove the ordering restriction */
    2323          113 :                 min_righthand = bms_del_member(min_righthand,
    2324          113 :                                                otherinfo->ojrelid);
    2325              :                 /* Record the (still tentative) commutability relationship */
    2326              :                 commute_below_r =
    2327          113 :                     bms_add_member(commute_below_r, otherinfo->ojrelid);
    2328              :             }
    2329              :         }
    2330              :     }
    2331              : 
    2332              :     /*
    2333              :      * Examine PlaceHolderVars.  If a PHV is supposed to be evaluated within
    2334              :      * this join's nullable side, then ensure that min_righthand contains the
    2335              :      * full eval_at set of the PHV.  This ensures that the PHV actually can be
    2336              :      * evaluated within the RHS.  Note that this works only because we should
    2337              :      * already have determined the final eval_at level for any PHV
    2338              :      * syntactically within this join.
    2339              :      */
    2340        28115 :     foreach(l, root->placeholder_list)
    2341              :     {
    2342          718 :         PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(l);
    2343          718 :         Relids      ph_syn_level = phinfo->ph_var->phrels;
    2344              : 
    2345              :         /* Ignore placeholder if it didn't syntactically come from RHS */
    2346          718 :         if (!bms_is_subset(ph_syn_level, right_rels))
    2347          260 :             continue;
    2348              : 
    2349              :         /* Else, prevent join from being formed before we eval the PHV */
    2350          458 :         min_righthand = bms_add_members(min_righthand, phinfo->ph_eval_at);
    2351              :     }
    2352              : 
    2353              :     /*
    2354              :      * If we found nothing to put in min_lefthand, punt and make it the full
    2355              :      * LHS, to avoid having an empty min_lefthand which will confuse later
    2356              :      * processing. (We don't try to be smart about such cases, just correct.)
    2357              :      * Likewise for min_righthand.
    2358              :      */
    2359        27397 :     if (bms_is_empty(min_lefthand))
    2360          811 :         min_lefthand = bms_copy(left_rels);
    2361        27397 :     if (bms_is_empty(min_righthand))
    2362          522 :         min_righthand = bms_copy(right_rels);
    2363              : 
    2364              :     /* Now they'd better be nonempty */
    2365              :     Assert(!bms_is_empty(min_lefthand));
    2366              :     Assert(!bms_is_empty(min_righthand));
    2367              :     /* Shouldn't overlap either */
    2368              :     Assert(!bms_overlap(min_lefthand, min_righthand));
    2369              : 
    2370        27397 :     sjinfo->min_lefthand = min_lefthand;
    2371        27397 :     sjinfo->min_righthand = min_righthand;
    2372              : 
    2373              :     /*
    2374              :      * Now that we've identified the correct min_lefthand and min_righthand,
    2375              :      * any commute_below_l or commute_below_r relids that have not gotten
    2376              :      * added back into those sets (due to intervening outer joins) are indeed
    2377              :      * commutable with this one.
    2378              :      *
    2379              :      * First, delete any subsequently-added-back relids (this is easier than
    2380              :      * maintaining commute_below_l/r precisely through all the above).
    2381              :      */
    2382        27397 :     commute_below_l = bms_del_members(commute_below_l, min_lefthand);
    2383        27397 :     commute_below_r = bms_del_members(commute_below_r, min_righthand);
    2384              : 
    2385              :     /* Anything left? */
    2386        27397 :     if (commute_below_l || commute_below_r)
    2387              :     {
    2388              :         /* Yup, so we must update the derived data in the SpecialJoinInfos */
    2389         2477 :         sjinfo->commute_below_l = commute_below_l;
    2390         2477 :         sjinfo->commute_below_r = commute_below_r;
    2391         5411 :         foreach(l, root->join_info_list)
    2392              :         {
    2393         2934 :             SpecialJoinInfo *otherinfo = (SpecialJoinInfo *) lfirst(l);
    2394              : 
    2395         2934 :             if (bms_is_member(otherinfo->ojrelid, commute_below_l))
    2396         2403 :                 otherinfo->commute_above_l =
    2397         2403 :                     bms_add_member(otherinfo->commute_above_l, ojrelid);
    2398          531 :             else if (bms_is_member(otherinfo->ojrelid, commute_below_r))
    2399           98 :                 otherinfo->commute_above_r =
    2400           98 :                     bms_add_member(otherinfo->commute_above_r, ojrelid);
    2401              :         }
    2402              :     }
    2403              : 
    2404        27397 :     return sjinfo;
    2405              : }
    2406              : 
    2407              : /*
    2408              :  * compute_semijoin_info
    2409              :  *    Fill semijoin-related fields of a new SpecialJoinInfo
    2410              :  *
    2411              :  * Note: this relies on only the jointype and syn_righthand fields of the
    2412              :  * SpecialJoinInfo; the rest may not be set yet.
    2413              :  */
    2414              : static void
    2415        27914 : compute_semijoin_info(PlannerInfo *root, SpecialJoinInfo *sjinfo, List *clause)
    2416              : {
    2417              :     List       *semi_operators;
    2418              :     List       *semi_rhs_exprs;
    2419              :     bool        all_btree;
    2420              :     bool        all_hash;
    2421              :     ListCell   *lc;
    2422              : 
    2423              :     /* Initialize semijoin-related fields in case we can't unique-ify */
    2424        27914 :     sjinfo->semi_can_btree = false;
    2425        27914 :     sjinfo->semi_can_hash = false;
    2426        27914 :     sjinfo->semi_operators = NIL;
    2427        27914 :     sjinfo->semi_rhs_exprs = NIL;
    2428              : 
    2429              :     /* Nothing more to do if it's not a semijoin */
    2430        27914 :     if (sjinfo->jointype != JOIN_SEMI)
    2431        25343 :         return;
    2432              : 
    2433              :     /*
    2434              :      * Look to see whether the semijoin's join quals consist of AND'ed
    2435              :      * equality operators, with (only) RHS variables on only one side of each
    2436              :      * one.  If so, we can figure out how to enforce uniqueness for the RHS.
    2437              :      *
    2438              :      * Note that the input clause list is the list of quals that are
    2439              :      * *syntactically* associated with the semijoin, which in practice means
    2440              :      * the synthesized comparison list for an IN or the WHERE of an EXISTS.
    2441              :      * Particularly in the latter case, it might contain clauses that aren't
    2442              :      * *semantically* associated with the join, but refer to just one side or
    2443              :      * the other.  We can ignore such clauses here, as they will just drop
    2444              :      * down to be processed within one side or the other.  (It is okay to
    2445              :      * consider only the syntactically-associated clauses here because for a
    2446              :      * semijoin, no higher-level quals could refer to the RHS, and so there
    2447              :      * can be no other quals that are semantically associated with this join.
    2448              :      * We do things this way because it is useful to have the set of potential
    2449              :      * unique-ification expressions before we can extract the list of quals
    2450              :      * that are actually semantically associated with the particular join.)
    2451              :      *
    2452              :      * Note that the semi_operators list consists of the joinqual operators
    2453              :      * themselves (but commuted if needed to put the RHS value on the right).
    2454              :      * These could be cross-type operators, in which case the operator
    2455              :      * actually needed for uniqueness is a related single-type operator. We
    2456              :      * assume here that that operator will be available from the btree or hash
    2457              :      * opclass when the time comes ... if not, create_unique_plan() will fail.
    2458              :      */
    2459         2571 :     semi_operators = NIL;
    2460         2571 :     semi_rhs_exprs = NIL;
    2461         2571 :     all_btree = true;
    2462         2571 :     all_hash = enable_hashagg;  /* don't consider hash if not enabled */
    2463         5327 :     foreach(lc, clause)
    2464              :     {
    2465         2813 :         OpExpr     *op = (OpExpr *) lfirst(lc);
    2466              :         Oid         opno;
    2467              :         Node       *left_expr;
    2468              :         Node       *right_expr;
    2469              :         Relids      left_varnos;
    2470              :         Relids      right_varnos;
    2471              :         Relids      all_varnos;
    2472              :         Oid         opinputtype;
    2473              : 
    2474              :         /* Is it a binary opclause? */
    2475         5572 :         if (!IsA(op, OpExpr) ||
    2476         2759 :             list_length(op->args) != 2)
    2477              :         {
    2478              :             /* No, but does it reference both sides? */
    2479           54 :             all_varnos = pull_varnos(root, (Node *) op);
    2480          102 :             if (!bms_overlap(all_varnos, sjinfo->syn_righthand) ||
    2481           48 :                 bms_is_subset(all_varnos, sjinfo->syn_righthand))
    2482              :             {
    2483              :                 /*
    2484              :                  * Clause refers to only one rel, so ignore it --- unless it
    2485              :                  * contains volatile functions, in which case we'd better
    2486              :                  * punt.
    2487              :                  */
    2488           48 :                 if (contain_volatile_functions((Node *) op))
    2489           57 :                     return;
    2490           48 :                 continue;
    2491              :             }
    2492              :             /* Non-operator clause referencing both sides, must punt */
    2493            6 :             return;
    2494              :         }
    2495              : 
    2496              :         /* Extract data from binary opclause */
    2497         2759 :         opno = op->opno;
    2498         2759 :         left_expr = linitial(op->args);
    2499         2759 :         right_expr = lsecond(op->args);
    2500         2759 :         left_varnos = pull_varnos(root, left_expr);
    2501         2759 :         right_varnos = pull_varnos(root, right_expr);
    2502         2759 :         all_varnos = bms_union(left_varnos, right_varnos);
    2503         2759 :         opinputtype = exprType(left_expr);
    2504              : 
    2505              :         /* Does it reference both sides? */
    2506         5508 :         if (!bms_overlap(all_varnos, sjinfo->syn_righthand) ||
    2507         2749 :             bms_is_subset(all_varnos, sjinfo->syn_righthand))
    2508              :         {
    2509              :             /*
    2510              :              * Clause refers to only one rel, so ignore it --- unless it
    2511              :              * contains volatile functions, in which case we'd better punt.
    2512              :              */
    2513           65 :             if (contain_volatile_functions((Node *) op))
    2514            0 :                 return;
    2515           65 :             continue;
    2516              :         }
    2517              : 
    2518              :         /* check rel membership of arguments */
    2519         5388 :         if (!bms_is_empty(right_varnos) &&
    2520         2694 :             bms_is_subset(right_varnos, sjinfo->syn_righthand) &&
    2521         2464 :             !bms_overlap(left_varnos, sjinfo->syn_righthand))
    2522              :         {
    2523              :             /* typical case, right_expr is RHS variable */
    2524              :         }
    2525          460 :         else if (!bms_is_empty(left_varnos) &&
    2526          230 :                  bms_is_subset(left_varnos, sjinfo->syn_righthand) &&
    2527          227 :                  !bms_overlap(right_varnos, sjinfo->syn_righthand))
    2528              :         {
    2529              :             /* flipped case, left_expr is RHS variable */
    2530          227 :             opno = get_commutator(opno);
    2531          227 :             if (!OidIsValid(opno))
    2532            0 :                 return;
    2533          227 :             right_expr = left_expr;
    2534              :         }
    2535              :         else
    2536              :         {
    2537              :             /* mixed membership of args, punt */
    2538            3 :             return;
    2539              :         }
    2540              : 
    2541              :         /* all operators must be btree equality or hash equality */
    2542         2691 :         if (all_btree)
    2543              :         {
    2544              :             /* oprcanmerge is considered a hint... */
    2545         5334 :             if (!op_mergejoinable(opno, opinputtype) ||
    2546         2643 :                 get_mergejoin_opfamilies(opno) == NIL)
    2547           48 :                 all_btree = false;
    2548              :         }
    2549         2691 :         if (all_hash)
    2550              :         {
    2551              :             /* ... but oprcanhash had better be correct */
    2552         2655 :             if (!op_hashjoinable(opno, opinputtype))
    2553           48 :                 all_hash = false;
    2554              :         }
    2555         2691 :         if (!(all_btree || all_hash))
    2556           48 :             return;
    2557              : 
    2558              :         /* so far so good, keep building lists */
    2559         2643 :         semi_operators = lappend_oid(semi_operators, opno);
    2560         2643 :         semi_rhs_exprs = lappend(semi_rhs_exprs, copyObject(right_expr));
    2561              :     }
    2562              : 
    2563              :     /* Punt if we didn't find at least one column to unique-ify */
    2564         2514 :     if (semi_rhs_exprs == NIL)
    2565            6 :         return;
    2566              : 
    2567              :     /*
    2568              :      * The expressions we'd need to unique-ify mustn't be volatile.
    2569              :      */
    2570         2508 :     if (contain_volatile_functions((Node *) semi_rhs_exprs))
    2571            0 :         return;
    2572              : 
    2573              :     /*
    2574              :      * If we get here, we can unique-ify the semijoin's RHS using at least one
    2575              :      * of sorting and hashing.  Save the information about how to do that.
    2576              :      */
    2577         2508 :     sjinfo->semi_can_btree = all_btree;
    2578         2508 :     sjinfo->semi_can_hash = all_hash;
    2579         2508 :     sjinfo->semi_operators = semi_operators;
    2580         2508 :     sjinfo->semi_rhs_exprs = semi_rhs_exprs;
    2581              : }
    2582              : 
    2583              : /*
    2584              :  * deconstruct_distribute_oj_quals
    2585              :  *    Adjust LEFT JOIN quals to be suitable for commuted-left-join cases,
    2586              :  *    then push them into the joinqual lists and EquivalenceClass structures.
    2587              :  *
    2588              :  * This runs immediately after we've completed the deconstruct_distribute scan.
    2589              :  * jtitems contains all the JoinTreeItems (in depth-first order), and jtitem
    2590              :  * is one that has postponed oj_joinclauses to deal with.
    2591              :  */
    2592              : static void
    2593        21981 : deconstruct_distribute_oj_quals(PlannerInfo *root,
    2594              :                                 List *jtitems,
    2595              :                                 JoinTreeItem *jtitem)
    2596              : {
    2597        21981 :     SpecialJoinInfo *sjinfo = jtitem->sjinfo;
    2598              :     Relids      qualscope,
    2599              :                 ojscope,
    2600              :                 nonnullable_rels;
    2601              : 
    2602              :     /* Recompute syntactic and semantic scopes of this left join */
    2603        21981 :     qualscope = bms_union(sjinfo->syn_lefthand, sjinfo->syn_righthand);
    2604        21981 :     qualscope = bms_add_member(qualscope, sjinfo->ojrelid);
    2605        21981 :     ojscope = bms_union(sjinfo->min_lefthand, sjinfo->min_righthand);
    2606        21981 :     nonnullable_rels = sjinfo->syn_lefthand;
    2607              : 
    2608              :     /*
    2609              :      * If this join can commute with any other ones per outer-join identity 3,
    2610              :      * and it is the one providing the join clause with flexible semantics,
    2611              :      * then we have to generate variants of the join clause with different
    2612              :      * nullingrels labeling.  Otherwise, just push out the postponed clause
    2613              :      * as-is.
    2614              :      */
    2615              :     Assert(sjinfo->lhs_strict); /* else we shouldn't be here */
    2616        21981 :     if (sjinfo->commute_above_r || sjinfo->commute_below_l)
    2617         2483 :     {
    2618              :         Relids      joins_above;
    2619              :         Relids      joins_below;
    2620              :         Relids      incompatible_joins;
    2621              :         Relids      joins_so_far;
    2622              :         List       *quals;
    2623              :         int         save_last_rinfo_serial;
    2624              :         ListCell   *lc;
    2625              : 
    2626              :         /* Identify the outer joins this one commutes with */
    2627         2483 :         joins_above = sjinfo->commute_above_r;
    2628         2483 :         joins_below = sjinfo->commute_below_l;
    2629              : 
    2630              :         /*
    2631              :          * Generate qual variants with different sets of nullingrels bits.
    2632              :          *
    2633              :          * We only need bit-sets that correspond to the successively less
    2634              :          * deeply syntactically-nested subsets of this join and its
    2635              :          * commutators.  That's true first because obviously only those forms
    2636              :          * of the Vars and PHVs could appear elsewhere in the query, and
    2637              :          * second because the outer join identities do not provide a way to
    2638              :          * re-order such joins in a way that would require different marking.
    2639              :          * (That is, while the current join may commute with several others,
    2640              :          * none of those others can commute with each other.)  To visit the
    2641              :          * interesting joins in syntactic nesting order, we rely on the
    2642              :          * jtitems list to be ordered that way.
    2643              :          *
    2644              :          * We first strip out all the nullingrels bits corresponding to
    2645              :          * commuting joins below this one, and then successively put them back
    2646              :          * as we crawl up the join stack.
    2647              :          */
    2648         2483 :         quals = jtitem->oj_joinclauses;
    2649         2483 :         if (!bms_is_empty(joins_below))
    2650         2385 :             quals = (List *) remove_nulling_relids((Node *) quals,
    2651              :                                                    joins_below,
    2652              :                                                    NULL);
    2653              : 
    2654              :         /*
    2655              :          * We'll need to mark the lower versions of the quals as not safe to
    2656              :          * apply above not-yet-processed joins of the stack.  This prevents
    2657              :          * possibly applying a cloned qual at the wrong join level.
    2658              :          */
    2659         2483 :         incompatible_joins = bms_union(joins_below, joins_above);
    2660         2483 :         incompatible_joins = bms_add_member(incompatible_joins,
    2661         2483 :                                             sjinfo->ojrelid);
    2662              : 
    2663              :         /*
    2664              :          * Each time we produce RestrictInfo(s) from these quals, reset the
    2665              :          * last_rinfo_serial counter, so that the RestrictInfos for the "same"
    2666              :          * qual condition get identical serial numbers.  (This relies on the
    2667              :          * fact that we're not changing the qual list in any way that'd affect
    2668              :          * the number of RestrictInfos built from it.) This'll allow us to
    2669              :          * detect duplicative qual usage later.
    2670              :          */
    2671         2483 :         save_last_rinfo_serial = root->last_rinfo_serial;
    2672              : 
    2673         2483 :         joins_so_far = NULL;
    2674        21623 :         foreach(lc, jtitems)
    2675              :         {
    2676        19140 :             JoinTreeItem *otherjtitem = (JoinTreeItem *) lfirst(lc);
    2677        19140 :             SpecialJoinInfo *othersj = otherjtitem->sjinfo;
    2678        19140 :             bool        below_sjinfo = false;
    2679        19140 :             bool        above_sjinfo = false;
    2680              :             Relids      this_qualscope;
    2681              :             Relids      this_ojscope;
    2682              :             bool        allow_equivalence,
    2683              :                         has_clone,
    2684              :                         is_clone;
    2685              : 
    2686        19140 :             if (othersj == NULL)
    2687        13595 :                 continue;       /* not an outer-join item, ignore */
    2688              : 
    2689         5545 :             if (bms_is_member(othersj->ojrelid, joins_below))
    2690              :             {
    2691              :                 /* othersj commutes with sjinfo from below left */
    2692         2403 :                 below_sjinfo = true;
    2693              :             }
    2694         3142 :             else if (othersj == sjinfo)
    2695              :             {
    2696              :                 /* found our join in syntactic order */
    2697              :                 Assert(bms_equal(joins_so_far, joins_below));
    2698              :             }
    2699          659 :             else if (bms_is_member(othersj->ojrelid, joins_above))
    2700              :             {
    2701              :                 /* othersj commutes with sjinfo from above */
    2702           98 :                 above_sjinfo = true;
    2703              :             }
    2704              :             else
    2705              :             {
    2706              :                 /* othersj is not relevant, ignore */
    2707          561 :                 continue;
    2708              :             }
    2709              : 
    2710              :             /* Reset serial counter for this version of the quals */
    2711         4984 :             root->last_rinfo_serial = save_last_rinfo_serial;
    2712              : 
    2713              :             /*
    2714              :              * When we are looking at joins above sjinfo, we are envisioning
    2715              :              * pushing sjinfo to above othersj, so add othersj's nulling bit
    2716              :              * before distributing the quals.  We should add it to Vars coming
    2717              :              * from the current join's LHS: we want to transform the second
    2718              :              * form of OJ identity 3 to the first form, in which Vars of
    2719              :              * relation B will appear nulled by the syntactically-upper OJ
    2720              :              * within the Pbc clause, but those of relation C will not.  (In
    2721              :              * the notation used by optimizer/README, we're converting a qual
    2722              :              * of the form Pbc to Pb*c.)  Of course, we must also remove that
    2723              :              * bit from the incompatible_joins value, else we'll make a qual
    2724              :              * that can't be placed anywhere.
    2725              :              */
    2726         4984 :             if (above_sjinfo)
    2727              :             {
    2728              :                 quals = (List *)
    2729           98 :                     add_nulling_relids((Node *) quals,
    2730           98 :                                        sjinfo->syn_lefthand,
    2731           98 :                                        bms_make_singleton(othersj->ojrelid));
    2732           98 :                 incompatible_joins = bms_del_member(incompatible_joins,
    2733           98 :                                                     othersj->ojrelid);
    2734              :             }
    2735              : 
    2736              :             /* Compute qualscope and ojscope for this join level */
    2737         4984 :             this_qualscope = bms_union(qualscope, joins_so_far);
    2738         4984 :             this_ojscope = bms_union(ojscope, joins_so_far);
    2739         4984 :             if (above_sjinfo)
    2740              :             {
    2741              :                 /* othersj is not yet in joins_so_far, but we need it */
    2742           98 :                 this_qualscope = bms_add_member(this_qualscope,
    2743           98 :                                                 othersj->ojrelid);
    2744           98 :                 this_ojscope = bms_add_member(this_ojscope,
    2745           98 :                                               othersj->ojrelid);
    2746              :                 /* sjinfo is in joins_so_far, and we don't want it */
    2747           98 :                 this_ojscope = bms_del_member(this_ojscope,
    2748           98 :                                               sjinfo->ojrelid);
    2749              :             }
    2750              : 
    2751              :             /*
    2752              :              * We generate EquivalenceClasses only from the first form of the
    2753              :              * quals, with the fewest nullingrels bits set.  An EC made from
    2754              :              * this version of the quals can be useful below the outer-join
    2755              :              * nest, whereas versions with some nullingrels bits set would not
    2756              :              * be.  We cannot generate ECs from more than one version, or
    2757              :              * we'll make nonsensical conclusions that Vars with nullingrels
    2758              :              * bits set are equal to their versions without.  Fortunately,
    2759              :              * such ECs wouldn't be very useful anyway, because they'd equate
    2760              :              * values not observable outside the join nest.  (See
    2761              :              * optimizer/README.)
    2762              :              *
    2763              :              * The first form of the quals is also the only one marked as
    2764              :              * has_clone rather than is_clone.
    2765              :              */
    2766         4984 :             allow_equivalence = (joins_so_far == NULL);
    2767         4984 :             has_clone = allow_equivalence;
    2768         4984 :             is_clone = !has_clone;
    2769              : 
    2770         4984 :             distribute_quals_to_rels(root, quals,
    2771              :                                      otherjtitem,
    2772              :                                      sjinfo,
    2773              :                                      root->qual_security_level,
    2774              :                                      this_qualscope,
    2775              :                                      this_ojscope, nonnullable_rels,
    2776              :                                      bms_copy(incompatible_joins),
    2777              :                                      allow_equivalence,
    2778              :                                      has_clone,
    2779              :                                      is_clone,
    2780              :                                      NULL); /* no more postponement */
    2781              : 
    2782              :             /*
    2783              :              * Adjust qual nulling bits for next level up, if needed.  We
    2784              :              * don't want to put sjinfo's own bit in at all, and if we're
    2785              :              * above sjinfo then we did it already.  Here, we should mark all
    2786              :              * Vars coming from the lower join's RHS.  (Again, we are
    2787              :              * converting a qual of the form Pbc to Pb*c, but now we are
    2788              :              * putting back bits that were there in the parser output and were
    2789              :              * temporarily stripped above.)  Update incompatible_joins too.
    2790              :              */
    2791         4984 :             if (below_sjinfo)
    2792              :             {
    2793              :                 quals = (List *)
    2794         2403 :                     add_nulling_relids((Node *) quals,
    2795         2403 :                                        othersj->syn_righthand,
    2796         2403 :                                        bms_make_singleton(othersj->ojrelid));
    2797         2403 :                 incompatible_joins = bms_del_member(incompatible_joins,
    2798         2403 :                                                     othersj->ojrelid);
    2799              :             }
    2800              : 
    2801              :             /* ... and track joins processed so far */
    2802         4984 :             joins_so_far = bms_add_member(joins_so_far, othersj->ojrelid);
    2803              :         }
    2804              :     }
    2805              :     else
    2806              :     {
    2807              :         /* No commutation possible, just process the postponed clauses */
    2808        19498 :         distribute_quals_to_rels(root, jtitem->oj_joinclauses,
    2809              :                                  jtitem,
    2810              :                                  sjinfo,
    2811              :                                  root->qual_security_level,
    2812              :                                  qualscope,
    2813              :                                  ojscope, nonnullable_rels,
    2814              :                                  NULL,  /* incompatible_relids */
    2815              :                                  true,  /* allow_equivalence */
    2816              :                                  false, false,  /* not clones */
    2817              :                                  NULL); /* no more postponement */
    2818              :     }
    2819        21981 : }
    2820              : 
    2821              : 
    2822              : /*****************************************************************************
    2823              :  *
    2824              :  *    QUALIFICATIONS
    2825              :  *
    2826              :  *****************************************************************************/
    2827              : 
    2828              : /*
    2829              :  * distribute_quals_to_rels
    2830              :  *    Convenience routine to apply distribute_qual_to_rels to each element
    2831              :  *    of an AND'ed list of clauses.
    2832              :  */
    2833              : static void
    2834       435681 : distribute_quals_to_rels(PlannerInfo *root, List *clauses,
    2835              :                          JoinTreeItem *jtitem,
    2836              :                          SpecialJoinInfo *sjinfo,
    2837              :                          Index security_level,
    2838              :                          Relids qualscope,
    2839              :                          Relids ojscope,
    2840              :                          Relids outerjoin_nonnullable,
    2841              :                          Relids incompatible_relids,
    2842              :                          bool allow_equivalence,
    2843              :                          bool has_clone,
    2844              :                          bool is_clone,
    2845              :                          List **postponed_oj_qual_list)
    2846              : {
    2847              :     ListCell   *lc;
    2848              : 
    2849       742907 :     foreach(lc, clauses)
    2850              :     {
    2851       307226 :         Node       *clause = (Node *) lfirst(lc);
    2852              : 
    2853       307226 :         distribute_qual_to_rels(root, clause,
    2854              :                                 jtitem,
    2855              :                                 sjinfo,
    2856              :                                 security_level,
    2857              :                                 qualscope,
    2858              :                                 ojscope,
    2859              :                                 outerjoin_nonnullable,
    2860              :                                 incompatible_relids,
    2861              :                                 allow_equivalence,
    2862              :                                 has_clone,
    2863              :                                 is_clone,
    2864              :                                 postponed_oj_qual_list);
    2865              :     }
    2866       435681 : }
    2867              : 
    2868              : /*
    2869              :  * distribute_qual_to_rels
    2870              :  *    Add clause information to either the baserestrictinfo or joininfo list
    2871              :  *    (depending on whether the clause is a join) of each base relation
    2872              :  *    mentioned in the clause.  A RestrictInfo node is created and added to
    2873              :  *    the appropriate list for each rel.  Alternatively, if the clause uses a
    2874              :  *    mergejoinable operator, enter its left- and right-side expressions into
    2875              :  *    the query's EquivalenceClasses.
    2876              :  *
    2877              :  * In some cases, quals will be added to parent jtitems' lateral_clauses
    2878              :  * or to postponed_oj_qual_list instead of being processed right away.
    2879              :  * These will be dealt with in later calls of deconstruct_distribute.
    2880              :  *
    2881              :  * 'clause': the qual clause to be distributed
    2882              :  * 'jtitem': the JoinTreeItem for the containing jointree node
    2883              :  * 'sjinfo': join's SpecialJoinInfo (NULL for an inner join or WHERE clause)
    2884              :  * 'security_level': security_level to assign to the qual
    2885              :  * 'qualscope': set of base+OJ rels the qual's syntactic scope covers
    2886              :  * 'ojscope': NULL if not an outer-join qual, else the minimum set of base+OJ
    2887              :  *      rels needed to form this join
    2888              :  * 'outerjoin_nonnullable': NULL if not an outer-join qual, else the set of
    2889              :  *      base+OJ rels appearing on the outer (nonnullable) side of the join
    2890              :  *      (for FULL JOIN this includes both sides of the join, and must in fact
    2891              :  *      equal qualscope)
    2892              :  * 'incompatible_relids': the set of outer-join relid(s) that must not be
    2893              :  *      computed below this qual.  We only bother to compute this for
    2894              :  *      "clone" quals, otherwise it can be left NULL.
    2895              :  * 'allow_equivalence': true if it's okay to convert clause into an
    2896              :  *      EquivalenceClass
    2897              :  * 'has_clone': has_clone property to assign to the qual
    2898              :  * 'is_clone': is_clone property to assign to the qual
    2899              :  * 'postponed_oj_qual_list': if not NULL, non-degenerate outer join clauses
    2900              :  *      should be added to this list instead of being processed (list entries
    2901              :  *      are just the bare clauses)
    2902              :  *
    2903              :  * 'qualscope' identifies what level of JOIN the qual came from syntactically.
    2904              :  * 'ojscope' is needed if we decide to force the qual up to the outer-join
    2905              :  * level, which will be ojscope not necessarily qualscope.
    2906              :  *
    2907              :  * At the time this is called, root->join_info_list must contain entries for
    2908              :  * at least those special joins that are syntactically below this qual.
    2909              :  * (We now need that only for detection of redundant IS NULL quals.)
    2910              :  */
    2911              : static void
    2912       307226 : distribute_qual_to_rels(PlannerInfo *root, Node *clause,
    2913              :                         JoinTreeItem *jtitem,
    2914              :                         SpecialJoinInfo *sjinfo,
    2915              :                         Index security_level,
    2916              :                         Relids qualscope,
    2917              :                         Relids ojscope,
    2918              :                         Relids outerjoin_nonnullable,
    2919              :                         Relids incompatible_relids,
    2920              :                         bool allow_equivalence,
    2921              :                         bool has_clone,
    2922              :                         bool is_clone,
    2923              :                         List **postponed_oj_qual_list)
    2924              : {
    2925              :     Relids      relids;
    2926              :     bool        is_pushed_down;
    2927       307226 :     bool        pseudoconstant = false;
    2928              :     bool        maybe_equivalence;
    2929              :     bool        maybe_outer_join;
    2930              :     RestrictInfo *restrictinfo;
    2931              : 
    2932              :     /*
    2933              :      * Retrieve all relids mentioned within the clause.
    2934              :      */
    2935       307226 :     relids = pull_varnos(root, clause);
    2936              : 
    2937              :     /*
    2938              :      * In ordinary SQL, a WHERE or JOIN/ON clause can't reference any rels
    2939              :      * that aren't within its syntactic scope; however, if we pulled up a
    2940              :      * LATERAL subquery then we might find such references in quals that have
    2941              :      * been pulled up.  We need to treat such quals as belonging to the join
    2942              :      * level that includes every rel they reference.  Although we could make
    2943              :      * pull_up_subqueries() place such quals correctly to begin with, it's
    2944              :      * easier to handle it here.  When we find a clause that contains Vars
    2945              :      * outside its syntactic scope, locate the nearest parent join level that
    2946              :      * includes all the required rels and add the clause to that level's
    2947              :      * lateral_clauses list.  We'll process it when we reach that join level.
    2948              :      */
    2949       307226 :     if (!bms_is_subset(relids, qualscope))
    2950              :     {
    2951              :         JoinTreeItem *pitem;
    2952              : 
    2953              :         Assert(root->hasLateralRTEs);    /* shouldn't happen otherwise */
    2954              :         Assert(sjinfo == NULL); /* mustn't postpone past outer join */
    2955           58 :         for (pitem = jtitem->jti_parent; pitem; pitem = pitem->jti_parent)
    2956              :         {
    2957           58 :             if (bms_is_subset(relids, pitem->qualscope))
    2958              :             {
    2959           55 :                 pitem->lateral_clauses = lappend(pitem->lateral_clauses,
    2960              :                                                  clause);
    2961       216436 :                 return;
    2962              :             }
    2963              : 
    2964              :             /*
    2965              :              * We should not be postponing any quals past an outer join.  If
    2966              :              * this Assert fires, pull_up_subqueries() messed up.
    2967              :              */
    2968              :             Assert(pitem->sjinfo == NULL);
    2969              :         }
    2970            0 :         elog(ERROR, "failed to postpone qual containing lateral reference");
    2971              :     }
    2972              : 
    2973              :     /*
    2974              :      * If it's an outer-join clause, also check that relids is a subset of
    2975              :      * ojscope.  (This should not fail if the syntactic scope check passed.)
    2976              :      */
    2977       307171 :     if (ojscope && !bms_is_subset(relids, ojscope))
    2978            0 :         elog(ERROR, "JOIN qualification cannot refer to other relations");
    2979              : 
    2980              :     /*
    2981              :      * If the clause is variable-free, our normal heuristic for pushing it
    2982              :      * down to just the mentioned rels doesn't work, because there are none.
    2983              :      *
    2984              :      * If the clause is an outer-join clause, we must force it to the OJ's
    2985              :      * semantic level to preserve semantics.
    2986              :      *
    2987              :      * Otherwise, when the clause contains volatile functions, we force it to
    2988              :      * be evaluated at its original syntactic level.  This preserves the
    2989              :      * expected semantics.
    2990              :      *
    2991              :      * When the clause contains no volatile functions either, it is actually a
    2992              :      * pseudoconstant clause that will not change value during any one
    2993              :      * execution of the plan, and hence can be used as a one-time qual in a
    2994              :      * gating Result plan node.  We put such a clause into the regular
    2995              :      * RestrictInfo lists for the moment, but eventually createplan.c will
    2996              :      * pull it out and make a gating Result node immediately above whatever
    2997              :      * plan node the pseudoconstant clause is assigned to.  It's usually best
    2998              :      * to put a gating node as high in the plan tree as possible.
    2999              :      */
    3000       307171 :     if (bms_is_empty(relids))
    3001              :     {
    3002         5750 :         if (ojscope)
    3003              :         {
    3004              :             /* clause is attached to outer join, eval it there */
    3005          202 :             relids = bms_copy(ojscope);
    3006              :             /* mustn't use as gating qual, so don't mark pseudoconstant */
    3007              :         }
    3008         5548 :         else if (contain_volatile_functions(clause))
    3009              :         {
    3010              :             /* eval at original syntactic level */
    3011           87 :             relids = bms_copy(qualscope);
    3012              :             /* again, can't mark pseudoconstant */
    3013              :         }
    3014              :         else
    3015              :         {
    3016              :             /*
    3017              :              * If we are in the top-level join domain, we can push the qual to
    3018              :              * the top of the plan tree.  Otherwise, be conservative and eval
    3019              :              * it at original syntactic level.  (Ideally we'd push it to the
    3020              :              * top of the current join domain in all cases, but that causes
    3021              :              * problems if we later rearrange outer-join evaluation order.
    3022              :              * Pseudoconstant quals below the top level are a pretty odd case,
    3023              :              * so it's not clear that it's worth working hard on.)
    3024              :              */
    3025         5461 :             if (jtitem->jdomain == (JoinDomain *) linitial(root->join_domains))
    3026         5431 :                 relids = bms_copy(jtitem->jdomain->jd_relids);
    3027              :             else
    3028           30 :                 relids = bms_copy(qualscope);
    3029              :             /* mark as gating qual */
    3030         5461 :             pseudoconstant = true;
    3031              :             /* tell createplan.c to check for gating quals */
    3032         5461 :             root->hasPseudoConstantQuals = true;
    3033              :         }
    3034              :     }
    3035              : 
    3036              :     /*----------
    3037              :      * Check to see if clause application must be delayed by outer-join
    3038              :      * considerations.
    3039              :      *
    3040              :      * A word about is_pushed_down: we mark the qual as "pushed down" if
    3041              :      * it is (potentially) applicable at a level different from its original
    3042              :      * syntactic level.  This flag is used to distinguish OUTER JOIN ON quals
    3043              :      * from other quals pushed down to the same joinrel.  The rules are:
    3044              :      *      WHERE quals and INNER JOIN quals: is_pushed_down = true.
    3045              :      *      Non-degenerate OUTER JOIN quals: is_pushed_down = false.
    3046              :      *      Degenerate OUTER JOIN quals: is_pushed_down = true.
    3047              :      * A "degenerate" OUTER JOIN qual is one that doesn't mention the
    3048              :      * non-nullable side, and hence can be pushed down into the nullable side
    3049              :      * without changing the join result.  It is correct to treat it as a
    3050              :      * regular filter condition at the level where it is evaluated.
    3051              :      *
    3052              :      * Note: it is not immediately obvious that a simple boolean is enough
    3053              :      * for this: if for some reason we were to attach a degenerate qual to
    3054              :      * its original join level, it would need to be treated as an outer join
    3055              :      * qual there.  However, this cannot happen, because all the rels the
    3056              :      * clause mentions must be in the outer join's min_righthand, therefore
    3057              :      * the join it needs must be formed before the outer join; and we always
    3058              :      * attach quals to the lowest level where they can be evaluated.  But
    3059              :      * if we were ever to re-introduce a mechanism for delaying evaluation
    3060              :      * of "expensive" quals, this area would need work.
    3061              :      *
    3062              :      * Note: generally, use of is_pushed_down has to go through the macro
    3063              :      * RINFO_IS_PUSHED_DOWN, because that flag alone is not always sufficient
    3064              :      * to tell whether a clause must be treated as pushed-down in context.
    3065              :      * This seems like another reason why it should perhaps be rethought.
    3066              :      *----------
    3067              :      */
    3068       307171 :     if (bms_overlap(relids, outerjoin_nonnullable))
    3069              :     {
    3070              :         /*
    3071              :          * The qual is attached to an outer join and mentions (some of the)
    3072              :          * rels on the nonnullable side, so it's not degenerate.  If the
    3073              :          * caller wants to postpone handling such clauses, just add it to
    3074              :          * postponed_oj_qual_list and return.  (The work we've done up to here
    3075              :          * will have to be redone later, but there's not much of it.)
    3076              :          */
    3077        54721 :         if (postponed_oj_qual_list != NULL)
    3078              :         {
    3079        24319 :             *postponed_oj_qual_list = lappend(*postponed_oj_qual_list, clause);
    3080        24319 :             return;
    3081              :         }
    3082              : 
    3083              :         /*
    3084              :          * We can't use such a clause to deduce equivalence (the left and
    3085              :          * right sides might be unequal above the join because one of them has
    3086              :          * gone to NULL) ... but we might be able to use it for more limited
    3087              :          * deductions, if it is mergejoinable.  So consider adding it to the
    3088              :          * lists of set-aside outer-join clauses.
    3089              :          */
    3090        30402 :         is_pushed_down = false;
    3091        30402 :         maybe_equivalence = false;
    3092        30402 :         maybe_outer_join = true;
    3093              : 
    3094              :         /*
    3095              :          * Now force the qual to be evaluated exactly at the level of joining
    3096              :          * corresponding to the outer join.  We cannot let it get pushed down
    3097              :          * into the nonnullable side, since then we'd produce no output rows,
    3098              :          * rather than the intended single null-extended row, for any
    3099              :          * nonnullable-side rows failing the qual.
    3100              :          */
    3101              :         Assert(ojscope);
    3102        30402 :         relids = ojscope;
    3103              :         Assert(!pseudoconstant);
    3104              :     }
    3105              :     else
    3106              :     {
    3107              :         /*
    3108              :          * Normal qual clause or degenerate outer-join clause.  Either way, we
    3109              :          * can mark it as pushed-down.
    3110              :          */
    3111       252450 :         is_pushed_down = true;
    3112              : 
    3113              :         /*
    3114              :          * It's possible that this is an IS NULL clause that's redundant with
    3115              :          * a lower antijoin; if so we can just discard it.  We need not test
    3116              :          * in any of the other cases, because this will only be possible for
    3117              :          * pushed-down clauses.
    3118              :          */
    3119       252450 :         if (check_redundant_nullability_qual(root, clause))
    3120          596 :             return;
    3121              : 
    3122              :         /* Feed qual to the equivalence machinery, if allowed by caller */
    3123       251854 :         maybe_equivalence = allow_equivalence;
    3124              : 
    3125              :         /*
    3126              :          * Since it doesn't mention the LHS, it's certainly not useful as a
    3127              :          * set-aside OJ clause, even if it's in an OJ.
    3128              :          */
    3129       251854 :         maybe_outer_join = false;
    3130              :     }
    3131              : 
    3132              :     /*
    3133              :      * Build the RestrictInfo node itself.
    3134              :      */
    3135       282256 :     restrictinfo = make_restrictinfo(root,
    3136              :                                      (Expr *) clause,
    3137              :                                      is_pushed_down,
    3138              :                                      has_clone,
    3139              :                                      is_clone,
    3140              :                                      pseudoconstant,
    3141              :                                      security_level,
    3142              :                                      relids,
    3143              :                                      incompatible_relids,
    3144              :                                      outerjoin_nonnullable);
    3145              : 
    3146              :     /*
    3147              :      * If it's a join clause, add vars used in the clause to targetlists of
    3148              :      * their relations, so that they will be emitted by the plan nodes that
    3149              :      * scan those relations (else they won't be available at the join node!).
    3150              :      *
    3151              :      * Normally we mark the vars as needed at the join identified by "relids".
    3152              :      * However, if this is a clone clause then ignore the outer-join relids in
    3153              :      * that set.  Otherwise, vars appearing in a cloned clause would end up
    3154              :      * marked as having to propagate to the highest one of the commuting
    3155              :      * joins, which would often be an overestimate.  For such clauses, correct
    3156              :      * var propagation is ensured by making ojscope include input rels from
    3157              :      * both sides of the join.
    3158              :      *
    3159              :      * See also rebuild_joinclause_attr_needed, which has to partially repeat
    3160              :      * this work after removal of an outer join.
    3161              :      *
    3162              :      * Note: if the clause gets absorbed into an EquivalenceClass then this
    3163              :      * may be unnecessary, but for now we have to do it to cover the case
    3164              :      * where the EC becomes ec_broken and we end up reinserting the original
    3165              :      * clauses into the plan.
    3166              :      */
    3167       282256 :     if (bms_membership(relids) == BMS_MULTIPLE)
    3168              :     {
    3169        84108 :         List       *vars = pull_var_clause(clause,
    3170              :                                            PVC_RECURSE_AGGREGATES |
    3171              :                                            PVC_RECURSE_WINDOWFUNCS |
    3172              :                                            PVC_INCLUDE_PLACEHOLDERS);
    3173              :         Relids      where_needed;
    3174              : 
    3175        84108 :         if (is_clone)
    3176         2709 :             where_needed = bms_intersect(relids, root->all_baserels);
    3177              :         else
    3178        81399 :             where_needed = relids;
    3179        84108 :         add_vars_to_targetlist(root, vars, where_needed);
    3180        84108 :         list_free(vars);
    3181              :     }
    3182              : 
    3183              :     /*
    3184              :      * We check "mergejoinability" of every clause, not only join clauses,
    3185              :      * because we want to know about equivalences between vars of the same
    3186              :      * relation, or between vars and consts.
    3187              :      */
    3188       282256 :     check_mergejoinable(restrictinfo);
    3189              : 
    3190              :     /*
    3191              :      * If it is a true equivalence clause, send it to the EquivalenceClass
    3192              :      * machinery.  We do *not* attach it directly to any restriction or join
    3193              :      * lists.  The EC code will propagate it to the appropriate places later.
    3194              :      *
    3195              :      * If the clause has a mergejoinable operator, yet isn't an equivalence
    3196              :      * because it is an outer-join clause, the EC code may still be able to do
    3197              :      * something with it.  We add it to appropriate lists for further
    3198              :      * consideration later.  Specifically:
    3199              :      *
    3200              :      * If it is a left or right outer-join qualification that relates the two
    3201              :      * sides of the outer join (no funny business like leftvar1 = leftvar2 +
    3202              :      * rightvar), we add it to root->left_join_clauses or
    3203              :      * root->right_join_clauses according to which side the nonnullable
    3204              :      * variable appears on.
    3205              :      *
    3206              :      * If it is a full outer-join qualification, we add it to
    3207              :      * root->full_join_clauses.  (Ideally we'd discard cases that aren't
    3208              :      * leftvar = rightvar, as we do for left/right joins, but this routine
    3209              :      * doesn't have the info needed to do that; and the current usage of the
    3210              :      * full_join_clauses list doesn't require that, so it's not currently
    3211              :      * worth complicating this routine's API to make it possible.)
    3212              :      *
    3213              :      * If none of the above hold, pass it off to
    3214              :      * distribute_restrictinfo_to_rels().
    3215              :      *
    3216              :      * In all cases, it's important to initialize the left_ec and right_ec
    3217              :      * fields of a mergejoinable clause, so that all possibly mergejoinable
    3218              :      * expressions have representations in EquivalenceClasses.  If
    3219              :      * process_equivalence is successful, it will take care of that;
    3220              :      * otherwise, we have to call initialize_mergeclause_eclasses to do it.
    3221              :      */
    3222       282256 :     if (restrictinfo->mergeopfamilies)
    3223              :     {
    3224       192053 :         if (maybe_equivalence)
    3225              :         {
    3226       162582 :             if (process_equivalence(root, &restrictinfo, jtitem->jdomain))
    3227       162451 :                 return;
    3228              :             /* EC rejected it, so set left_ec/right_ec the hard way ... */
    3229          131 :             if (restrictinfo->mergeopfamilies)   /* EC might have changed this */
    3230          104 :                 initialize_mergeclause_eclasses(root, restrictinfo);
    3231              :             /* ... and fall through to distribute_restrictinfo_to_rels */
    3232              :         }
    3233        29471 :         else if (maybe_outer_join && restrictinfo->can_join)
    3234              :         {
    3235              :             /* we need to set up left_ec/right_ec the hard way */
    3236        29116 :             initialize_mergeclause_eclasses(root, restrictinfo);
    3237              :             /* now see if it should go to any outer-join lists */
    3238              :             Assert(sjinfo != NULL);
    3239        29116 :             if (bms_is_subset(restrictinfo->left_relids,
    3240        14434 :                               outerjoin_nonnullable) &&
    3241        14434 :                 !bms_overlap(restrictinfo->right_relids,
    3242              :                              outerjoin_nonnullable))
    3243              :             {
    3244              :                 /* we have outervar = innervar */
    3245        13784 :                 OuterJoinClauseInfo *ojcinfo = makeNode(OuterJoinClauseInfo);
    3246              : 
    3247        13784 :                 ojcinfo->rinfo = restrictinfo;
    3248        13784 :                 ojcinfo->sjinfo = sjinfo;
    3249        13784 :                 root->left_join_clauses = lappend(root->left_join_clauses,
    3250              :                                                   ojcinfo);
    3251        13784 :                 return;
    3252              :             }
    3253        15332 :             if (bms_is_subset(restrictinfo->right_relids,
    3254        15249 :                               outerjoin_nonnullable) &&
    3255        15249 :                 !bms_overlap(restrictinfo->left_relids,
    3256              :                              outerjoin_nonnullable))
    3257              :             {
    3258              :                 /* we have innervar = outervar */
    3259        14599 :                 OuterJoinClauseInfo *ojcinfo = makeNode(OuterJoinClauseInfo);
    3260              : 
    3261        14599 :                 ojcinfo->rinfo = restrictinfo;
    3262        14599 :                 ojcinfo->sjinfo = sjinfo;
    3263        14599 :                 root->right_join_clauses = lappend(root->right_join_clauses,
    3264              :                                                    ojcinfo);
    3265        14599 :                 return;
    3266              :             }
    3267          733 :             if (sjinfo->jointype == JOIN_FULL)
    3268              :             {
    3269              :                 /* FULL JOIN (above tests cannot match in this case) */
    3270          632 :                 OuterJoinClauseInfo *ojcinfo = makeNode(OuterJoinClauseInfo);
    3271              : 
    3272          632 :                 ojcinfo->rinfo = restrictinfo;
    3273          632 :                 ojcinfo->sjinfo = sjinfo;
    3274          632 :                 root->full_join_clauses = lappend(root->full_join_clauses,
    3275              :                                                   ojcinfo);
    3276          632 :                 return;
    3277              :             }
    3278              :             /* nope, so fall through to distribute_restrictinfo_to_rels */
    3279              :         }
    3280              :         else
    3281              :         {
    3282              :             /* we still need to set up left_ec/right_ec */
    3283          355 :             initialize_mergeclause_eclasses(root, restrictinfo);
    3284              :         }
    3285              :     }
    3286              : 
    3287              :     /* No EC special case applies, so push it into the clause lists */
    3288        90790 :     distribute_restrictinfo_to_rels(root, restrictinfo);
    3289              : }
    3290              : 
    3291              : /*
    3292              :  * check_redundant_nullability_qual
    3293              :  *    Check to see if the qual is an IS NULL qual that is redundant with
    3294              :  *    a lower JOIN_ANTI join.
    3295              :  *
    3296              :  * We want to suppress redundant IS NULL quals, not so much to save cycles
    3297              :  * as to avoid generating bogus selectivity estimates for them.  So if
    3298              :  * redundancy is detected here, distribute_qual_to_rels() just throws away
    3299              :  * the qual.
    3300              :  */
    3301              : static bool
    3302       252450 : check_redundant_nullability_qual(PlannerInfo *root, Node *clause)
    3303              : {
    3304              :     Var        *forced_null_var;
    3305              :     ListCell   *lc;
    3306              : 
    3307              :     /* Check for IS NULL, and identify the Var forced to NULL */
    3308       252450 :     forced_null_var = find_forced_null_var(clause);
    3309       252450 :     if (forced_null_var == NULL)
    3310       251021 :         return false;
    3311              : 
    3312              :     /*
    3313              :      * If the Var comes from the nullable side of a lower antijoin, the IS
    3314              :      * NULL condition is necessarily true.  If it's not nulled by anything,
    3315              :      * there is no point in searching the join_info_list.  Otherwise, we need
    3316              :      * to find out whether the nulling rel is an antijoin.
    3317              :      */
    3318         1429 :     if (forced_null_var->varnullingrels == NULL)
    3319          783 :         return false;
    3320              : 
    3321          721 :     foreach(lc, root->join_info_list)
    3322              :     {
    3323          671 :         SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
    3324              : 
    3325              :         /*
    3326              :          * This test will not succeed if sjinfo->ojrelid is zero, which is
    3327              :          * possible for an antijoin that was converted from a semijoin; but in
    3328              :          * such a case the Var couldn't have come from its nullable side.
    3329              :          */
    3330         1267 :         if (sjinfo->jointype == JOIN_ANTI && sjinfo->ojrelid != 0 &&
    3331          596 :             bms_is_member(sjinfo->ojrelid, forced_null_var->varnullingrels))
    3332          596 :             return true;
    3333              :     }
    3334              : 
    3335           50 :     return false;
    3336              : }
    3337              : 
    3338              : /*
    3339              :  * add_base_clause_to_rel
    3340              :  *      Add 'restrictinfo' as a baserestrictinfo to the base relation denoted
    3341              :  *      by 'relid'.  We offer some simple prechecks to try to determine if the
    3342              :  *      qual is always true, in which case we ignore it rather than add it.
    3343              :  *      If we detect the qual is always false, we replace it with
    3344              :  *      constant-FALSE.
    3345              :  */
    3346              : static void
    3347       207336 : add_base_clause_to_rel(PlannerInfo *root, Index relid,
    3348              :                        RestrictInfo *restrictinfo)
    3349              : {
    3350       207336 :     RelOptInfo *rel = find_base_rel(root, relid);
    3351       207336 :     RangeTblEntry *rte = root->simple_rte_array[relid];
    3352              : 
    3353              :     Assert(bms_membership(restrictinfo->required_relids) == BMS_SINGLETON);
    3354              : 
    3355              :     /*
    3356              :      * For inheritance parent tables, we must always record the RestrictInfo
    3357              :      * in baserestrictinfo as is.  If we were to transform or skip adding it,
    3358              :      * then the original wouldn't be available in apply_child_basequals. Since
    3359              :      * there are two RangeTblEntries for inheritance parents, one with
    3360              :      * inh==true and the other with inh==false, we're still able to apply this
    3361              :      * optimization to the inh==false one.  The inh==true one is what
    3362              :      * apply_child_basequals() sees, whereas the inh==false one is what's used
    3363              :      * for the scan node in the final plan.
    3364              :      *
    3365              :      * We make an exception to this for partitioned tables.  For these, we
    3366              :      * always apply the constant-TRUE and constant-FALSE transformations.  A
    3367              :      * qual which is either of these for a partitioned table must also be that
    3368              :      * for all of its child partitions.
    3369              :      */
    3370       207336 :     if (!rte->inh || rte->relkind == RELKIND_PARTITIONED_TABLE)
    3371              :     {
    3372              :         /* Don't add the clause if it is always true */
    3373       206336 :         if (restriction_is_always_true(root, restrictinfo))
    3374          240 :             return;
    3375              : 
    3376              :         /*
    3377              :          * Substitute the origin qual with constant-FALSE if it is provably
    3378              :          * always false.
    3379              :          *
    3380              :          * Note that we need to keep the same rinfo_serial, since it is in
    3381              :          * practice the same condition.  We also need to reset the
    3382              :          * last_rinfo_serial counter, which is essential to ensure that the
    3383              :          * RestrictInfos for the "same" qual condition get identical serial
    3384              :          * numbers (see deconstruct_distribute_oj_quals).
    3385              :          */
    3386       206096 :         if (restriction_is_always_false(root, restrictinfo))
    3387              :         {
    3388            0 :             int         save_rinfo_serial = restrictinfo->rinfo_serial;
    3389            0 :             int         save_last_rinfo_serial = root->last_rinfo_serial;
    3390              : 
    3391            0 :             restrictinfo = make_restrictinfo(root,
    3392            0 :                                              (Expr *) makeBoolConst(false, false),
    3393            0 :                                              restrictinfo->is_pushed_down,
    3394            0 :                                              restrictinfo->has_clone,
    3395            0 :                                              restrictinfo->is_clone,
    3396            0 :                                              restrictinfo->pseudoconstant,
    3397              :                                              0, /* security_level */
    3398              :                                              restrictinfo->required_relids,
    3399              :                                              restrictinfo->incompatible_relids,
    3400              :                                              restrictinfo->outer_relids);
    3401            0 :             restrictinfo->rinfo_serial = save_rinfo_serial;
    3402            0 :             root->last_rinfo_serial = save_last_rinfo_serial;
    3403              :         }
    3404              :     }
    3405              : 
    3406              :     /* Add clause to rel's restriction list */
    3407       207096 :     rel->baserestrictinfo = lappend(rel->baserestrictinfo, restrictinfo);
    3408              : 
    3409              :     /* Update security level info */
    3410       207096 :     rel->baserestrict_min_security = Min(rel->baserestrict_min_security,
    3411              :                                          restrictinfo->security_level);
    3412              : }
    3413              : 
    3414              : /*
    3415              :  * restriction_is_always_true
    3416              :  *    Check to see if the RestrictInfo is always true.
    3417              :  *
    3418              :  * Currently we only check for NullTest quals and OR clauses that include
    3419              :  * NullTest quals.  We may extend it in the future.
    3420              :  */
    3421              : bool
    3422       266970 : restriction_is_always_true(PlannerInfo *root,
    3423              :                            RestrictInfo *restrictinfo)
    3424              : {
    3425              :     /*
    3426              :      * For a clone clause, we don't have a reliable way to determine if the
    3427              :      * input expression of a NullTest is non-nullable: nullingrel bits in
    3428              :      * clone clauses may not reflect reality, so we dare not draw conclusions
    3429              :      * from clones about whether Vars are guaranteed not-null.
    3430              :      */
    3431       266970 :     if (restrictinfo->has_clone || restrictinfo->is_clone)
    3432         5400 :         return false;
    3433              : 
    3434              :     /* Check for NullTest qual */
    3435       261570 :     if (IsA(restrictinfo->clause, NullTest))
    3436              :     {
    3437         6043 :         NullTest   *nulltest = (NullTest *) restrictinfo->clause;
    3438              : 
    3439              :         /* is this NullTest an IS_NOT_NULL qual? */
    3440         6043 :         if (nulltest->nulltesttype != IS_NOT_NULL)
    3441         1591 :             return false;
    3442              : 
    3443              :         /*
    3444              :          * Empty rows can appear NULL in some contexts and NOT NULL in others,
    3445              :          * so avoid this optimization for row expressions.
    3446              :          */
    3447         4452 :         if (nulltest->argisrow)
    3448           78 :             return false;
    3449              : 
    3450         4374 :         return expr_is_nonnullable(root, nulltest->arg, true);
    3451              :     }
    3452              : 
    3453              :     /* If it's an OR, check its sub-clauses */
    3454       255527 :     if (restriction_is_or_clause(restrictinfo))
    3455              :     {
    3456              :         ListCell   *lc;
    3457              : 
    3458              :         Assert(is_orclause(restrictinfo->orclause));
    3459              : 
    3460              :         /*
    3461              :          * if any of the given OR branches is provably always true then the
    3462              :          * entire condition is true.
    3463              :          */
    3464        16249 :         foreach(lc, ((BoolExpr *) restrictinfo->orclause)->args)
    3465              :         {
    3466        11382 :             Node       *orarg = (Node *) lfirst(lc);
    3467              : 
    3468        11382 :             if (!IsA(orarg, RestrictInfo))
    3469         1577 :                 continue;
    3470              : 
    3471         9805 :             if (restriction_is_always_true(root, (RestrictInfo *) orarg))
    3472            0 :                 return true;
    3473              :         }
    3474              :     }
    3475              : 
    3476       255527 :     return false;
    3477              : }
    3478              : 
    3479              : /*
    3480              :  * restriction_is_always_false
    3481              :  *    Check to see if the RestrictInfo is always false.
    3482              :  *
    3483              :  * Currently we only check for NullTest quals and OR clauses that include
    3484              :  * NullTest quals.  We may extend it in the future.
    3485              :  */
    3486              : bool
    3487       261065 : restriction_is_always_false(PlannerInfo *root,
    3488              :                             RestrictInfo *restrictinfo)
    3489              : {
    3490              :     /*
    3491              :      * For a clone clause, we don't have a reliable way to determine if the
    3492              :      * input expression of a NullTest is non-nullable: nullingrel bits in
    3493              :      * clone clauses may not reflect reality, so we dare not draw conclusions
    3494              :      * from clones about whether Vars are guaranteed not-null.
    3495              :      */
    3496       261065 :     if (restrictinfo->has_clone || restrictinfo->is_clone)
    3497         5400 :         return false;
    3498              : 
    3499              :     /* Check for NullTest qual */
    3500       255665 :     if (IsA(restrictinfo->clause, NullTest))
    3501              :     {
    3502         5221 :         NullTest   *nulltest = (NullTest *) restrictinfo->clause;
    3503              : 
    3504              :         /* is this NullTest an IS_NULL qual? */
    3505         5221 :         if (nulltest->nulltesttype != IS_NULL)
    3506         3830 :             return false;
    3507              : 
    3508              :         /*
    3509              :          * Empty rows can appear NULL in some contexts and NOT NULL in others,
    3510              :          * so avoid this optimization for row expressions.
    3511              :          */
    3512         1391 :         if (nulltest->argisrow)
    3513           60 :             return false;
    3514              : 
    3515         1331 :         return expr_is_nonnullable(root, nulltest->arg, true);
    3516              :     }
    3517              : 
    3518              :     /* If it's an OR, check its sub-clauses */
    3519       250444 :     if (restriction_is_or_clause(restrictinfo))
    3520              :     {
    3521              :         ListCell   *lc;
    3522              : 
    3523              :         Assert(is_orclause(restrictinfo->orclause));
    3524              : 
    3525              :         /*
    3526              :          * Currently, when processing OR expressions, we only return true when
    3527              :          * all of the OR branches are always false.  This could perhaps be
    3528              :          * expanded to remove OR branches that are provably false.  This may
    3529              :          * be a useful thing to do as it could result in the OR being left
    3530              :          * with a single arg.  That's useful as it would allow the OR
    3531              :          * condition to be replaced with its single argument which may allow
    3532              :          * use of an index for faster filtering on the remaining condition.
    3533              :          */
    3534         4867 :         foreach(lc, ((BoolExpr *) restrictinfo->orclause)->args)
    3535              :         {
    3536         4867 :             Node       *orarg = (Node *) lfirst(lc);
    3537              : 
    3538         4867 :             if (!IsA(orarg, RestrictInfo) ||
    3539         4140 :                 !restriction_is_always_false(root, (RestrictInfo *) orarg))
    3540         4867 :                 return false;
    3541              :         }
    3542            0 :         return true;
    3543              :     }
    3544              : 
    3545       245577 :     return false;
    3546              : }
    3547              : 
    3548              : /*
    3549              :  * distribute_restrictinfo_to_rels
    3550              :  *    Push a completed RestrictInfo into the proper restriction or join
    3551              :  *    clause list(s).
    3552              :  *
    3553              :  * This is the last step of distribute_qual_to_rels() for ordinary qual
    3554              :  * clauses.  Clauses that are interesting for equivalence-class processing
    3555              :  * are diverted to the EC machinery, but may ultimately get fed back here.
    3556              :  */
    3557              : void
    3558       243269 : distribute_restrictinfo_to_rels(PlannerInfo *root,
    3559              :                                 RestrictInfo *restrictinfo)
    3560              : {
    3561       243269 :     Relids      relids = restrictinfo->required_relids;
    3562              : 
    3563       243269 :     if (!bms_is_empty(relids))
    3564              :     {
    3565              :         int         relid;
    3566              : 
    3567       243269 :         if (bms_get_singleton_member(relids, &relid))
    3568              :         {
    3569              :             /*
    3570              :              * There is only one relation participating in the clause, so it
    3571              :              * is a restriction clause for that relation.
    3572              :              */
    3573       207336 :             add_base_clause_to_rel(root, relid, restrictinfo);
    3574              :         }
    3575              :         else
    3576              :         {
    3577              :             /*
    3578              :              * The clause is a join clause, since there is more than one rel
    3579              :              * in its relid set.
    3580              :              */
    3581              : 
    3582              :             /*
    3583              :              * Check for hashjoinable operators.  (We don't bother setting the
    3584              :              * hashjoin info except in true join clauses.)
    3585              :              */
    3586        35933 :             check_hashjoinable(restrictinfo);
    3587              : 
    3588              :             /*
    3589              :              * Likewise, check if the clause is suitable to be used with a
    3590              :              * Memoize node to cache inner tuples during a parameterized
    3591              :              * nested loop.
    3592              :              */
    3593        35933 :             check_memoizable(restrictinfo);
    3594              : 
    3595              :             /*
    3596              :              * Add clause to the join lists of all the relevant relations.
    3597              :              */
    3598        35933 :             add_join_clause_to_rels(root, restrictinfo, relids);
    3599              :         }
    3600              :     }
    3601              :     else
    3602              :     {
    3603              :         /*
    3604              :          * clause references no rels, and therefore we have no place to attach
    3605              :          * it.  Shouldn't get here if callers are working properly.
    3606              :          */
    3607            0 :         elog(ERROR, "cannot cope with variable-free clause");
    3608              :     }
    3609       243269 : }
    3610              : 
    3611              : /*
    3612              :  * process_implied_equality
    3613              :  *    Create a restrictinfo item that says "item1 op item2", and push it
    3614              :  *    into the appropriate lists.  (In practice opno is always a btree
    3615              :  *    equality operator.)
    3616              :  *
    3617              :  * "qualscope" is the nominal syntactic level to impute to the restrictinfo.
    3618              :  * This must contain at least all the rels used in the expressions, but it
    3619              :  * is used only to set the qual application level when both exprs are
    3620              :  * variable-free.  (Hence, it should usually match the join domain in which
    3621              :  * the clause applies.)  Otherwise the qual is applied at the lowest join
    3622              :  * level that provides all its variables.
    3623              :  *
    3624              :  * "security_level" is the security level to assign to the new restrictinfo.
    3625              :  *
    3626              :  * "both_const" indicates whether both items are known pseudo-constant;
    3627              :  * in this case it is worth applying eval_const_expressions() in case we
    3628              :  * can produce constant TRUE or constant FALSE.  (Otherwise it's not,
    3629              :  * because the expressions went through eval_const_expressions already.)
    3630              :  *
    3631              :  * Returns the generated RestrictInfo, if any.  The result will be NULL
    3632              :  * if both_const is true and we successfully reduced the clause to
    3633              :  * constant TRUE.
    3634              :  *
    3635              :  * Note: this function will copy item1 and item2, but it is caller's
    3636              :  * responsibility to make sure that the Relids parameters are fresh copies
    3637              :  * not shared with other uses.
    3638              :  *
    3639              :  * Note: we do not do initialize_mergeclause_eclasses() here.  It is
    3640              :  * caller's responsibility that left_ec/right_ec be set as necessary.
    3641              :  */
    3642              : RestrictInfo *
    3643        18929 : process_implied_equality(PlannerInfo *root,
    3644              :                          Oid opno,
    3645              :                          Oid collation,
    3646              :                          Expr *item1,
    3647              :                          Expr *item2,
    3648              :                          Relids qualscope,
    3649              :                          Index security_level,
    3650              :                          bool both_const)
    3651              : {
    3652              :     RestrictInfo *restrictinfo;
    3653              :     Node       *clause;
    3654              :     Relids      relids;
    3655        18929 :     bool        pseudoconstant = false;
    3656              : 
    3657              :     /*
    3658              :      * Build the new clause.  Copy to ensure it shares no substructure with
    3659              :      * original (this is necessary in case there are subselects in there...)
    3660              :      */
    3661        18929 :     clause = (Node *) make_opclause(opno,
    3662              :                                     BOOLOID,    /* opresulttype */
    3663              :                                     false,  /* opretset */
    3664        18929 :                                     copyObject(item1),
    3665        18929 :                                     copyObject(item2),
    3666              :                                     InvalidOid,
    3667              :                                     collation);
    3668              : 
    3669              :     /* If both constant, try to reduce to a boolean constant. */
    3670        18929 :     if (both_const)
    3671              :     {
    3672           66 :         clause = eval_const_expressions(root, clause);
    3673              : 
    3674              :         /* If we produced const TRUE, just drop the clause */
    3675           66 :         if (clause && IsA(clause, Const))
    3676              :         {
    3677           63 :             Const      *cclause = (Const *) clause;
    3678              : 
    3679              :             Assert(cclause->consttype == BOOLOID);
    3680           63 :             if (!cclause->constisnull && DatumGetBool(cclause->constvalue))
    3681            0 :                 return NULL;
    3682              :         }
    3683              :     }
    3684              : 
    3685              :     /*
    3686              :      * The rest of this is a very cut-down version of distribute_qual_to_rels.
    3687              :      * We can skip most of the work therein, but there are a couple of special
    3688              :      * cases we still have to handle.
    3689              :      *
    3690              :      * Retrieve all relids mentioned within the possibly-simplified clause.
    3691              :      */
    3692        18929 :     relids = pull_varnos(root, clause);
    3693              :     Assert(bms_is_subset(relids, qualscope));
    3694              : 
    3695              :     /*
    3696              :      * If the clause is variable-free, our normal heuristic for pushing it
    3697              :      * down to just the mentioned rels doesn't work, because there are none.
    3698              :      * Apply it as a gating qual at the appropriate level (see comments for
    3699              :      * get_join_domain_min_rels).
    3700              :      */
    3701        18929 :     if (bms_is_empty(relids))
    3702              :     {
    3703              :         /* eval at join domain's safe level */
    3704           66 :         relids = get_join_domain_min_rels(root, qualscope);
    3705              :         /* mark as gating qual */
    3706           66 :         pseudoconstant = true;
    3707              :         /* tell createplan.c to check for gating quals */
    3708           66 :         root->hasPseudoConstantQuals = true;
    3709              :     }
    3710              : 
    3711              :     /*
    3712              :      * Build the RestrictInfo node itself.
    3713              :      */
    3714        18929 :     restrictinfo = make_restrictinfo(root,
    3715              :                                      (Expr *) clause,
    3716              :                                      true,  /* is_pushed_down */
    3717              :                                      false, /* !has_clone */
    3718              :                                      false, /* !is_clone */
    3719              :                                      pseudoconstant,
    3720              :                                      security_level,
    3721              :                                      relids,
    3722              :                                      NULL,  /* incompatible_relids */
    3723              :                                      NULL); /* outer_relids */
    3724              : 
    3725              :     /*
    3726              :      * If it's a join clause, add vars used in the clause to targetlists of
    3727              :      * their relations, so that they will be emitted by the plan nodes that
    3728              :      * scan those relations (else they won't be available at the join node!).
    3729              :      *
    3730              :      * Typically, we'd have already done this when the component expressions
    3731              :      * were first seen by distribute_qual_to_rels; but it is possible that
    3732              :      * some of the Vars could have missed having that done because they only
    3733              :      * appeared in single-relation clauses originally.  So do it here for
    3734              :      * safety.
    3735              :      *
    3736              :      * See also rebuild_joinclause_attr_needed, which has to partially repeat
    3737              :      * this work after removal of an outer join.  (Since we will put this
    3738              :      * clause into the joininfo lists, that function needn't do any extra work
    3739              :      * to find it.)
    3740              :      */
    3741        18929 :     if (bms_membership(relids) == BMS_MULTIPLE)
    3742              :     {
    3743           30 :         List       *vars = pull_var_clause(clause,
    3744              :                                            PVC_RECURSE_AGGREGATES |
    3745              :                                            PVC_RECURSE_WINDOWFUNCS |
    3746              :                                            PVC_INCLUDE_PLACEHOLDERS);
    3747              : 
    3748           30 :         add_vars_to_targetlist(root, vars, relids);
    3749           30 :         list_free(vars);
    3750              :     }
    3751              : 
    3752              :     /*
    3753              :      * Check mergejoinability.  This will usually succeed, since the op came
    3754              :      * from an EquivalenceClass; but we could have reduced the original clause
    3755              :      * to a constant.
    3756              :      */
    3757        18929 :     check_mergejoinable(restrictinfo);
    3758              : 
    3759              :     /*
    3760              :      * Note we don't do initialize_mergeclause_eclasses(); the caller can
    3761              :      * handle that much more cheaply than we can.  It's okay to call
    3762              :      * distribute_restrictinfo_to_rels() before that happens.
    3763              :      */
    3764              : 
    3765              :     /*
    3766              :      * Push the new clause into all the appropriate restrictinfo lists.
    3767              :      */
    3768        18929 :     distribute_restrictinfo_to_rels(root, restrictinfo);
    3769              : 
    3770        18929 :     return restrictinfo;
    3771              : }
    3772              : 
    3773              : /*
    3774              :  * build_implied_join_equality --- build a RestrictInfo for a derived equality
    3775              :  *
    3776              :  * This overlaps the functionality of process_implied_equality(), but we
    3777              :  * must not push the RestrictInfo into the joininfo tree.
    3778              :  *
    3779              :  * Note: this function will copy item1 and item2, but it is caller's
    3780              :  * responsibility to make sure that the Relids parameters are fresh copies
    3781              :  * not shared with other uses.
    3782              :  *
    3783              :  * Note: we do not do initialize_mergeclause_eclasses() here.  It is
    3784              :  * caller's responsibility that left_ec/right_ec be set as necessary.
    3785              :  */
    3786              : RestrictInfo *
    3787        44764 : build_implied_join_equality(PlannerInfo *root,
    3788              :                             Oid opno,
    3789              :                             Oid collation,
    3790              :                             Expr *item1,
    3791              :                             Expr *item2,
    3792              :                             Relids qualscope,
    3793              :                             Index security_level)
    3794              : {
    3795              :     RestrictInfo *restrictinfo;
    3796              :     Expr       *clause;
    3797              : 
    3798              :     /*
    3799              :      * Build the new clause.  Copy to ensure it shares no substructure with
    3800              :      * original (this is necessary in case there are subselects in there...)
    3801              :      */
    3802        44764 :     clause = make_opclause(opno,
    3803              :                            BOOLOID, /* opresulttype */
    3804              :                            false,   /* opretset */
    3805        44764 :                            copyObject(item1),
    3806        44764 :                            copyObject(item2),
    3807              :                            InvalidOid,
    3808              :                            collation);
    3809              : 
    3810              :     /*
    3811              :      * Build the RestrictInfo node itself.
    3812              :      */
    3813        44764 :     restrictinfo = make_restrictinfo(root,
    3814              :                                      clause,
    3815              :                                      true,  /* is_pushed_down */
    3816              :                                      false, /* !has_clone */
    3817              :                                      false, /* !is_clone */
    3818              :                                      false, /* pseudoconstant */
    3819              :                                      security_level,    /* security_level */
    3820              :                                      qualscope, /* required_relids */
    3821              :                                      NULL,  /* incompatible_relids */
    3822              :                                      NULL); /* outer_relids */
    3823              : 
    3824              :     /* Set mergejoinability/hashjoinability flags */
    3825        44764 :     check_mergejoinable(restrictinfo);
    3826        44764 :     check_hashjoinable(restrictinfo);
    3827        44764 :     check_memoizable(restrictinfo);
    3828              : 
    3829        44764 :     return restrictinfo;
    3830              : }
    3831              : 
    3832              : /*
    3833              :  * get_join_domain_min_rels
    3834              :  *    Identify the appropriate join level for derived quals belonging
    3835              :  *    to the join domain with the given relids.
    3836              :  *
    3837              :  * When we derive a pseudoconstant (Var-free) clause from an EquivalenceClass,
    3838              :  * we'd ideally apply the clause at the top level of the EC's join domain.
    3839              :  * However, if there are any outer joins inside that domain that get commuted
    3840              :  * with joins outside it, that leads to not finding a correct place to apply
    3841              :  * the clause.  Instead, remove any lower outer joins from the relid set,
    3842              :  * and apply the clause to just the remaining rels.  This still results in a
    3843              :  * correct answer, since if the clause produces FALSE then the LHS of these
    3844              :  * joins will be empty leading to an empty join result.
    3845              :  *
    3846              :  * However, there's no need to remove outer joins if this is the top-level
    3847              :  * join domain of the query, since then there's nothing else to commute with.
    3848              :  *
    3849              :  * Note: it's tempting to use this in distribute_qual_to_rels where it's
    3850              :  * dealing with pseudoconstant quals; but we can't because the necessary
    3851              :  * SpecialJoinInfos aren't all formed at that point.
    3852              :  *
    3853              :  * The result is always freshly palloc'd; we do not modify domain_relids.
    3854              :  */
    3855              : static Relids
    3856           66 : get_join_domain_min_rels(PlannerInfo *root, Relids domain_relids)
    3857              : {
    3858           66 :     Relids      result = bms_copy(domain_relids);
    3859              :     ListCell   *lc;
    3860              : 
    3861              :     /* Top-level join domain? */
    3862           66 :     if (bms_equal(result, root->all_query_rels))
    3863           33 :         return result;
    3864              : 
    3865              :     /* Nope, look for lower outer joins that could potentially commute out */
    3866           69 :     foreach(lc, root->join_info_list)
    3867              :     {
    3868           36 :         SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
    3869              : 
    3870           72 :         if (sjinfo->jointype == JOIN_LEFT &&
    3871           36 :             bms_is_member(sjinfo->ojrelid, result))
    3872              :         {
    3873            3 :             result = bms_del_member(result, sjinfo->ojrelid);
    3874            3 :             result = bms_del_members(result, sjinfo->syn_righthand);
    3875              :         }
    3876              :     }
    3877           33 :     return result;
    3878              : }
    3879              : 
    3880              : 
    3881              : /*
    3882              :  * rebuild_joinclause_attr_needed
    3883              :  *    Put back attr_needed bits for Vars/PHVs needed for join clauses.
    3884              :  *
    3885              :  * This is used to rebuild attr_needed/ph_needed sets after removal of a
    3886              :  * useless outer join.  It should match what distribute_qual_to_rels did,
    3887              :  * except that we call add_vars_to_attr_needed not add_vars_to_targetlist.
    3888              :  */
    3889              : void
    3890         6260 : rebuild_joinclause_attr_needed(PlannerInfo *root)
    3891              : {
    3892              :     /*
    3893              :      * We must examine all join clauses, but there's no value in processing
    3894              :      * any join clause more than once.  So it's slightly annoying that we have
    3895              :      * to find them via the per-base-relation joininfo lists.  Avoid duplicate
    3896              :      * processing by tracking the rinfo_serial numbers of join clauses we've
    3897              :      * already seen.  (This doesn't work for is_clone clauses, so we must
    3898              :      * waste effort on them.)
    3899              :      */
    3900         6260 :     Bitmapset  *seen_serials = NULL;
    3901              :     Index       rti;
    3902              : 
    3903              :     /* Scan all baserels for join clauses */
    3904        41136 :     for (rti = 1; rti < root->simple_rel_array_size; rti++)
    3905              :     {
    3906        34876 :         RelOptInfo *brel = root->simple_rel_array[rti];
    3907              :         ListCell   *lc;
    3908              : 
    3909        34876 :         if (brel == NULL)
    3910        23516 :             continue;
    3911        11360 :         if (brel->reloptkind != RELOPT_BASEREL)
    3912            0 :             continue;
    3913              : 
    3914        16801 :         foreach(lc, brel->joininfo)
    3915              :         {
    3916         5441 :             RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    3917         5441 :             Relids      relids = rinfo->required_relids;
    3918              : 
    3919         5441 :             if (!rinfo->is_clone)    /* else serial number is not unique */
    3920              :             {
    3921         5405 :                 if (bms_is_member(rinfo->rinfo_serial, seen_serials))
    3922         2884 :                     continue;   /* saw it already */
    3923         2521 :                 seen_serials = bms_add_member(seen_serials,
    3924              :                                               rinfo->rinfo_serial);
    3925              :             }
    3926              : 
    3927         2557 :             if (bms_membership(relids) == BMS_MULTIPLE)
    3928              :             {
    3929         2557 :                 List       *vars = pull_var_clause((Node *) rinfo->clause,
    3930              :                                                    PVC_RECURSE_AGGREGATES |
    3931              :                                                    PVC_RECURSE_WINDOWFUNCS |
    3932              :                                                    PVC_INCLUDE_PLACEHOLDERS);
    3933              :                 Relids      where_needed;
    3934              : 
    3935         2557 :                 if (rinfo->is_clone)
    3936           36 :                     where_needed = bms_intersect(relids, root->all_baserels);
    3937              :                 else
    3938         2521 :                     where_needed = relids;
    3939         2557 :                 add_vars_to_attr_needed(root, vars, where_needed);
    3940         2557 :                 list_free(vars);
    3941              :             }
    3942              :         }
    3943              :     }
    3944         6260 : }
    3945              : 
    3946              : 
    3947              : /*
    3948              :  * match_foreign_keys_to_quals
    3949              :  *      Match foreign-key constraints to equivalence classes and join quals
    3950              :  *
    3951              :  * The idea here is to see which query join conditions match equality
    3952              :  * constraints of a foreign-key relationship.  For such join conditions,
    3953              :  * we can use the FK semantics to make selectivity estimates that are more
    3954              :  * reliable than estimating from statistics, especially for multiple-column
    3955              :  * FKs, where the normal assumption of independent conditions tends to fail.
    3956              :  *
    3957              :  * In this function we annotate the ForeignKeyOptInfos in root->fkey_list
    3958              :  * with info about which eclasses and join qual clauses they match, and
    3959              :  * discard any ForeignKeyOptInfos that are irrelevant for the query.
    3960              :  */
    3961              : void
    3962       172436 : match_foreign_keys_to_quals(PlannerInfo *root)
    3963              : {
    3964       172436 :     List       *newlist = NIL;
    3965              :     ListCell   *lc;
    3966              : 
    3967       173326 :     foreach(lc, root->fkey_list)
    3968              :     {
    3969          890 :         ForeignKeyOptInfo *fkinfo = (ForeignKeyOptInfo *) lfirst(lc);
    3970              :         RelOptInfo *con_rel;
    3971              :         RelOptInfo *ref_rel;
    3972              :         int         colno;
    3973              : 
    3974              :         /*
    3975              :          * Either relid might identify a rel that is in the query's rtable but
    3976              :          * isn't referenced by the jointree, or has been removed by join
    3977              :          * removal, so that it won't have a RelOptInfo.  Hence don't use
    3978              :          * find_base_rel() here.  We can ignore such FKs.
    3979              :          */
    3980          890 :         if (fkinfo->con_relid >= root->simple_rel_array_size ||
    3981          890 :             fkinfo->ref_relid >= root->simple_rel_array_size)
    3982            0 :             continue;           /* just paranoia */
    3983          890 :         con_rel = root->simple_rel_array[fkinfo->con_relid];
    3984          890 :         if (con_rel == NULL)
    3985            6 :             continue;
    3986          884 :         ref_rel = root->simple_rel_array[fkinfo->ref_relid];
    3987          884 :         if (ref_rel == NULL)
    3988           12 :             continue;
    3989              : 
    3990              :         /*
    3991              :          * Ignore FK unless both rels are baserels.  This gets rid of FKs that
    3992              :          * link to inheritance child rels (otherrels).
    3993              :          */
    3994          872 :         if (con_rel->reloptkind != RELOPT_BASEREL ||
    3995          872 :             ref_rel->reloptkind != RELOPT_BASEREL)
    3996            0 :             continue;
    3997              : 
    3998              :         /*
    3999              :          * Scan the columns and try to match them to eclasses and quals.
    4000              :          *
    4001              :          * Note: for simple inner joins, any match should be in an eclass.
    4002              :          * "Loose" quals that syntactically match an FK equality must have
    4003              :          * been rejected for EC status because they are outer-join quals or
    4004              :          * similar.  We can still consider them to match the FK.
    4005              :          */
    4006         2022 :         for (colno = 0; colno < fkinfo->nkeys; colno++)
    4007              :         {
    4008              :             EquivalenceClass *ec;
    4009              :             AttrNumber  con_attno,
    4010              :                         ref_attno;
    4011              :             Oid         fpeqop;
    4012              :             ListCell   *lc2;
    4013              : 
    4014         1150 :             ec = match_eclasses_to_foreign_key_col(root, fkinfo, colno);
    4015              :             /* Don't bother looking for loose quals if we got an EC match */
    4016         1150 :             if (ec != NULL)
    4017              :             {
    4018          171 :                 fkinfo->nmatched_ec++;
    4019          171 :                 if (ec->ec_has_const)
    4020           37 :                     fkinfo->nconst_ec++;
    4021          171 :                 continue;
    4022              :             }
    4023              : 
    4024              :             /*
    4025              :              * Scan joininfo list for relevant clauses.  Either rel's joininfo
    4026              :              * list would do equally well; we use con_rel's.
    4027              :              */
    4028          979 :             con_attno = fkinfo->conkey[colno];
    4029          979 :             ref_attno = fkinfo->confkey[colno];
    4030          979 :             fpeqop = InvalidOid;    /* we'll look this up only if needed */
    4031              : 
    4032         2556 :             foreach(lc2, con_rel->joininfo)
    4033              :             {
    4034         1577 :                 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc2);
    4035         1577 :                 OpExpr     *clause = (OpExpr *) rinfo->clause;
    4036              :                 Var        *leftvar;
    4037              :                 Var        *rightvar;
    4038              : 
    4039              :                 /* Only binary OpExprs are useful for consideration */
    4040         3154 :                 if (!IsA(clause, OpExpr) ||
    4041         1577 :                     list_length(clause->args) != 2)
    4042            0 :                     continue;
    4043         1577 :                 leftvar = (Var *) get_leftop((Expr *) clause);
    4044         1577 :                 rightvar = (Var *) get_rightop((Expr *) clause);
    4045              : 
    4046              :                 /* Operands must be Vars, possibly with RelabelType */
    4047         1700 :                 while (leftvar && IsA(leftvar, RelabelType))
    4048          123 :                     leftvar = (Var *) ((RelabelType *) leftvar)->arg;
    4049         1577 :                 if (!(leftvar && IsA(leftvar, Var)))
    4050            0 :                     continue;
    4051         1691 :                 while (rightvar && IsA(rightvar, RelabelType))
    4052          114 :                     rightvar = (Var *) ((RelabelType *) rightvar)->arg;
    4053         1577 :                 if (!(rightvar && IsA(rightvar, Var)))
    4054           15 :                     continue;
    4055              : 
    4056              :                 /* Now try to match the vars to the current foreign key cols */
    4057         1562 :                 if (fkinfo->ref_relid == leftvar->varno &&
    4058         1499 :                     ref_attno == leftvar->varattno &&
    4059          856 :                     fkinfo->con_relid == rightvar->varno &&
    4060          856 :                     con_attno == rightvar->varattno)
    4061              :                 {
    4062              :                     /* Vars match, but is it the right operator? */
    4063          817 :                     if (clause->opno == fkinfo->conpfeqop[colno])
    4064              :                     {
    4065          817 :                         fkinfo->rinfos[colno] = lappend(fkinfo->rinfos[colno],
    4066              :                                                         rinfo);
    4067          817 :                         fkinfo->nmatched_ri++;
    4068              :                     }
    4069              :                 }
    4070          745 :                 else if (fkinfo->ref_relid == rightvar->varno &&
    4071           45 :                          ref_attno == rightvar->varattno &&
    4072           18 :                          fkinfo->con_relid == leftvar->varno &&
    4073           18 :                          con_attno == leftvar->varattno)
    4074              :                 {
    4075              :                     /*
    4076              :                      * Reverse match, must check commutator operator.  Look it
    4077              :                      * up if we didn't already.  (In the worst case we might
    4078              :                      * do multiple lookups here, but that would require an FK
    4079              :                      * equality operator without commutator, which is
    4080              :                      * unlikely.)
    4081              :                      */
    4082           18 :                     if (!OidIsValid(fpeqop))
    4083           18 :                         fpeqop = get_commutator(fkinfo->conpfeqop[colno]);
    4084           18 :                     if (clause->opno == fpeqop)
    4085              :                     {
    4086           18 :                         fkinfo->rinfos[colno] = lappend(fkinfo->rinfos[colno],
    4087              :                                                         rinfo);
    4088           18 :                         fkinfo->nmatched_ri++;
    4089              :                     }
    4090              :                 }
    4091              :             }
    4092              :             /* If we found any matching loose quals, count col as matched */
    4093          979 :             if (fkinfo->rinfos[colno])
    4094          835 :                 fkinfo->nmatched_rcols++;
    4095              :         }
    4096              : 
    4097              :         /*
    4098              :          * Currently, we drop multicolumn FKs that aren't fully matched to the
    4099              :          * query.  Later we might figure out how to derive some sort of
    4100              :          * estimate from them, in which case this test should be weakened to
    4101              :          * "if ((fkinfo->nmatched_ec + fkinfo->nmatched_rcols) > 0)".
    4102              :          */
    4103          872 :         if ((fkinfo->nmatched_ec + fkinfo->nmatched_rcols) == fkinfo->nkeys)
    4104          740 :             newlist = lappend(newlist, fkinfo);
    4105              :     }
    4106              :     /* Replace fkey_list, thereby discarding any useless entries */
    4107       172436 :     root->fkey_list = newlist;
    4108       172436 : }
    4109              : 
    4110              : 
    4111              : /*****************************************************************************
    4112              :  *
    4113              :  *   CHECKS FOR MERGEJOINABLE AND HASHJOINABLE CLAUSES
    4114              :  *
    4115              :  *****************************************************************************/
    4116              : 
    4117              : /*
    4118              :  * check_mergejoinable
    4119              :  *    If the restrictinfo's clause is mergejoinable, set the mergejoin
    4120              :  *    info fields in the restrictinfo.
    4121              :  *
    4122              :  *    Currently, we support mergejoin for binary opclauses where
    4123              :  *    the operator is a mergejoinable operator.  The arguments can be
    4124              :  *    anything --- as long as there are no volatile functions in them.
    4125              :  */
    4126              : static void
    4127       345949 : check_mergejoinable(RestrictInfo *restrictinfo)
    4128              : {
    4129       345949 :     Expr       *clause = restrictinfo->clause;
    4130              :     Oid         opno;
    4131              :     Node       *leftarg;
    4132              : 
    4133       345949 :     if (restrictinfo->pseudoconstant)
    4134         5527 :         return;
    4135       340422 :     if (!is_opclause(clause))
    4136        42377 :         return;
    4137       298045 :     if (list_length(((OpExpr *) clause)->args) != 2)
    4138           12 :         return;
    4139              : 
    4140       298033 :     opno = ((OpExpr *) clause)->opno;
    4141       298033 :     leftarg = linitial(((OpExpr *) clause)->args);
    4142              : 
    4143       298033 :     if (op_mergejoinable(opno, exprType(leftarg)) &&
    4144       255696 :         !contain_volatile_functions((Node *) restrictinfo))
    4145       255680 :         restrictinfo->mergeopfamilies = get_mergejoin_opfamilies(opno);
    4146              : 
    4147              :     /*
    4148              :      * Note: op_mergejoinable is just a hint; if we fail to find the operator
    4149              :      * in any btree opfamilies, mergeopfamilies remains NIL and so the clause
    4150              :      * is not treated as mergejoinable.
    4151              :      */
    4152              : }
    4153              : 
    4154              : /*
    4155              :  * check_hashjoinable
    4156              :  *    If the restrictinfo's clause is hashjoinable, set the hashjoin
    4157              :  *    info fields in the restrictinfo.
    4158              :  *
    4159              :  *    Currently, we support hashjoin for binary opclauses where
    4160              :  *    the operator is a hashjoinable operator.  The arguments can be
    4161              :  *    anything --- as long as there are no volatile functions in them.
    4162              :  */
    4163              : static void
    4164        80697 : check_hashjoinable(RestrictInfo *restrictinfo)
    4165              : {
    4166        80697 :     Expr       *clause = restrictinfo->clause;
    4167              :     Oid         opno;
    4168              :     Node       *leftarg;
    4169              : 
    4170        80697 :     if (restrictinfo->pseudoconstant)
    4171         1775 :         return;
    4172        78922 :     if (!is_opclause(clause))
    4173         4004 :         return;
    4174        74918 :     if (list_length(((OpExpr *) clause)->args) != 2)
    4175            0 :         return;
    4176              : 
    4177        74918 :     opno = ((OpExpr *) clause)->opno;
    4178        74918 :     leftarg = linitial(((OpExpr *) clause)->args);
    4179              : 
    4180        74918 :     if (op_hashjoinable(opno, exprType(leftarg)) &&
    4181        73229 :         !contain_volatile_functions((Node *) restrictinfo))
    4182        73225 :         restrictinfo->hashjoinoperator = opno;
    4183              : }
    4184              : 
    4185              : /*
    4186              :  * check_memoizable
    4187              :  *    If the restrictinfo's clause is suitable to be used for a Memoize node,
    4188              :  *    set the left_hasheqoperator and right_hasheqoperator to the hash equality
    4189              :  *    operator that will be needed during caching.
    4190              :  */
    4191              : static void
    4192        80697 : check_memoizable(RestrictInfo *restrictinfo)
    4193              : {
    4194              :     TypeCacheEntry *typentry;
    4195        80697 :     Expr       *clause = restrictinfo->clause;
    4196              :     Oid         lefttype;
    4197              :     Oid         righttype;
    4198              : 
    4199        80697 :     if (restrictinfo->pseudoconstant)
    4200         1775 :         return;
    4201        78922 :     if (!is_opclause(clause))
    4202         4004 :         return;
    4203        74918 :     if (list_length(((OpExpr *) clause)->args) != 2)
    4204            0 :         return;
    4205              : 
    4206        74918 :     lefttype = exprType(linitial(((OpExpr *) clause)->args));
    4207              : 
    4208        74918 :     typentry = lookup_type_cache(lefttype, TYPECACHE_HASH_PROC |
    4209              :                                  TYPECACHE_EQ_OPR);
    4210              : 
    4211        74918 :     if (OidIsValid(typentry->hash_proc) && OidIsValid(typentry->eq_opr))
    4212        74714 :         restrictinfo->left_hasheqoperator = typentry->eq_opr;
    4213              : 
    4214        74918 :     righttype = exprType(lsecond(((OpExpr *) clause)->args));
    4215              : 
    4216              :     /*
    4217              :      * Lookup the right type, unless it's the same as the left type, in which
    4218              :      * case typentry is already pointing to the required TypeCacheEntry.
    4219              :      */
    4220        74918 :     if (lefttype != righttype)
    4221         1162 :         typentry = lookup_type_cache(righttype, TYPECACHE_HASH_PROC |
    4222              :                                      TYPECACHE_EQ_OPR);
    4223              : 
    4224        74918 :     if (OidIsValid(typentry->hash_proc) && OidIsValid(typentry->eq_opr))
    4225        74612 :         restrictinfo->right_hasheqoperator = typentry->eq_opr;
    4226              : }
        

Generated by: LCOV version 2.0-1