LCOV - code coverage report
Current view: top level - src/backend/optimizer/plan - initsplan.c (source / functions) Hit Total Coverage
Test: PostgreSQL 19devel Lines: 1119 1171 95.6 %
Date: 2025-12-13 10:19:04 Functions: 38 38 100.0 %
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-2025, 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      943128 : add_base_rels_to_query(PlannerInfo *root, Node *jtnode)
     166             : {
     167      943128 :     if (jtnode == NULL)
     168           0 :         return;
     169      943128 :     if (IsA(jtnode, RangeTblRef))
     170             :     {
     171      490452 :         int         varno = ((RangeTblRef *) jtnode)->rtindex;
     172             : 
     173      490452 :         (void) build_simple_rel(root, varno, NULL);
     174             :     }
     175      452676 :     else if (IsA(jtnode, FromExpr))
     176             :     {
     177      351664 :         FromExpr   *f = (FromExpr *) jtnode;
     178             :         ListCell   *l;
     179             : 
     180      753528 :         foreach(l, f->fromlist)
     181      401882 :             add_base_rels_to_query(root, lfirst(l));
     182             :     }
     183      101012 :     else if (IsA(jtnode, JoinExpr))
     184             :     {
     185      101012 :         JoinExpr   *j = (JoinExpr *) jtnode;
     186             : 
     187      101012 :         add_base_rels_to_query(root, j->larg);
     188      101012 :         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      339204 : add_other_rels_to_query(PlannerInfo *root)
     204             : {
     205             :     int         rti;
     206             : 
     207     1039618 :     for (rti = 1; rti < root->simple_rel_array_size; rti++)
     208             :     {
     209      700416 :         RelOptInfo *rel = root->simple_rel_array[rti];
     210      700416 :         RangeTblEntry *rte = root->simple_rte_array[rti];
     211             : 
     212             :         /* there may be empty slots corresponding to non-baserel RTEs */
     213      700416 :         if (rel == NULL)
     214      163772 :             continue;
     215             : 
     216             :         /* Ignore any "otherrels" that were already added. */
     217      536644 :         if (rel->reloptkind != RELOPT_BASEREL)
     218       58256 :             continue;
     219             : 
     220             :         /* If it's marked as inheritable, look for children. */
     221      478388 :         if (rte->inh)
     222       22036 :             expand_inherited_rtentry(root, rel, rte, rti);
     223             :     }
     224      339202 : }
     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      339234 : build_base_rel_tlists(PlannerInfo *root, List *final_tlist)
     243             : {
     244      339234 :     List       *tlist_vars = pull_var_clause((Node *) final_tlist,
     245             :                                              PVC_RECURSE_AGGREGATES |
     246             :                                              PVC_RECURSE_WINDOWFUNCS |
     247             :                                              PVC_INCLUDE_PLACEHOLDERS);
     248             : 
     249      339234 :     if (tlist_vars != NIL)
     250             :     {
     251      315432 :         add_vars_to_targetlist(root, tlist_vars, bms_make_singleton(0));
     252      315432 :         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      339234 :     if (root->parse->havingQual)
     260             :     {
     261         932 :         List       *having_vars = pull_var_clause(root->parse->havingQual,
     262             :                                                   PVC_RECURSE_AGGREGATES |
     263             :                                                   PVC_INCLUDE_PLACEHOLDERS);
     264             : 
     265         932 :         if (having_vars != NIL)
     266             :         {
     267         812 :             add_vars_to_targetlist(root, having_vars,
     268             :                                    bms_make_singleton(0));
     269         812 :             list_free(having_vars);
     270             :         }
     271             :     }
     272      339234 : }
     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      649890 : 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     2278430 :     foreach(temp, vars)
     297             :     {
     298     1628540 :         Node       *node = (Node *) lfirst(temp);
     299             : 
     300     1628540 :         if (IsA(node, Var))
     301             :         {
     302     1625360 :             Var        *var = (Var *) node;
     303     1625360 :             RelOptInfo *rel = find_base_rel(root, var->varno);
     304     1625360 :             int         attno = var->varattno;
     305             : 
     306     1625360 :             if (bms_is_subset(where_needed, rel->relids))
     307        1408 :                 continue;
     308             :             Assert(attno >= rel->min_attr && attno <= rel->max_attr);
     309     1623952 :             attno -= rel->min_attr;
     310     1623952 :             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     1222192 :                 var = copyObject(var);
     320     1222192 :                 var->varnullingrels = NULL;
     321     1222192 :                 rel->reltarget->exprs = lappend(rel->reltarget->exprs, var);
     322             :                 /* reltarget cost and width will be computed later */
     323             :             }
     324     1623952 :             rel->attr_needed[attno] = bms_add_members(rel->attr_needed[attno],
     325             :                                                       where_needed);
     326             :         }
     327        3180 :         else if (IsA(node, PlaceHolderVar))
     328             :         {
     329        3180 :             PlaceHolderVar *phv = (PlaceHolderVar *) node;
     330        3180 :             PlaceHolderInfo *phinfo = find_placeholder_info(root, phv);
     331             : 
     332        3180 :             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      649890 : }
     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       14102 : 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       32638 :     foreach(temp, vars)
     368             :     {
     369       18536 :         Node       *node = (Node *) lfirst(temp);
     370             : 
     371       18536 :         if (IsA(node, Var))
     372             :         {
     373       18440 :             Var        *var = (Var *) node;
     374       18440 :             RelOptInfo *rel = find_base_rel(root, var->varno);
     375       18440 :             int         attno = var->varattno;
     376             : 
     377       18440 :             if (bms_is_subset(where_needed, rel->relids))
     378         856 :                 continue;
     379             :             Assert(attno >= rel->min_attr && attno <= rel->max_attr);
     380       17584 :             attno -= rel->min_attr;
     381       17584 :             rel->attr_needed[attno] = bms_add_members(rel->attr_needed[attno],
     382             :                                                       where_needed);
     383             :         }
     384          96 :         else if (IsA(node, PlaceHolderVar))
     385             :         {
     386          96 :             PlaceHolderVar *phv = (PlaceHolderVar *) node;
     387          96 :             PlaceHolderInfo *phinfo = find_placeholder_info(root, phv);
     388             : 
     389          96 :             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       14102 : }
     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      339204 : remove_useless_groupby_columns(PlannerInfo *root)
     420             : {
     421      339204 :     Query      *parse = root->parse;
     422             :     Bitmapset **groupbyattnos;
     423             :     Bitmapset **surplusvars;
     424      339204 :     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      339204 :     if (list_length(root->processed_groupClause) < 2)
     430      337076 :         return;
     431             : 
     432             :     /* Don't fiddle with the GROUP BY clause if the query has grouping sets */
     433        2128 :     if (parse->groupingSets)
     434         686 :         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        1442 :     groupbyattnos = palloc0_array(Bitmapset *, list_length(parse->rtable) + 1);
     442        5218 :     foreach(lc, root->processed_groupClause)
     443             :     {
     444        3776 :         SortGroupClause *sgc = lfirst_node(SortGroupClause, lc);
     445        3776 :         TargetEntry *tle = get_sortgroupclause_tle(sgc, parse->targetList);
     446        3776 :         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        3776 :         if (!IsA(var, Var) ||
     457        2966 :             var->varlevelsup > 0)
     458         810 :             continue;
     459             : 
     460             :         /* OK, remember we have this Var */
     461        2966 :         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        2966 :         tryremove |= !bms_is_empty(groupbyattnos[relid]);
     470        2966 :         groupbyattnos[relid] = bms_add_member(groupbyattnos[relid],
     471        2966 :                                               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        1442 :     if (!tryremove)
     479         452 :         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         990 :     surplusvars = NULL;         /* don't allocate array unless required */
     488         990 :     relid = 0;
     489        4148 :     foreach(lc, parse->rtable)
     490             :     {
     491        3158 :         RangeTblEntry *rte = lfirst_node(RangeTblEntry, lc);
     492             :         RelOptInfo *rel;
     493             :         Bitmapset  *relattnos;
     494        3158 :         Bitmapset  *best_keycolumns = NULL;
     495        3158 :         int32       best_nkeycolumns = PG_INT32_MAX;
     496             : 
     497        3158 :         relid++;
     498             : 
     499             :         /* Only plain relations could have primary-key constraints */
     500        3158 :         if (rte->rtekind != RTE_RELATION)
     501        1606 :             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        1552 :         if (rte->inh && rte->relkind != RELKIND_PARTITIONED_TABLE)
     509          18 :             continue;
     510             : 
     511             :         /* Nothing to do unless this rel has multiple Vars in GROUP BY */
     512        1534 :         relattnos = groupbyattnos[relid];
     513        1534 :         if (bms_membership(relattnos) != BMS_MULTIPLE)
     514         580 :             continue;
     515             : 
     516         954 :         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        2954 :         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        1046 :             if (!index->unique || !index->immediate || index->indpred != NIL)
     534         410 :                 continue;
     535             : 
     536             :             /* For simplicity, we currently don't support expression indexes */
     537         636 :             if (index->indexprs != NIL)
     538           0 :                 continue;
     539             : 
     540         636 :             ind_attnos = NULL;
     541         636 :             nulls_check_ok = true;
     542        1604 :             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         974 :                 if (!index->nullsnotdistinct &&
     553         968 :                     !bms_is_member(index->indexkeys[i],
     554         968 :                                    rel->notnullattnums))
     555             :                 {
     556           6 :                     nulls_check_ok = false;
     557           6 :                     break;
     558             :                 }
     559             : 
     560             :                 ind_attnos =
     561         968 :                     bms_add_member(ind_attnos,
     562         968 :                                    index->indexkeys[i] -
     563             :                                    FirstLowInvalidHeapAttributeNumber);
     564             :             }
     565             : 
     566         636 :             if (!nulls_check_ok)
     567           6 :                 continue;
     568             : 
     569             :             /*
     570             :              * Skip any indexes where the indexed columns aren't a proper
     571             :              * subset of the GROUP BY.
     572             :              */
     573         630 :             if (bms_subset_compare(ind_attnos, relattnos) != BMS_SUBSET1)
     574         290 :                 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         340 :             if (index->nkeycolumns < best_nkeycolumns)
     585             :             {
     586         322 :                 best_keycolumns = ind_attnos;
     587         322 :                 best_nkeycolumns = index->nkeycolumns;
     588             :             }
     589             :         }
     590             : 
     591             :         /* Did we find a suitable index? */
     592         954 :         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         322 :             if (surplusvars == NULL)
     599         316 :                 surplusvars = palloc0_array(Bitmapset *, list_length(parse->rtable) + 1);
     600             : 
     601             :             /* Remember the attnos of the removable columns */
     602         322 :             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         990 :     if (surplusvars != NULL)
     612             :     {
     613         316 :         List       *new_groupby = NIL;
     614             : 
     615        1298 :         foreach(lc, root->processed_groupClause)
     616             :         {
     617         982 :             SortGroupClause *sgc = lfirst_node(SortGroupClause, lc);
     618         982 :             TargetEntry *tle = get_sortgroupclause_tle(sgc, parse->targetList);
     619         982 :             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         982 :             if (!IsA(var, Var) ||
     626         982 :                 var->varlevelsup > 0 ||
     627         982 :                 !bms_is_member(var->varattno - FirstLowInvalidHeapAttributeNumber,
     628         982 :                                surplusvars[var->varno]))
     629         618 :                 new_groupby = lappend(new_groupby, sgc);
     630             :         }
     631             : 
     632         316 :         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      339204 : setup_eager_aggregation(PlannerInfo *root)
     643             : {
     644             :     /*
     645             :      * Don't apply eager aggregation if disabled by user.
     646             :      */
     647      339204 :     if (!enable_eager_aggregate)
     648         480 :         return;
     649             : 
     650             :     /*
     651             :      * Don't apply eager aggregation if there are no available GROUP BY
     652             :      * clauses.
     653             :      */
     654      338724 :     if (!root->processed_groupClause)
     655      334470 :         return;
     656             : 
     657             :     /*
     658             :      * For now we don't try to support grouping sets.
     659             :      */
     660        4254 :     if (root->parse->groupingSets)
     661         778 :         return;
     662             : 
     663             :     /*
     664             :      * For now we don't try to support DISTINCT or ORDER BY aggregates.
     665             :      */
     666        3476 :     if (root->numOrderedAggs > 0)
     667         192 :         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        3284 :     if (root->hasNonPartialAggs || root->hasNonSerialAggs)
     675         154 :         return;
     676             : 
     677             :     /*
     678             :      * We don't try to apply eager aggregation if there are set-returning
     679             :      * functions in targetlist.
     680             :      */
     681        3130 :     if (root->parse->hasTargetSRFs)
     682          72 :         return;
     683             : 
     684             :     /*
     685             :      * Eager aggregation only makes sense if there are multiple base rels in
     686             :      * the query.
     687             :      */
     688        3058 :     if (bms_membership(root->all_baserels) != BMS_MULTIPLE)
     689        2072 :         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         986 :     if (is_partial_agg_memory_risky(root))
     696           2 :         return;
     697             : 
     698             :     /*
     699             :      * Collect aggregate expressions and plain Vars that appear in the
     700             :      * targetlist and havingQual.
     701             :      */
     702         984 :     create_agg_clause_infos(root);
     703             : 
     704             :     /*
     705             :      * If there are no suitable aggregate expressions, we cannot apply eager
     706             :      * aggregation.
     707             :      */
     708         984 :     if (root->agg_clause_list == NIL)
     709         326 :         return;
     710             : 
     711             :     /*
     712             :      * Collect grouping expressions that appear in grouping clauses.
     713             :      */
     714         658 :     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         986 : is_partial_agg_memory_risky(PlannerInfo *root)
     730             : {
     731             :     ListCell   *lc;
     732             : 
     733        1902 :     foreach(lc, root->aggtransinfos)
     734             :     {
     735         918 :         AggTransInfo *transinfo = lfirst_node(AggTransInfo, lc);
     736             : 
     737         918 :         if (transinfo->aggtransspace < 0)
     738           2 :             return true;
     739             :     }
     740             : 
     741         984 :     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         984 : create_agg_clause_infos(PlannerInfo *root)
     751             : {
     752             :     List       *tlist_exprs;
     753         984 :     List       *agg_clause_list = NIL;
     754         984 :     List       *tlist_vars = NIL;
     755         984 :     Relids      aggregate_relids = NULL;
     756         984 :     bool        eager_agg_applicable = true;
     757             :     ListCell   *lc;
     758             : 
     759             :     Assert(root->agg_clause_list == NIL);
     760             :     Assert(root->tlist_vars == NIL);
     761             : 
     762         984 :     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         984 :     if (root->parse->havingQual != NULL)
     773             :     {
     774             :         List       *having_exprs;
     775             : 
     776          58 :         having_exprs = pull_var_clause((Node *) root->parse->havingQual,
     777             :                                        PVC_INCLUDE_AGGREGATES |
     778             :                                        PVC_RECURSE_PLACEHOLDERS);
     779          58 :         if (having_exprs != NIL)
     780             :         {
     781          58 :             tlist_exprs = list_concat(tlist_exprs, having_exprs);
     782          58 :             list_free(having_exprs);
     783             :         }
     784             :     }
     785             : 
     786        4368 :     foreach(lc, tlist_exprs)
     787             :     {
     788        3432 :         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        3432 :         if (IsA(expr, GroupingFunc))
     795             :         {
     796           0 :             eager_agg_applicable = false;
     797           0 :             break;
     798             :         }
     799             : 
     800             :         /* Collect plain Vars for future reference */
     801        3432 :         if (IsA(expr, Var))
     802             :         {
     803        2510 :             tlist_vars = list_append_unique(tlist_vars, expr);
     804        2510 :             continue;
     805             :         }
     806             : 
     807         922 :         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         922 :         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         922 :         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         922 :         aggregate_relids = bms_add_members(aggregate_relids, agg_eval_at);
     831         922 :         if (bms_is_subset(root->all_baserels, aggregate_relids))
     832             :         {
     833          48 :             eager_agg_applicable = false;
     834          48 :             break;
     835             :         }
     836             : 
     837             :         /* OK, create the AggClauseInfo node */
     838         874 :         ac_info = makeNode(AggClauseInfo);
     839         874 :         ac_info->aggref = aggref;
     840         874 :         ac_info->agg_eval_at = agg_eval_at;
     841             : 
     842             :         /* ... and add it to the list */
     843         874 :         agg_clause_list = list_append_unique(agg_clause_list, ac_info);
     844             :     }
     845             : 
     846         984 :     list_free(tlist_exprs);
     847             : 
     848         984 :     if (eager_agg_applicable)
     849             :     {
     850         936 :         root->agg_clause_list = agg_clause_list;
     851         936 :         root->tlist_vars = tlist_vars;
     852             :     }
     853             :     else
     854             :     {
     855          48 :         list_free_deep(agg_clause_list);
     856          48 :         list_free(tlist_vars);
     857             :     }
     858         984 : }
     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         658 : create_grouping_expr_infos(PlannerInfo *root)
     869             : {
     870         658 :     List       *exprs = NIL;
     871         658 :     List       *sortgrouprefs = NIL;
     872         658 :     List       *ecs = NIL;
     873             :     ListCell   *lc,
     874             :                *lc1,
     875             :                *lc2,
     876             :                *lc3;
     877             : 
     878             :     Assert(root->group_expr_list == NIL);
     879             : 
     880        1306 :     foreach(lc, root->processed_groupClause)
     881             :     {
     882         714 :         SortGroupClause *sgc = lfirst_node(SortGroupClause, lc);
     883         714 :         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         714 :         if (!IsA(tle->expr, Var))
     893          66 :             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         654 :         tce = lookup_type_cache(exprType((Node *) tle->expr),
     906             :                                 TYPECACHE_BTREE_OPFAMILY);
     907         654 :         if (!OidIsValid(tce->btree_opf) ||
     908         654 :             !OidIsValid(tce->btree_opintype))
     909           0 :             return;
     910             : 
     911         654 :         equalimageproc = get_opfamily_proc(tce->btree_opf,
     912             :                                            tce->btree_opintype,
     913             :                                            tce->btree_opintype,
     914             :                                            BTEQUALIMAGE_PROC);
     915         654 :         if (!OidIsValid(equalimageproc) ||
     916         648 :             !DatumGetBool(OidFunctionCall1Coll(equalimageproc,
     917             :                                                tce->typcollation,
     918             :                                                ObjectIdGetDatum(tce->btree_opintype))))
     919           6 :             return;
     920             : 
     921         648 :         exprs = lappend(exprs, tle->expr);
     922         648 :         sortgrouprefs = lappend_int(sortgrouprefs, tle->ressortgroupref);
     923         648 :         ecs = lappend(ecs, get_eclass_for_sortgroupclause(root, sgc, tle->expr));
     924             :     }
     925             : 
     926             :     /*
     927             :      * Construct a GroupingExprInfo for each expression.
     928             :      */
     929        1228 :     forthree(lc1, exprs, lc2, sortgrouprefs, lc3, ecs)
     930             :     {
     931         636 :         Expr       *expr = (Expr *) lfirst(lc1);
     932         636 :         int         sortgroupref = lfirst_int(lc2);
     933         636 :         EquivalenceClass *ec = (EquivalenceClass *) lfirst(lc3);
     934             :         GroupingExprInfo *ge_info;
     935             : 
     936         636 :         ge_info = makeNode(GroupingExprInfo);
     937         636 :         ge_info->expr = (Expr *) copyObject(expr);
     938         636 :         ge_info->sortgroupref = sortgroupref;
     939         636 :         ge_info->ec = ec;
     940             : 
     941         636 :         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         648 : 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         648 :     if (!OidIsValid(sgc->sortop))
     963           0 :         return NULL;
     964             : 
     965             :     /* Find the operator in pg_amop --- failure shouldn't happen */
     966         648 :     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         648 :     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         648 :     equality_op = get_opfamily_member_for_cmptype(opfamily,
     981             :                                                   opcintype,
     982             :                                                   opcintype,
     983             :                                                   COMPARE_EQ);
     984         648 :     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         648 :     opfamilies = get_mergejoin_opfamilies(equality_op);
     988         648 :     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         648 :     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      339204 : find_lateral_references(PlannerInfo *root)
    1026             : {
    1027             :     Index       rti;
    1028             : 
    1029             :     /* We need do nothing if the query contains no LATERAL RTEs */
    1030      339204 :     if (!root->hasLateralRTEs)
    1031      328770 :         return;
    1032             : 
    1033             :     /*
    1034             :      * Examine all baserels (the rel array has been set up by now).
    1035             :      */
    1036       41260 :     for (rti = 1; rti < root->simple_rel_array_size; rti++)
    1037             :     {
    1038       30826 :         RelOptInfo *brel = root->simple_rel_array[rti];
    1039             : 
    1040             :         /* there may be empty slots corresponding to non-baserel RTEs */
    1041       30826 :         if (brel == NULL)
    1042        7052 :             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       23774 :         if (brel->reloptkind != RELOPT_BASEREL)
    1066           0 :             continue;
    1067             : 
    1068       23774 :         extract_lateral_references(root, brel, rti);
    1069             :     }
    1070             : }
    1071             : 
    1072             : static void
    1073       23774 : extract_lateral_references(PlannerInfo *root, RelOptInfo *brel, Index rtindex)
    1074             : {
    1075       23774 :     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       23774 :     if (!rte->lateral)
    1083       13984 :         return;
    1084             : 
    1085             :     /* Fetch the appropriate variables */
    1086        9790 :     if (rte->rtekind == RTE_RELATION)
    1087          36 :         vars = pull_vars_of_level((Node *) rte->tablesample, 0);
    1088        9754 :     else if (rte->rtekind == RTE_SUBQUERY)
    1089         800 :         vars = pull_vars_of_level((Node *) rte->subquery, 1);
    1090        8954 :     else if (rte->rtekind == RTE_FUNCTION)
    1091        8648 :         vars = pull_vars_of_level((Node *) rte->functions, 0);
    1092         306 :     else if (rte->rtekind == RTE_TABLEFUNC)
    1093         234 :         vars = pull_vars_of_level((Node *) rte->tablefunc, 0);
    1094          72 :     else if (rte->rtekind == RTE_VALUES)
    1095          72 :         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        9790 :     if (vars == NIL)
    1103         100 :         return;                 /* nothing to do */
    1104             : 
    1105             :     /* Copy each Var (or PlaceHolderVar) and adjust it to match our level */
    1106        9690 :     newvars = NIL;
    1107       20294 :     foreach(lc, vars)
    1108             :     {
    1109       10604 :         Node       *node = (Node *) lfirst(lc);
    1110             : 
    1111       10604 :         node = copyObject(node);
    1112       10604 :         if (IsA(node, Var))
    1113             :         {
    1114       10478 :             Var        *var = (Var *) node;
    1115             : 
    1116             :             /* Adjustment is easy since it's just one node */
    1117       10478 :             var->varlevelsup = 0;
    1118             :         }
    1119         126 :         else if (IsA(node, PlaceHolderVar))
    1120             :         {
    1121         126 :             PlaceHolderVar *phv = (PlaceHolderVar *) node;
    1122         126 :             int         levelsup = phv->phlevelsup;
    1123             : 
    1124             :             /* Have to work harder to adjust the contained expression too */
    1125         126 :             if (levelsup != 0)
    1126          90 :                 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         126 :             if (levelsup > 0)
    1134          90 :                 phv->phexpr = preprocess_phv_expression(root, phv->phexpr);
    1135             :         }
    1136             :         else
    1137             :             Assert(false);
    1138       10604 :         newvars = lappend(newvars, node);
    1139             :     }
    1140             : 
    1141        9690 :     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        9690 :     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        9690 :     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        9690 :     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       12046 : rebuild_lateral_attr_needed(PlannerInfo *root)
    1175             : {
    1176             :     Index       rti;
    1177             : 
    1178             :     /* We need do nothing if the query contains no LATERAL RTEs */
    1179       12046 :     if (!root->hasLateralRTEs)
    1180       11386 :         return;
    1181             : 
    1182             :     /* Examine the same baserels that find_lateral_references did */
    1183        6814 :     for (rti = 1; rti < root->simple_rel_array_size; rti++)
    1184             :     {
    1185        6154 :         RelOptInfo *brel = root->simple_rel_array[rti];
    1186             :         Relids      where_needed;
    1187             : 
    1188        6154 :         if (brel == NULL)
    1189        4386 :             continue;
    1190        1768 :         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        1768 :         if (brel->lateral_vars == NIL)
    1198        1428 :             continue;
    1199             : 
    1200         340 :         where_needed = bms_make_singleton(rti);
    1201             : 
    1202         340 :         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      339204 : create_lateral_join_info(PlannerInfo *root)
    1213             : {
    1214      339204 :     bool        found_laterals = false;
    1215             :     Index       rti;
    1216             :     ListCell   *lc;
    1217             : 
    1218             :     /* We need do nothing if the query contains no LATERAL RTEs */
    1219      339204 :     if (!root->hasLateralRTEs)
    1220      328770 :         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       41260 :     for (rti = 1; rti < root->simple_rel_array_size; rti++)
    1229             :     {
    1230       30826 :         RelOptInfo *brel = root->simple_rel_array[rti];
    1231             :         Relids      lateral_relids;
    1232             : 
    1233             :         /* there may be empty slots corresponding to non-baserel RTEs */
    1234       30826 :         if (brel == NULL)
    1235        7712 :             continue;
    1236             : 
    1237             :         Assert(brel->relid == rti); /* sanity check on array */
    1238             : 
    1239             :         /* ignore RTEs that are "other rels" */
    1240       23114 :         if (brel->reloptkind != RELOPT_BASEREL)
    1241           0 :             continue;
    1242             : 
    1243       23114 :         lateral_relids = NULL;
    1244             : 
    1245             :         /* consider each laterally-referenced Var or PHV */
    1246       33550 :         foreach(lc, brel->lateral_vars)
    1247             :         {
    1248       10436 :             Node       *node = (Node *) lfirst(lc);
    1249             : 
    1250       10436 :             if (IsA(node, Var))
    1251             :             {
    1252       10310 :                 Var        *var = (Var *) node;
    1253             : 
    1254       10310 :                 found_laterals = true;
    1255       10310 :                 lateral_relids = bms_add_member(lateral_relids,
    1256             :                                                 var->varno);
    1257             :             }
    1258         126 :             else if (IsA(node, PlaceHolderVar))
    1259             :             {
    1260         126 :                 PlaceHolderVar *phv = (PlaceHolderVar *) node;
    1261         126 :                 PlaceHolderInfo *phinfo = find_placeholder_info(root, phv);
    1262             : 
    1263         126 :                 found_laterals = true;
    1264         126 :                 lateral_relids = bms_add_members(lateral_relids,
    1265         126 :                                                  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       23114 :         brel->direct_lateral_relids = lateral_relids;
    1273       23114 :         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       11024 :     foreach(lc, root->placeholder_list)
    1290             :     {
    1291         590 :         PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc);
    1292         590 :         Relids      eval_at = phinfo->ph_eval_at;
    1293             :         Relids      lateral_refs;
    1294             :         int         varno;
    1295             : 
    1296         590 :         if (phinfo->ph_lateral == NULL)
    1297         328 :             continue;           /* PHV is uninteresting if no lateral refs */
    1298             : 
    1299         262 :         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         262 :         lateral_refs = bms_intersect(phinfo->ph_lateral, root->all_baserels);
    1308             :         Assert(!bms_is_empty(lateral_refs));
    1309             : 
    1310         262 :         if (bms_get_singleton_member(eval_at, &varno))
    1311             :         {
    1312             :             /* Evaluation site is a baserel */
    1313         196 :             RelOptInfo *brel = find_base_rel(root, varno);
    1314             : 
    1315         196 :             brel->direct_lateral_relids =
    1316         196 :                 bms_add_members(brel->direct_lateral_relids,
    1317             :                                 lateral_refs);
    1318         196 :             brel->lateral_relids =
    1319         196 :                 bms_add_members(brel->lateral_relids,
    1320             :                                 lateral_refs);
    1321             :         }
    1322             :         else
    1323             :         {
    1324             :             /* Evaluation site is a join */
    1325          66 :             varno = -1;
    1326         198 :             while ((varno = bms_next_member(eval_at, varno)) >= 0)
    1327             :             {
    1328         132 :                 RelOptInfo *brel = find_base_rel_ignore_join(root, varno);
    1329             : 
    1330         132 :                 if (brel == NULL)
    1331           0 :                     continue;   /* ignore outer joins in eval_at */
    1332         132 :                 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       10434 :     if (!found_laterals)
    1343             :     {
    1344         740 :         root->hasLateralRTEs = false;
    1345         740 :         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       35648 :     for (rti = 1; rti < root->simple_rel_array_size; rti++)
    1360             :     {
    1361       25954 :         RelOptInfo *brel = root->simple_rel_array[rti];
    1362             :         Relids      outer_lateral_relids;
    1363             :         Index       rti2;
    1364             : 
    1365       25954 :         if (brel == NULL || brel->reloptkind != RELOPT_BASEREL)
    1366        4364 :             continue;
    1367             : 
    1368             :         /* need not consider baserel further if it has no lateral refs */
    1369       21590 :         outer_lateral_relids = brel->lateral_relids;
    1370       21590 :         if (outer_lateral_relids == NULL)
    1371       11740 :             continue;
    1372             : 
    1373             :         /* else scan all baserels */
    1374       36788 :         for (rti2 = 1; rti2 < root->simple_rel_array_size; rti2++)
    1375             :         {
    1376       26938 :             RelOptInfo *brel2 = root->simple_rel_array[rti2];
    1377             : 
    1378       26938 :             if (brel2 == NULL || brel2->reloptkind != RELOPT_BASEREL)
    1379        4778 :                 continue;
    1380             : 
    1381             :             /* if brel2 has lateral ref to brel, propagate brel's refs */
    1382       22160 :             if (bms_is_member(rti, brel2->lateral_relids))
    1383          72 :                 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       35648 :     for (rti = 1; rti < root->simple_rel_array_size; rti++)
    1394             :     {
    1395       25954 :         RelOptInfo *brel = root->simple_rel_array[rti];
    1396             :         Relids      lateral_relids;
    1397             :         int         rti2;
    1398             : 
    1399       25954 :         if (brel == NULL || brel->reloptkind != RELOPT_BASEREL)
    1400        4364 :             continue;
    1401             : 
    1402             :         /* Nothing to do at rels with no lateral refs */
    1403       21590 :         lateral_relids = brel->lateral_relids;
    1404       21590 :         if (bms_is_empty(lateral_relids))
    1405       11740 :             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        9850 :         rti2 = -1;
    1412       19970 :         while ((rti2 = bms_next_member(lateral_relids, rti2)) >= 0)
    1413             :         {
    1414       10120 :             RelOptInfo *brel2 = root->simple_rel_array[rti2];
    1415             : 
    1416       10120 :             if (brel2 == NULL)
    1417          12 :                 continue;       /* must be an OJ */
    1418             : 
    1419             :             Assert(brel2->reloptkind == RELOPT_BASEREL);
    1420       10108 :             brel2->lateral_referencers =
    1421       10108 :                 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      339204 : deconstruct_jointree(PlannerInfo *root)
    1452             : {
    1453             :     List       *result;
    1454             :     JoinDomain *top_jdomain;
    1455      339204 :     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      339204 :     root->placeholdersFrozen = true;
    1464             : 
    1465             :     /* Fetch the already-created top-level join domain for the query */
    1466      339204 :     top_jdomain = linitial_node(JoinDomain, root->join_domains);
    1467      339204 :     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      339204 :     root->all_baserels = NULL;
    1475      339204 :     root->outer_join_rels = NULL;
    1476             : 
    1477             :     /* Perform the initial scan of the jointree */
    1478      339204 :     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      339204 :     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     1282296 :     foreach(lc, item_list)
    1490             :     {
    1491      943092 :         JoinTreeItem *jtitem = (JoinTreeItem *) lfirst(lc);
    1492             : 
    1493      943092 :         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      339204 :     if (root->join_info_list)
    1501             :     {
    1502      261498 :         foreach(lc, item_list)
    1503             :         {
    1504      221784 :             JoinTreeItem *jtitem = (JoinTreeItem *) lfirst(lc);
    1505             : 
    1506      221784 :             if (jtitem->oj_joinclauses != NIL)
    1507       42728 :                 deconstruct_distribute_oj_quals(root, item_list, jtitem);
    1508             :         }
    1509             :     }
    1510             : 
    1511             :     /* Don't need the JoinTreeItems any more */
    1512      339204 :     list_free_deep(item_list);
    1513             : 
    1514      339204 :     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      943092 : 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      943092 :     jtitem = palloc0_object(JoinTreeItem);
    1545      943092 :     jtitem->jtnode = jtnode;
    1546      943092 :     jtitem->jti_parent = parent_jtitem;
    1547             : 
    1548      943092 :     if (IsA(jtnode, RangeTblRef))
    1549             :     {
    1550      490434 :         int         varno = ((RangeTblRef *) jtnode)->rtindex;
    1551             : 
    1552             :         /* Fill all_baserels as we encounter baserel jointree nodes */
    1553      490434 :         root->all_baserels = bms_add_member(root->all_baserels, varno);
    1554             :         /* This node belongs to parent_domain */
    1555      490434 :         jtitem->jdomain = parent_domain;
    1556      490434 :         parent_domain->jd_relids = bms_add_member(parent_domain->jd_relids,
    1557             :                                                   varno);
    1558             :         /* qualscope is just the one RTE */
    1559      490434 :         jtitem->qualscope = bms_make_singleton(varno);
    1560             :         /* A single baserel does not create an inner join */
    1561      490434 :         jtitem->inner_join_rels = NULL;
    1562      490434 :         joinlist = list_make1(jtnode);
    1563             :     }
    1564      452658 :     else if (IsA(jtnode, FromExpr))
    1565             :     {
    1566      351646 :         FromExpr   *f = (FromExpr *) jtnode;
    1567             :         int         remaining;
    1568             :         ListCell   *l;
    1569             : 
    1570             :         /* This node belongs to parent_domain, as do its children */
    1571      351646 :         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      351646 :         jtitem->qualscope = NULL;
    1581      351646 :         jtitem->inner_join_rels = NULL;
    1582      351646 :         joinlist = NIL;
    1583      351646 :         remaining = list_length(f->fromlist);
    1584      753510 :         foreach(l, f->fromlist)
    1585             :         {
    1586             :             JoinTreeItem *sub_item;
    1587             :             List       *sub_joinlist;
    1588             :             int         sub_members;
    1589             : 
    1590      401864 :             sub_joinlist = deconstruct_recurse(root, lfirst(l),
    1591             :                                                parent_domain,
    1592             :                                                jtitem,
    1593             :                                                item_list);
    1594      401864 :             sub_item = (JoinTreeItem *) llast(*item_list);
    1595      803728 :             jtitem->qualscope = bms_add_members(jtitem->qualscope,
    1596      401864 :                                                 sub_item->qualscope);
    1597      401864 :             jtitem->inner_join_rels = sub_item->inner_join_rels;
    1598      401864 :             sub_members = list_length(sub_joinlist);
    1599      401864 :             remaining--;
    1600      401864 :             if (sub_members <= 1 ||
    1601       65510 :                 list_length(joinlist) + sub_members + remaining <= from_collapse_limit)
    1602      401852 :                 joinlist = list_concat(joinlist, sub_joinlist);
    1603             :             else
    1604          12 :                 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      351646 :         if (list_length(f->fromlist) > 1)
    1615       45232 :             jtitem->inner_join_rels = jtitem->qualscope;
    1616             :     }
    1617      101012 :     else if (IsA(jtnode, JoinExpr))
    1618             :     {
    1619      101012 :         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      101012 :         switch (j->jointype)
    1628             :         {
    1629       46598 :             case JOIN_INNER:
    1630             :                 /* This node belongs to parent_domain, as do its children */
    1631       46598 :                 jtitem->jdomain = parent_domain;
    1632             :                 /* Recurse */
    1633       46598 :                 leftjoinlist = deconstruct_recurse(root, j->larg,
    1634             :                                                    parent_domain,
    1635             :                                                    jtitem,
    1636             :                                                    item_list);
    1637       46598 :                 left_item = (JoinTreeItem *) llast(*item_list);
    1638       46598 :                 rightjoinlist = deconstruct_recurse(root, j->rarg,
    1639             :                                                     parent_domain,
    1640             :                                                     jtitem,
    1641             :                                                     item_list);
    1642       46598 :                 right_item = (JoinTreeItem *) llast(*item_list);
    1643             :                 /* Compute qualscope etc */
    1644       93196 :                 jtitem->qualscope = bms_union(left_item->qualscope,
    1645       46598 :                                               right_item->qualscope);
    1646       46598 :                 jtitem->inner_join_rels = jtitem->qualscope;
    1647       46598 :                 jtitem->left_rels = left_item->qualscope;
    1648       46598 :                 jtitem->right_rels = right_item->qualscope;
    1649             :                 /* Inner join adds no restrictions for quals */
    1650       46598 :                 jtitem->nonnullable_rels = NULL;
    1651       46598 :                 break;
    1652       48346 :             case JOIN_LEFT:
    1653             :             case JOIN_ANTI:
    1654             :                 /* Make new join domain for my quals and the RHS */
    1655       48346 :                 child_domain = makeNode(JoinDomain);
    1656       48346 :                 child_domain->jd_relids = NULL; /* filled by recursion */
    1657       48346 :                 root->join_domains = lappend(root->join_domains, child_domain);
    1658       48346 :                 jtitem->jdomain = child_domain;
    1659             :                 /* Recurse */
    1660       48346 :                 leftjoinlist = deconstruct_recurse(root, j->larg,
    1661             :                                                    parent_domain,
    1662             :                                                    jtitem,
    1663             :                                                    item_list);
    1664       48346 :                 left_item = (JoinTreeItem *) llast(*item_list);
    1665       48346 :                 rightjoinlist = deconstruct_recurse(root, j->rarg,
    1666             :                                                     child_domain,
    1667             :                                                     jtitem,
    1668             :                                                     item_list);
    1669       48346 :                 right_item = (JoinTreeItem *) llast(*item_list);
    1670             :                 /* Compute join domain contents, qualscope etc */
    1671       48346 :                 parent_domain->jd_relids =
    1672       48346 :                     bms_add_members(parent_domain->jd_relids,
    1673       48346 :                                     child_domain->jd_relids);
    1674       96692 :                 jtitem->qualscope = bms_union(left_item->qualscope,
    1675       48346 :                                               right_item->qualscope);
    1676             :                 /* caution: ANTI join derived from SEMI will lack rtindex */
    1677       48346 :                 if (j->rtindex != 0)
    1678             :                 {
    1679       45586 :                     parent_domain->jd_relids =
    1680       45586 :                         bms_add_member(parent_domain->jd_relids,
    1681             :                                        j->rtindex);
    1682       45586 :                     jtitem->qualscope = bms_add_member(jtitem->qualscope,
    1683             :                                                        j->rtindex);
    1684       45586 :                     root->outer_join_rels = bms_add_member(root->outer_join_rels,
    1685             :                                                            j->rtindex);
    1686       45586 :                     mark_rels_nulled_by_join(root, j->rtindex,
    1687             :                                              right_item->qualscope);
    1688             :                 }
    1689       96692 :                 jtitem->inner_join_rels = bms_union(left_item->inner_join_rels,
    1690       48346 :                                                     right_item->inner_join_rels);
    1691       48346 :                 jtitem->left_rels = left_item->qualscope;
    1692       48346 :                 jtitem->right_rels = right_item->qualscope;
    1693       48346 :                 jtitem->nonnullable_rels = left_item->qualscope;
    1694       48346 :                 break;
    1695        5034 :             case JOIN_SEMI:
    1696             :                 /* This node belongs to parent_domain, as do its children */
    1697        5034 :                 jtitem->jdomain = parent_domain;
    1698             :                 /* Recurse */
    1699        5034 :                 leftjoinlist = deconstruct_recurse(root, j->larg,
    1700             :                                                    parent_domain,
    1701             :                                                    jtitem,
    1702             :                                                    item_list);
    1703        5034 :                 left_item = (JoinTreeItem *) llast(*item_list);
    1704        5034 :                 rightjoinlist = deconstruct_recurse(root, j->rarg,
    1705             :                                                     parent_domain,
    1706             :                                                     jtitem,
    1707             :                                                     item_list);
    1708        5034 :                 right_item = (JoinTreeItem *) llast(*item_list);
    1709             :                 /* Compute qualscope etc */
    1710       10068 :                 jtitem->qualscope = bms_union(left_item->qualscope,
    1711        5034 :                                               right_item->qualscope);
    1712             :                 /* SEMI join never has rtindex, so don't add to anything */
    1713             :                 Assert(j->rtindex == 0);
    1714       10068 :                 jtitem->inner_join_rels = bms_union(left_item->inner_join_rels,
    1715        5034 :                                                     right_item->inner_join_rels);
    1716        5034 :                 jtitem->left_rels = left_item->qualscope;
    1717        5034 :                 jtitem->right_rels = right_item->qualscope;
    1718             :                 /* Semi join adds no restrictions for quals */
    1719        5034 :                 jtitem->nonnullable_rels = NULL;
    1720        5034 :                 break;
    1721        1034 :             case JOIN_FULL:
    1722             :                 /* The FULL JOIN's quals need their very own domain */
    1723        1034 :                 fj_domain = makeNode(JoinDomain);
    1724        1034 :                 root->join_domains = lappend(root->join_domains, fj_domain);
    1725        1034 :                 jtitem->jdomain = fj_domain;
    1726             :                 /* Recurse, giving each side its own join domain */
    1727        1034 :                 child_domain = makeNode(JoinDomain);
    1728        1034 :                 child_domain->jd_relids = NULL; /* filled by recursion */
    1729        1034 :                 root->join_domains = lappend(root->join_domains, child_domain);
    1730        1034 :                 leftjoinlist = deconstruct_recurse(root, j->larg,
    1731             :                                                    child_domain,
    1732             :                                                    jtitem,
    1733             :                                                    item_list);
    1734        1034 :                 left_item = (JoinTreeItem *) llast(*item_list);
    1735        1034 :                 fj_domain->jd_relids = bms_copy(child_domain->jd_relids);
    1736        1034 :                 child_domain = makeNode(JoinDomain);
    1737        1034 :                 child_domain->jd_relids = NULL; /* filled by recursion */
    1738        1034 :                 root->join_domains = lappend(root->join_domains, child_domain);
    1739        1034 :                 rightjoinlist = deconstruct_recurse(root, j->rarg,
    1740             :                                                     child_domain,
    1741             :                                                     jtitem,
    1742             :                                                     item_list);
    1743        1034 :                 right_item = (JoinTreeItem *) llast(*item_list);
    1744             :                 /* Compute qualscope etc */
    1745        2068 :                 fj_domain->jd_relids = bms_add_members(fj_domain->jd_relids,
    1746        1034 :                                                        child_domain->jd_relids);
    1747        2068 :                 parent_domain->jd_relids = bms_add_members(parent_domain->jd_relids,
    1748        1034 :                                                            fj_domain->jd_relids);
    1749        2068 :                 jtitem->qualscope = bms_union(left_item->qualscope,
    1750        1034 :                                               right_item->qualscope);
    1751             :                 Assert(j->rtindex != 0);
    1752        1034 :                 parent_domain->jd_relids = bms_add_member(parent_domain->jd_relids,
    1753             :                                                           j->rtindex);
    1754        1034 :                 jtitem->qualscope = bms_add_member(jtitem->qualscope,
    1755             :                                                    j->rtindex);
    1756        1034 :                 root->outer_join_rels = bms_add_member(root->outer_join_rels,
    1757             :                                                        j->rtindex);
    1758        1034 :                 mark_rels_nulled_by_join(root, j->rtindex,
    1759             :                                          left_item->qualscope);
    1760        1034 :                 mark_rels_nulled_by_join(root, j->rtindex,
    1761             :                                          right_item->qualscope);
    1762        2068 :                 jtitem->inner_join_rels = bms_union(left_item->inner_join_rels,
    1763        1034 :                                                     right_item->inner_join_rels);
    1764        1034 :                 jtitem->left_rels = left_item->qualscope;
    1765        1034 :                 jtitem->right_rels = right_item->qualscope;
    1766             :                 /* each side is both outer and inner */
    1767        1034 :                 jtitem->nonnullable_rels = jtitem->qualscope;
    1768        1034 :                 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      101012 :         if (j->jointype == JOIN_FULL)
    1782             :         {
    1783             :             /* force the join order exactly at this node */
    1784        1034 :             joinlist = list_make1(list_make2(leftjoinlist, rightjoinlist));
    1785             :         }
    1786       99978 :         else if (list_length(leftjoinlist) + list_length(rightjoinlist) <=
    1787             :                  join_collapse_limit)
    1788             :         {
    1789             :             /* OK to combine subproblems */
    1790       99810 :             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         168 :             if (list_length(leftjoinlist) == 1)
    1800          30 :                 leftpart = (Node *) linitial(leftjoinlist);
    1801             :             else
    1802         138 :                 leftpart = (Node *) leftjoinlist;
    1803         168 :             if (list_length(rightjoinlist) == 1)
    1804          24 :                 rightpart = (Node *) linitial(rightjoinlist);
    1805             :             else
    1806         144 :                 rightpart = (Node *) rightjoinlist;
    1807         168 :             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      943092 :     *item_list = lappend(*item_list, jtitem);
    1819             : 
    1820      943092 :     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      943092 : deconstruct_distribute(PlannerInfo *root, JoinTreeItem *jtitem)
    1832             : {
    1833      943092 :     Node       *jtnode = jtitem->jtnode;
    1834             : 
    1835      943092 :     if (IsA(jtnode, RangeTblRef))
    1836             :     {
    1837      490434 :         int         varno = ((RangeTblRef *) jtnode)->rtindex;
    1838             : 
    1839             :         /* Deal with any securityQuals attached to the RTE */
    1840      490434 :         if (root->qual_security_level > 0)
    1841        2988 :             process_security_barrier_quals(root,
    1842             :                                            varno,
    1843             :                                            jtitem);
    1844             :     }
    1845      452658 :     else if (IsA(jtnode, FromExpr))
    1846             :     {
    1847      351646 :         FromExpr   *f = (FromExpr *) jtnode;
    1848             : 
    1849             :         /*
    1850             :          * Process any lateral-referencing quals that were postponed to this
    1851             :          * level by children.
    1852             :          */
    1853      351646 :         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      351646 :         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      101012 :     else if (IsA(jtnode, JoinExpr))
    1875             :     {
    1876      101012 :         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      101012 :         my_quals = list_concat(jtitem->lateral_clauses,
    1889      101012 :                                (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      101012 :         if (j->jointype != JOIN_INNER)
    1899             :         {
    1900       54414 :             sjinfo = make_outerjoininfo(root,
    1901             :                                         jtitem->left_rels,
    1902             :                                         jtitem->right_rels,
    1903             :                                         jtitem->inner_join_rels,
    1904             :                                         j->jointype,
    1905       54414 :                                         j->rtindex,
    1906             :                                         my_quals);
    1907       54414 :             jtitem->sjinfo = sjinfo;
    1908       54414 :             if (j->jointype == JOIN_SEMI)
    1909        5034 :                 ojscope = NULL;
    1910             :             else
    1911       49380 :                 ojscope = bms_union(sjinfo->min_lefthand,
    1912       49380 :                                     sjinfo->min_righthand);
    1913             :         }
    1914             :         else
    1915             :         {
    1916       46598 :             sjinfo = NULL;
    1917       46598 :             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      101012 :         if (j->jointype == JOIN_LEFT && sjinfo->lhs_strict)
    1928             :         {
    1929       42728 :             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       42728 :             ojscope = bms_add_members(ojscope, sjinfo->commute_below_l);
    1941       42728 :             ojscope = bms_add_members(ojscope, sjinfo->commute_below_r);
    1942             :         }
    1943             :         else
    1944       58284 :             postponed_oj_qual_list = NULL;
    1945             : 
    1946             :         /* Process the JOIN's qual clauses */
    1947      101012 :         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      101012 :         if (sjinfo)
    1960       54414 :             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      943092 : }
    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        2988 : process_security_barrier_quals(PlannerInfo *root,
    1984             :                                int rti, JoinTreeItem *jtitem)
    1985             : {
    1986        2988 :     RangeTblEntry *rte = root->simple_rte_array[rti];
    1987        2988 :     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        6118 :     foreach(lc, rte->securityQuals)
    1997             :     {
    1998        3130 :         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        3130 :         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        3130 :         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        2988 : }
    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       47654 : mark_rels_nulled_by_join(PlannerInfo *root, Index ojrelid,
    2034             :                          Relids lower_rels)
    2035             : {
    2036       47654 :     int         relid = -1;
    2037             : 
    2038       98060 :     while ((relid = bms_next_member(lower_rels, relid)) > 0)
    2039             :     {
    2040       50406 :         RelOptInfo *rel = root->simple_rel_array[relid];
    2041             : 
    2042             :         /* ignore the RTE_GROUP RTE */
    2043       50406 :         if (relid == root->group_rtindex)
    2044           0 :             continue;
    2045             : 
    2046       50406 :         if (rel == NULL)        /* must be an outer join */
    2047             :         {
    2048             :             Assert(bms_is_member(relid, root->outer_join_rels));
    2049         770 :             continue;
    2050             :         }
    2051       49636 :         rel->nulling_relids = bms_add_member(rel->nulling_relids, ojrelid);
    2052             :     }
    2053       47654 : }
    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       54414 : 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       54414 :     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       54458 :     foreach(l, root->parse->rowMarks)
    2113             :     {
    2114          44 :         RowMarkClause *rc = (RowMarkClause *) lfirst(l);
    2115             : 
    2116          44 :         if (bms_is_member(rc->rti, right_rels) ||
    2117           8 :             (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       54414 :     sjinfo->syn_lefthand = left_rels;
    2127       54414 :     sjinfo->syn_righthand = right_rels;
    2128       54414 :     sjinfo->jointype = jointype;
    2129       54414 :     sjinfo->ojrelid = ojrelid;
    2130             :     /* these fields may get added to later: */
    2131       54414 :     sjinfo->commute_above_l = NULL;
    2132       54414 :     sjinfo->commute_above_r = NULL;
    2133       54414 :     sjinfo->commute_below_l = NULL;
    2134       54414 :     sjinfo->commute_below_r = NULL;
    2135             : 
    2136       54414 :     compute_semijoin_info(root, sjinfo, clause);
    2137             : 
    2138             :     /* If it's a full join, no need to be very smart */
    2139       54414 :     if (jointype == JOIN_FULL)
    2140             :     {
    2141        1034 :         sjinfo->min_lefthand = bms_copy(left_rels);
    2142        1034 :         sjinfo->min_righthand = bms_copy(right_rels);
    2143        1034 :         sjinfo->lhs_strict = false; /* don't care about this */
    2144        1034 :         return sjinfo;
    2145             :     }
    2146             : 
    2147             :     /*
    2148             :      * Retrieve all relids mentioned within the join clause.
    2149             :      */
    2150       53380 :     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       53380 :     strict_relids = find_nonnullable_rels((Node *) clause);
    2157             : 
    2158             :     /* Remember whether the clause is strict for any LHS relations */
    2159       53380 :     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       53380 :     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       53380 :     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       53380 :     commute_below_l = commute_below_r = NULL;
    2184       71046 :     foreach(l, root->join_info_list)
    2185             :     {
    2186       17666 :         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       17666 :         if (otherinfo->jointype == JOIN_FULL)
    2195             :         {
    2196             :             Assert(otherinfo->ojrelid != 0);
    2197          94 :             if (bms_overlap(left_rels, otherinfo->syn_lefthand) ||
    2198          30 :                 bms_overlap(left_rels, otherinfo->syn_righthand))
    2199             :             {
    2200          34 :                 min_lefthand = bms_add_members(min_lefthand,
    2201          34 :                                                otherinfo->syn_lefthand);
    2202          34 :                 min_lefthand = bms_add_members(min_lefthand,
    2203          34 :                                                otherinfo->syn_righthand);
    2204          34 :                 min_lefthand = bms_add_member(min_lefthand,
    2205          34 :                                               otherinfo->ojrelid);
    2206             :             }
    2207          98 :             if (bms_overlap(right_rels, otherinfo->syn_lefthand) ||
    2208          34 :                 bms_overlap(right_rels, otherinfo->syn_righthand))
    2209             :             {
    2210          30 :                 min_righthand = bms_add_members(min_righthand,
    2211          30 :                                                 otherinfo->syn_lefthand);
    2212          30 :                 min_righthand = bms_add_members(min_righthand,
    2213          30 :                                                 otherinfo->syn_righthand);
    2214          30 :                 min_righthand = bms_add_member(min_righthand,
    2215          30 :                                                otherinfo->ojrelid);
    2216             :             }
    2217             :             /* Needn't do anything else with the full join */
    2218          64 :             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       17602 :         if (otherinfo->ojrelid != 0)
    2226             :             have_unsafe_phvs =
    2227       17248 :                 contain_placeholder_references_to(root,
    2228             :                                                   (Node *) clause,
    2229       17248 :                                                   otherinfo->ojrelid);
    2230             :         else
    2231         354 :             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       17602 :         if (bms_overlap(left_rels, otherinfo->syn_righthand))
    2252             :         {
    2253       16750 :             if (bms_overlap(clause_relids, otherinfo->syn_righthand) &&
    2254        4858 :                 (have_unsafe_phvs ||
    2255        4858 :                  jointype == JOIN_SEMI || jointype == JOIN_ANTI ||
    2256        4858 :                  !bms_overlap(strict_relids, otherinfo->min_righthand)))
    2257             :             {
    2258             :                 /* Preserve ordering */
    2259          42 :                 min_lefthand = bms_add_members(min_lefthand,
    2260          42 :                                                otherinfo->syn_lefthand);
    2261          42 :                 min_lefthand = bms_add_members(min_lefthand,
    2262          42 :                                                otherinfo->syn_righthand);
    2263          42 :                 if (otherinfo->ojrelid != 0)
    2264          42 :                     min_lefthand = bms_add_member(min_lefthand,
    2265          42 :                                                   otherinfo->ojrelid);
    2266             :             }
    2267       16708 :             else if (jointype == JOIN_LEFT &&
    2268       32152 :                      otherinfo->jointype == JOIN_LEFT &&
    2269       16074 :                      bms_overlap(strict_relids, otherinfo->min_righthand) &&
    2270        4828 :                      !bms_overlap(clause_relids, otherinfo->syn_lefthand))
    2271             :             {
    2272             :                 /* Identity 3 applies, so remove the ordering restriction */
    2273        4774 :                 min_lefthand = bms_del_member(min_lefthand, otherinfo->ojrelid);
    2274             :                 /* Record the (still tentative) commutability relationship */
    2275             :                 commute_below_l =
    2276        4774 :                     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       17602 :         if (bms_overlap(right_rels, otherinfo->syn_righthand))
    2299             :         {
    2300         766 :             if (bms_overlap(clause_relids, otherinfo->syn_righthand) ||
    2301         718 :                 !bms_overlap(clause_relids, otherinfo->min_lefthand) ||
    2302         406 :                 have_unsafe_phvs ||
    2303         310 :                 jointype == JOIN_SEMI ||
    2304         304 :                 jointype == JOIN_ANTI ||
    2305         304 :                 otherinfo->jointype == JOIN_SEMI ||
    2306         244 :                 otherinfo->jointype == JOIN_ANTI ||
    2307         244 :                 !otherinfo->lhs_strict)
    2308             :             {
    2309             :                 /* Preserve ordering */
    2310         546 :                 min_righthand = bms_add_members(min_righthand,
    2311         546 :                                                 otherinfo->syn_lefthand);
    2312         546 :                 min_righthand = bms_add_members(min_righthand,
    2313         546 :                                                 otherinfo->syn_righthand);
    2314         546 :                 if (otherinfo->ojrelid != 0)
    2315         390 :                     min_righthand = bms_add_member(min_righthand,
    2316         390 :                                                    otherinfo->ojrelid);
    2317             :             }
    2318         220 :             else if (jointype == JOIN_LEFT &&
    2319         220 :                      otherinfo->jointype == JOIN_LEFT &&
    2320         220 :                      otherinfo->lhs_strict)
    2321             :             {
    2322             :                 /* Identity 3 applies, so remove the ordering restriction */
    2323         220 :                 min_righthand = bms_del_member(min_righthand,
    2324         220 :                                                otherinfo->ojrelid);
    2325             :                 /* Record the (still tentative) commutability relationship */
    2326             :                 commute_below_r =
    2327         220 :                     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       54816 :     foreach(l, root->placeholder_list)
    2341             :     {
    2342        1436 :         PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(l);
    2343        1436 :         Relids      ph_syn_level = phinfo->ph_var->phrels;
    2344             : 
    2345             :         /* Ignore placeholder if it didn't syntactically come from RHS */
    2346        1436 :         if (!bms_is_subset(ph_syn_level, right_rels))
    2347         520 :             continue;
    2348             : 
    2349             :         /* Else, prevent join from being formed before we eval the PHV */
    2350         916 :         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       53380 :     if (bms_is_empty(min_lefthand))
    2360        1614 :         min_lefthand = bms_copy(left_rels);
    2361       53380 :     if (bms_is_empty(min_righthand))
    2362         674 :         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       53380 :     sjinfo->min_lefthand = min_lefthand;
    2371       53380 :     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       53380 :     commute_below_l = bms_del_members(commute_below_l, min_lefthand);
    2383       53380 :     commute_below_r = bms_del_members(commute_below_r, min_righthand);
    2384             : 
    2385             :     /* Anything left? */
    2386       53380 :     if (commute_below_l || commute_below_r)
    2387             :     {
    2388             :         /* Yup, so we must update the derived data in the SpecialJoinInfos */
    2389        4916 :         sjinfo->commute_below_l = commute_below_l;
    2390        4916 :         sjinfo->commute_below_r = commute_below_r;
    2391       10762 :         foreach(l, root->join_info_list)
    2392             :         {
    2393        5846 :             SpecialJoinInfo *otherinfo = (SpecialJoinInfo *) lfirst(l);
    2394             : 
    2395        5846 :             if (bms_is_member(otherinfo->ojrelid, commute_below_l))
    2396        4774 :                 otherinfo->commute_above_l =
    2397        4774 :                     bms_add_member(otherinfo->commute_above_l, ojrelid);
    2398        1072 :             else if (bms_is_member(otherinfo->ojrelid, commute_below_r))
    2399         190 :                 otherinfo->commute_above_r =
    2400         190 :                     bms_add_member(otherinfo->commute_above_r, ojrelid);
    2401             :         }
    2402             :     }
    2403             : 
    2404       53380 :     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       54414 : 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       54414 :     sjinfo->semi_can_btree = false;
    2425       54414 :     sjinfo->semi_can_hash = false;
    2426       54414 :     sjinfo->semi_operators = NIL;
    2427       54414 :     sjinfo->semi_rhs_exprs = NIL;
    2428             : 
    2429             :     /* Nothing more to do if it's not a semijoin */
    2430       54414 :     if (sjinfo->jointype != JOIN_SEMI)
    2431       49380 :         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        5034 :     semi_operators = NIL;
    2460        5034 :     semi_rhs_exprs = NIL;
    2461        5034 :     all_btree = true;
    2462        5034 :     all_hash = enable_hashagg;  /* don't consider hash if not enabled */
    2463       10438 :     foreach(lc, clause)
    2464             :     {
    2465        5518 :         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       10928 :         if (!IsA(op, OpExpr) ||
    2476        5410 :             list_length(op->args) != 2)
    2477             :         {
    2478             :             /* No, but does it reference both sides? */
    2479         108 :             all_varnos = pull_varnos(root, (Node *) op);
    2480         204 :             if (!bms_overlap(all_varnos, sjinfo->syn_righthand) ||
    2481          96 :                 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          96 :                 if (contain_volatile_functions((Node *) op))
    2489         114 :                     return;
    2490          96 :                 continue;
    2491             :             }
    2492             :             /* Non-operator clause referencing both sides, must punt */
    2493          12 :             return;
    2494             :         }
    2495             : 
    2496             :         /* Extract data from binary opclause */
    2497        5410 :         opno = op->opno;
    2498        5410 :         left_expr = linitial(op->args);
    2499        5410 :         right_expr = lsecond(op->args);
    2500        5410 :         left_varnos = pull_varnos(root, left_expr);
    2501        5410 :         right_varnos = pull_varnos(root, right_expr);
    2502        5410 :         all_varnos = bms_union(left_varnos, right_varnos);
    2503        5410 :         opinputtype = exprType(left_expr);
    2504             : 
    2505             :         /* Does it reference both sides? */
    2506       10800 :         if (!bms_overlap(all_varnos, sjinfo->syn_righthand) ||
    2507        5390 :             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         130 :             if (contain_volatile_functions((Node *) op))
    2514           0 :                 return;
    2515         130 :             continue;
    2516             :         }
    2517             : 
    2518             :         /* check rel membership of arguments */
    2519       10560 :         if (!bms_is_empty(right_varnos) &&
    2520        5280 :             bms_is_subset(right_varnos, sjinfo->syn_righthand) &&
    2521        4820 :             !bms_overlap(left_varnos, sjinfo->syn_righthand))
    2522             :         {
    2523             :             /* typical case, right_expr is RHS variable */
    2524             :         }
    2525         920 :         else if (!bms_is_empty(left_varnos) &&
    2526         460 :                  bms_is_subset(left_varnos, sjinfo->syn_righthand) &&
    2527         454 :                  !bms_overlap(right_varnos, sjinfo->syn_righthand))
    2528             :         {
    2529             :             /* flipped case, left_expr is RHS variable */
    2530         454 :             opno = get_commutator(opno);
    2531         454 :             if (!OidIsValid(opno))
    2532           0 :                 return;
    2533         454 :             right_expr = left_expr;
    2534             :         }
    2535             :         else
    2536             :         {
    2537             :             /* mixed membership of args, punt */
    2538           6 :             return;
    2539             :         }
    2540             : 
    2541             :         /* all operators must be btree equality or hash equality */
    2542        5274 :         if (all_btree)
    2543             :         {
    2544             :             /* oprcanmerge is considered a hint... */
    2545       10452 :             if (!op_mergejoinable(opno, opinputtype) ||
    2546        5178 :                 get_mergejoin_opfamilies(opno) == NIL)
    2547          96 :                 all_btree = false;
    2548             :         }
    2549        5274 :         if (all_hash)
    2550             :         {
    2551             :             /* ... but oprcanhash had better be correct */
    2552        5202 :             if (!op_hashjoinable(opno, opinputtype))
    2553          96 :                 all_hash = false;
    2554             :         }
    2555        5274 :         if (!(all_btree || all_hash))
    2556          96 :             return;
    2557             : 
    2558             :         /* so far so good, keep building lists */
    2559        5178 :         semi_operators = lappend_oid(semi_operators, opno);
    2560        5178 :         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        4920 :     if (semi_rhs_exprs == NIL)
    2565          12 :         return;
    2566             : 
    2567             :     /*
    2568             :      * The expressions we'd need to unique-ify mustn't be volatile.
    2569             :      */
    2570        4908 :     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        4908 :     sjinfo->semi_can_btree = all_btree;
    2578        4908 :     sjinfo->semi_can_hash = all_hash;
    2579        4908 :     sjinfo->semi_operators = semi_operators;
    2580        4908 :     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       42728 : deconstruct_distribute_oj_quals(PlannerInfo *root,
    2594             :                                 List *jtitems,
    2595             :                                 JoinTreeItem *jtitem)
    2596             : {
    2597       42728 :     SpecialJoinInfo *sjinfo = jtitem->sjinfo;
    2598             :     Relids      qualscope,
    2599             :                 ojscope,
    2600             :                 nonnullable_rels;
    2601             : 
    2602             :     /* Recompute syntactic and semantic scopes of this left join */
    2603       42728 :     qualscope = bms_union(sjinfo->syn_lefthand, sjinfo->syn_righthand);
    2604       42728 :     qualscope = bms_add_member(qualscope, sjinfo->ojrelid);
    2605       42728 :     ojscope = bms_union(sjinfo->min_lefthand, sjinfo->min_righthand);
    2606       42728 :     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       42728 :     if (sjinfo->commute_above_r || sjinfo->commute_below_l)
    2617        4928 :     {
    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        4928 :         joins_above = sjinfo->commute_above_r;
    2628        4928 :         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        4928 :         quals = jtitem->oj_joinclauses;
    2649        4928 :         if (!bms_is_empty(joins_below))
    2650        4738 :             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        4928 :         incompatible_joins = bms_union(joins_below, joins_above);
    2660        4928 :         incompatible_joins = bms_add_member(incompatible_joins,
    2661        4928 :                                             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        4928 :         save_last_rinfo_serial = root->last_rinfo_serial;
    2672             : 
    2673        4928 :         joins_so_far = NULL;
    2674       42984 :         foreach(lc, jtitems)
    2675             :         {
    2676       38056 :             JoinTreeItem *otherjtitem = (JoinTreeItem *) lfirst(lc);
    2677       38056 :             SpecialJoinInfo *othersj = otherjtitem->sjinfo;
    2678       38056 :             bool        below_sjinfo = false;
    2679       38056 :             bool        above_sjinfo = false;
    2680             :             Relids      this_qualscope;
    2681             :             Relids      this_ojscope;
    2682             :             bool        allow_equivalence,
    2683             :                         has_clone,
    2684             :                         is_clone;
    2685             : 
    2686       38056 :             if (othersj == NULL)
    2687       27026 :                 continue;       /* not an outer-join item, ignore */
    2688             : 
    2689       11030 :             if (bms_is_member(othersj->ojrelid, joins_below))
    2690             :             {
    2691             :                 /* othersj commutes with sjinfo from below left */
    2692        4774 :                 below_sjinfo = true;
    2693             :             }
    2694        6256 :             else if (othersj == sjinfo)
    2695             :             {
    2696             :                 /* found our join in syntactic order */
    2697             :                 Assert(bms_equal(joins_so_far, joins_below));
    2698             :             }
    2699        1328 :             else if (bms_is_member(othersj->ojrelid, joins_above))
    2700             :             {
    2701             :                 /* othersj commutes with sjinfo from above */
    2702         190 :                 above_sjinfo = true;
    2703             :             }
    2704             :             else
    2705             :             {
    2706             :                 /* othersj is not relevant, ignore */
    2707        1138 :                 continue;
    2708             :             }
    2709             : 
    2710             :             /* Reset serial counter for this version of the quals */
    2711        9892 :             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        9892 :             if (above_sjinfo)
    2727             :             {
    2728             :                 quals = (List *)
    2729         190 :                     add_nulling_relids((Node *) quals,
    2730         190 :                                        sjinfo->syn_lefthand,
    2731         190 :                                        bms_make_singleton(othersj->ojrelid));
    2732         190 :                 incompatible_joins = bms_del_member(incompatible_joins,
    2733         190 :                                                     othersj->ojrelid);
    2734             :             }
    2735             : 
    2736             :             /* Compute qualscope and ojscope for this join level */
    2737        9892 :             this_qualscope = bms_union(qualscope, joins_so_far);
    2738        9892 :             this_ojscope = bms_union(ojscope, joins_so_far);
    2739        9892 :             if (above_sjinfo)
    2740             :             {
    2741             :                 /* othersj is not yet in joins_so_far, but we need it */
    2742         190 :                 this_qualscope = bms_add_member(this_qualscope,
    2743         190 :                                                 othersj->ojrelid);
    2744         190 :                 this_ojscope = bms_add_member(this_ojscope,
    2745         190 :                                               othersj->ojrelid);
    2746             :                 /* sjinfo is in joins_so_far, and we don't want it */
    2747         190 :                 this_ojscope = bms_del_member(this_ojscope,
    2748         190 :                                               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        9892 :             allow_equivalence = (joins_so_far == NULL);
    2767        9892 :             has_clone = allow_equivalence;
    2768        9892 :             is_clone = !has_clone;
    2769             : 
    2770        9892 :             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        9892 :             if (below_sjinfo)
    2792             :             {
    2793             :                 quals = (List *)
    2794        4774 :                     add_nulling_relids((Node *) quals,
    2795        4774 :                                        othersj->syn_righthand,
    2796        4774 :                                        bms_make_singleton(othersj->ojrelid));
    2797        4774 :                 incompatible_joins = bms_del_member(incompatible_joins,
    2798        4774 :                                                     othersj->ojrelid);
    2799             :             }
    2800             : 
    2801             :             /* ... and track joins processed so far */
    2802        9892 :             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       37800 :         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       42728 : }
    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      855126 : 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     1456130 :     foreach(lc, clauses)
    2850             :     {
    2851      601004 :         Node       *clause = (Node *) lfirst(lc);
    2852             : 
    2853      601004 :         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      855126 : }
    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      601004 : 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      601004 :     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      601004 :     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      601004 :     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         116 :         for (pitem = jtitem->jti_parent; pitem; pitem = pitem->jti_parent)
    2956             :         {
    2957         116 :             if (bms_is_subset(relids, pitem->qualscope))
    2958             :             {
    2959         110 :                 pitem->lateral_clauses = lappend(pitem->lateral_clauses,
    2960             :                                                  clause);
    2961      422600 :                 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      600894 :     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      600894 :     if (bms_is_empty(relids))
    3001             :     {
    3002       11182 :         if (ojscope)
    3003             :         {
    3004             :             /* clause is attached to outer join, eval it there */
    3005         404 :             relids = bms_copy(ojscope);
    3006             :             /* mustn't use as gating qual, so don't mark pseudoconstant */
    3007             :         }
    3008       10778 :         else if (contain_volatile_functions(clause))
    3009             :         {
    3010             :             /* eval at original syntactic level */
    3011         174 :             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       10604 :             if (jtitem->jdomain == (JoinDomain *) linitial(root->join_domains))
    3026       10544 :                 relids = bms_copy(jtitem->jdomain->jd_relids);
    3027             :             else
    3028          60 :                 relids = bms_copy(qualscope);
    3029             :             /* mark as gating qual */
    3030       10604 :             pseudoconstant = true;
    3031             :             /* tell createplan.c to check for gating quals */
    3032       10604 :             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      600894 :     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      106804 :         if (postponed_oj_qual_list != NULL)
    3078             :         {
    3079       47372 :             *postponed_oj_qual_list = lappend(*postponed_oj_qual_list, clause);
    3080       47372 :             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       59432 :         is_pushed_down = false;
    3091       59432 :         maybe_equivalence = false;
    3092       59432 :         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       59432 :         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      494090 :         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      494090 :         if (check_redundant_nullability_qual(root, clause))
    3120        1156 :             return;
    3121             : 
    3122             :         /* Feed qual to the equivalence machinery, if allowed by caller */
    3123      492934 :         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      492934 :         maybe_outer_join = false;
    3130             :     }
    3131             : 
    3132             :     /*
    3133             :      * Build the RestrictInfo node itself.
    3134             :      */
    3135      552366 :     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      552366 :     if (bms_membership(relids) == BMS_MULTIPLE)
    3168             :     {
    3169      164348 :         List       *vars = pull_var_clause(clause,
    3170             :                                            PVC_RECURSE_AGGREGATES |
    3171             :                                            PVC_RECURSE_WINDOWFUNCS |
    3172             :                                            PVC_INCLUDE_PLACEHOLDERS);
    3173             :         Relids      where_needed;
    3174             : 
    3175      164348 :         if (is_clone)
    3176        5378 :             where_needed = bms_intersect(relids, root->all_baserels);
    3177             :         else
    3178      158970 :             where_needed = relids;
    3179      164348 :         add_vars_to_targetlist(root, vars, where_needed);
    3180      164348 :         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      552366 :     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      552366 :     if (restrictinfo->mergeopfamilies)
    3223             :     {
    3224      375128 :         if (maybe_equivalence)
    3225             :         {
    3226      317186 :             if (process_equivalence(root, &restrictinfo, jtitem->jdomain))
    3227      316924 :                 return;
    3228             :             /* EC rejected it, so set left_ec/right_ec the hard way ... */
    3229         262 :             if (restrictinfo->mergeopfamilies)   /* EC might have changed this */
    3230         208 :                 initialize_mergeclause_eclasses(root, restrictinfo);
    3231             :             /* ... and fall through to distribute_restrictinfo_to_rels */
    3232             :         }
    3233       57942 :         else if (maybe_outer_join && restrictinfo->can_join)
    3234             :         {
    3235             :             /* we need to set up left_ec/right_ec the hard way */
    3236       57234 :             initialize_mergeclause_eclasses(root, restrictinfo);
    3237             :             /* now see if it should go to any outer-join lists */
    3238             :             Assert(sjinfo != NULL);
    3239       57234 :             if (bms_is_subset(restrictinfo->left_relids,
    3240       28626 :                               outerjoin_nonnullable) &&
    3241       28626 :                 !bms_overlap(restrictinfo->right_relids,
    3242             :                              outerjoin_nonnullable))
    3243             :             {
    3244             :                 /* we have outervar = innervar */
    3245       27326 :                 OuterJoinClauseInfo *ojcinfo = makeNode(OuterJoinClauseInfo);
    3246             : 
    3247       27326 :                 ojcinfo->rinfo = restrictinfo;
    3248       27326 :                 ojcinfo->sjinfo = sjinfo;
    3249       27326 :                 root->left_join_clauses = lappend(root->left_join_clauses,
    3250             :                                                   ojcinfo);
    3251       27326 :                 return;
    3252             :             }
    3253       29908 :             if (bms_is_subset(restrictinfo->right_relids,
    3254       29748 :                               outerjoin_nonnullable) &&
    3255       29748 :                 !bms_overlap(restrictinfo->left_relids,
    3256             :                              outerjoin_nonnullable))
    3257             :             {
    3258             :                 /* we have innervar = outervar */
    3259       28448 :                 OuterJoinClauseInfo *ojcinfo = makeNode(OuterJoinClauseInfo);
    3260             : 
    3261       28448 :                 ojcinfo->rinfo = restrictinfo;
    3262       28448 :                 ojcinfo->sjinfo = sjinfo;
    3263       28448 :                 root->right_join_clauses = lappend(root->right_join_clauses,
    3264             :                                                    ojcinfo);
    3265       28448 :                 return;
    3266             :             }
    3267        1460 :             if (sjinfo->jointype == JOIN_FULL)
    3268             :             {
    3269             :                 /* FULL JOIN (above tests cannot match in this case) */
    3270        1264 :                 OuterJoinClauseInfo *ojcinfo = makeNode(OuterJoinClauseInfo);
    3271             : 
    3272        1264 :                 ojcinfo->rinfo = restrictinfo;
    3273        1264 :                 ojcinfo->sjinfo = sjinfo;
    3274        1264 :                 root->full_join_clauses = lappend(root->full_join_clauses,
    3275             :                                                   ojcinfo);
    3276        1264 :                 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         708 :             initialize_mergeclause_eclasses(root, restrictinfo);
    3284             :         }
    3285             :     }
    3286             : 
    3287             :     /* No EC special case applies, so push it into the clause lists */
    3288      178404 :     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      494090 : 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      494090 :     forced_null_var = find_forced_null_var(clause);
    3309      494090 :     if (forced_null_var == NULL)
    3310      491386 :         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        2704 :     if (forced_null_var->varnullingrels == NULL)
    3319        1442 :         return false;
    3320             : 
    3321        1412 :     foreach(lc, root->join_info_list)
    3322             :     {
    3323        1306 :         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        2462 :         if (sjinfo->jointype == JOIN_ANTI && sjinfo->ojrelid != 0 &&
    3331        1156 :             bms_is_member(sjinfo->ojrelid, forced_null_var->varnullingrels))
    3332        1156 :             return true;
    3333             :     }
    3334             : 
    3335         106 :     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      406134 : add_base_clause_to_rel(PlannerInfo *root, Index relid,
    3348             :                        RestrictInfo *restrictinfo)
    3349             : {
    3350      406134 :     RelOptInfo *rel = find_base_rel(root, relid);
    3351      406134 :     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      406134 :     if (!rte->inh || rte->relkind == RELKIND_PARTITIONED_TABLE)
    3371             :     {
    3372             :         /* Don't add the clause if it is always true */
    3373      404134 :         if (restriction_is_always_true(root, restrictinfo))
    3374         480 :             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      403654 :         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      405654 :     rel->baserestrictinfo = lappend(rel->baserestrictinfo, restrictinfo);
    3408             : 
    3409             :     /* Update security level info */
    3410      405654 :     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      522568 : 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      522568 :     if (restrictinfo->has_clone || restrictinfo->is_clone)
    3432       10720 :         return false;
    3433             : 
    3434             :     /* Check for NullTest qual */
    3435      511848 :     if (IsA(restrictinfo->clause, NullTest))
    3436             :     {
    3437       11474 :         NullTest   *nulltest = (NullTest *) restrictinfo->clause;
    3438             : 
    3439             :         /* is this NullTest an IS_NOT_NULL qual? */
    3440       11474 :         if (nulltest->nulltesttype != IS_NOT_NULL)
    3441        3040 :             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        8434 :         if (nulltest->argisrow)
    3448         156 :             return false;
    3449             : 
    3450        8278 :         return expr_is_nonnullable(root, nulltest->arg, true);
    3451             :     }
    3452             : 
    3453             :     /* If it's an OR, check its sub-clauses */
    3454      500374 :     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       30936 :         foreach(lc, ((BoolExpr *) restrictinfo->orclause)->args)
    3465             :         {
    3466       21676 :             Node       *orarg = (Node *) lfirst(lc);
    3467             : 
    3468       21676 :             if (!IsA(orarg, RestrictInfo))
    3469        3122 :                 continue;
    3470             : 
    3471       18554 :             if (restriction_is_always_true(root, (RestrictInfo *) orarg))
    3472           0 :                 return true;
    3473             :         }
    3474             :     }
    3475             : 
    3476      500374 :     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      511342 : 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      511342 :     if (restrictinfo->has_clone || restrictinfo->is_clone)
    3497       10720 :         return false;
    3498             : 
    3499             :     /* Check for NullTest qual */
    3500      500622 :     if (IsA(restrictinfo->clause, NullTest))
    3501             :     {
    3502        9832 :         NullTest   *nulltest = (NullTest *) restrictinfo->clause;
    3503             : 
    3504             :         /* is this NullTest an IS_NULL qual? */
    3505        9832 :         if (nulltest->nulltesttype != IS_NULL)
    3506        7192 :             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        2640 :         if (nulltest->argisrow)
    3513         120 :             return false;
    3514             : 
    3515        2520 :         return expr_is_nonnullable(root, nulltest->arg, true);
    3516             :     }
    3517             : 
    3518             :     /* If it's an OR, check its sub-clauses */
    3519      490790 :     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        9260 :         foreach(lc, ((BoolExpr *) restrictinfo->orclause)->args)
    3535             :         {
    3536        9260 :             Node       *orarg = (Node *) lfirst(lc);
    3537             : 
    3538        9260 :             if (!IsA(orarg, RestrictInfo) ||
    3539        7808 :                 !restriction_is_always_false(root, (RestrictInfo *) orarg))
    3540        9260 :                 return false;
    3541             :         }
    3542           0 :         return true;
    3543             :     }
    3544             : 
    3545      481530 :     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      476502 : distribute_restrictinfo_to_rels(PlannerInfo *root,
    3559             :                                 RestrictInfo *restrictinfo)
    3560             : {
    3561      476502 :     Relids      relids = restrictinfo->required_relids;
    3562             : 
    3563      476502 :     if (!bms_is_empty(relids))
    3564             :     {
    3565             :         int         relid;
    3566             : 
    3567      476502 :         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      406134 :             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       70368 :             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       70368 :             check_memoizable(restrictinfo);
    3594             : 
    3595             :             /*
    3596             :              * Add clause to the join lists of all the relevant relations.
    3597             :              */
    3598       70368 :             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      476502 : }
    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       37366 : 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       37366 :     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       37366 :     clause = (Node *) make_opclause(opno,
    3662             :                                     BOOLOID,    /* opresulttype */
    3663             :                                     false,  /* opretset */
    3664       37366 :                                     copyObject(item1),
    3665       37366 :                                     copyObject(item2),
    3666             :                                     InvalidOid,
    3667             :                                     collation);
    3668             : 
    3669             :     /* If both constant, try to reduce to a boolean constant. */
    3670       37366 :     if (both_const)
    3671             :     {
    3672         132 :         clause = eval_const_expressions(root, clause);
    3673             : 
    3674             :         /* If we produced const TRUE, just drop the clause */
    3675         132 :         if (clause && IsA(clause, Const))
    3676             :         {
    3677         126 :             Const      *cclause = (Const *) clause;
    3678             : 
    3679             :             Assert(cclause->consttype == BOOLOID);
    3680         126 :             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       37366 :     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       37366 :     if (bms_is_empty(relids))
    3702             :     {
    3703             :         /* eval at join domain's safe level */
    3704         132 :         relids = get_join_domain_min_rels(root, qualscope);
    3705             :         /* mark as gating qual */
    3706         132 :         pseudoconstant = true;
    3707             :         /* tell createplan.c to check for gating quals */
    3708         132 :         root->hasPseudoConstantQuals = true;
    3709             :     }
    3710             : 
    3711             :     /*
    3712             :      * Build the RestrictInfo node itself.
    3713             :      */
    3714       37366 :     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       37366 :     if (bms_membership(relids) == BMS_MULTIPLE)
    3742             :     {
    3743          60 :         List       *vars = pull_var_clause(clause,
    3744             :                                            PVC_RECURSE_AGGREGATES |
    3745             :                                            PVC_RECURSE_WINDOWFUNCS |
    3746             :                                            PVC_INCLUDE_PLACEHOLDERS);
    3747             : 
    3748          60 :         add_vars_to_targetlist(root, vars, relids);
    3749          60 :         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       37366 :     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       37366 :     distribute_restrictinfo_to_rels(root, restrictinfo);
    3769             : 
    3770       37366 :     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       87344 : 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       87344 :     clause = make_opclause(opno,
    3803             :                            BOOLOID, /* opresulttype */
    3804             :                            false,   /* opretset */
    3805       87344 :                            copyObject(item1),
    3806       87344 :                            copyObject(item2),
    3807             :                            InvalidOid,
    3808             :                            collation);
    3809             : 
    3810             :     /*
    3811             :      * Build the RestrictInfo node itself.
    3812             :      */
    3813       87344 :     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       87344 :     check_mergejoinable(restrictinfo);
    3826       87344 :     check_hashjoinable(restrictinfo);
    3827       87344 :     check_memoizable(restrictinfo);
    3828             : 
    3829       87344 :     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         132 : get_join_domain_min_rels(PlannerInfo *root, Relids domain_relids)
    3857             : {
    3858         132 :     Relids      result = bms_copy(domain_relids);
    3859             :     ListCell   *lc;
    3860             : 
    3861             :     /* Top-level join domain? */
    3862         132 :     if (bms_equal(result, root->all_query_rels))
    3863          66 :         return result;
    3864             : 
    3865             :     /* Nope, look for lower outer joins that could potentially commute out */
    3866         138 :     foreach(lc, root->join_info_list)
    3867             :     {
    3868          72 :         SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
    3869             : 
    3870         144 :         if (sjinfo->jointype == JOIN_LEFT &&
    3871          72 :             bms_is_member(sjinfo->ojrelid, result))
    3872             :         {
    3873           6 :             result = bms_del_member(result, sjinfo->ojrelid);
    3874           6 :             result = bms_del_members(result, sjinfo->syn_righthand);
    3875             :         }
    3876             :     }
    3877          66 :     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       12046 : 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       12046 :     Bitmapset  *seen_serials = NULL;
    3901             :     Index       rti;
    3902             : 
    3903             :     /* Scan all baserels for join clauses */
    3904       77146 :     for (rti = 1; rti < root->simple_rel_array_size; rti++)
    3905             :     {
    3906       65100 :         RelOptInfo *brel = root->simple_rel_array[rti];
    3907             :         ListCell   *lc;
    3908             : 
    3909       65100 :         if (brel == NULL)
    3910       44344 :             continue;
    3911       20756 :         if (brel->reloptkind != RELOPT_BASEREL)
    3912           0 :             continue;
    3913             : 
    3914       30716 :         foreach(lc, brel->joininfo)
    3915             :         {
    3916        9960 :             RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    3917        9960 :             Relids      relids = rinfo->required_relids;
    3918             : 
    3919        9960 :             if (!rinfo->is_clone)    /* else serial number is not unique */
    3920             :             {
    3921        9864 :                 if (bms_is_member(rinfo->rinfo_serial, seen_serials))
    3922        5286 :                     continue;   /* saw it already */
    3923        4578 :                 seen_serials = bms_add_member(seen_serials,
    3924             :                                               rinfo->rinfo_serial);
    3925             :             }
    3926             : 
    3927        4674 :             if (bms_membership(relids) == BMS_MULTIPLE)
    3928             :             {
    3929        4674 :                 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        4674 :                 if (rinfo->is_clone)
    3936          96 :                     where_needed = bms_intersect(relids, root->all_baserels);
    3937             :                 else
    3938        4578 :                     where_needed = relids;
    3939        4674 :                 add_vars_to_attr_needed(root, vars, where_needed);
    3940        4674 :                 list_free(vars);
    3941             :             }
    3942             :         }
    3943             :     }
    3944       12046 : }
    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      339204 : match_foreign_keys_to_quals(PlannerInfo *root)
    3963             : {
    3964      339204 :     List       *newlist = NIL;
    3965             :     ListCell   *lc;
    3966             : 
    3967      340984 :     foreach(lc, root->fkey_list)
    3968             :     {
    3969        1780 :         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        1780 :         if (fkinfo->con_relid >= root->simple_rel_array_size ||
    3981        1780 :             fkinfo->ref_relid >= root->simple_rel_array_size)
    3982           0 :             continue;           /* just paranoia */
    3983        1780 :         con_rel = root->simple_rel_array[fkinfo->con_relid];
    3984        1780 :         if (con_rel == NULL)
    3985          12 :             continue;
    3986        1768 :         ref_rel = root->simple_rel_array[fkinfo->ref_relid];
    3987        1768 :         if (ref_rel == NULL)
    3988          24 :             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        1744 :         if (con_rel->reloptkind != RELOPT_BASEREL ||
    3995        1744 :             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        4044 :         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        2300 :             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        2300 :             if (ec != NULL)
    4017             :             {
    4018         342 :                 fkinfo->nmatched_ec++;
    4019         342 :                 if (ec->ec_has_const)
    4020          74 :                     fkinfo->nconst_ec++;
    4021         342 :                 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        1958 :             con_attno = fkinfo->conkey[colno];
    4029        1958 :             ref_attno = fkinfo->confkey[colno];
    4030        1958 :             fpeqop = InvalidOid;    /* we'll look this up only if needed */
    4031             : 
    4032        5112 :             foreach(lc2, con_rel->joininfo)
    4033             :             {
    4034        3154 :                 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc2);
    4035        3154 :                 OpExpr     *clause = (OpExpr *) rinfo->clause;
    4036             :                 Var        *leftvar;
    4037             :                 Var        *rightvar;
    4038             : 
    4039             :                 /* Only binary OpExprs are useful for consideration */
    4040        6308 :                 if (!IsA(clause, OpExpr) ||
    4041        3154 :                     list_length(clause->args) != 2)
    4042           0 :                     continue;
    4043        3154 :                 leftvar = (Var *) get_leftop((Expr *) clause);
    4044        3154 :                 rightvar = (Var *) get_rightop((Expr *) clause);
    4045             : 
    4046             :                 /* Operands must be Vars, possibly with RelabelType */
    4047        3400 :                 while (leftvar && IsA(leftvar, RelabelType))
    4048         246 :                     leftvar = (Var *) ((RelabelType *) leftvar)->arg;
    4049        3154 :                 if (!(leftvar && IsA(leftvar, Var)))
    4050           0 :                     continue;
    4051        3382 :                 while (rightvar && IsA(rightvar, RelabelType))
    4052         228 :                     rightvar = (Var *) ((RelabelType *) rightvar)->arg;
    4053        3154 :                 if (!(rightvar && IsA(rightvar, Var)))
    4054          30 :                     continue;
    4055             : 
    4056             :                 /* Now try to match the vars to the current foreign key cols */
    4057        3124 :                 if (fkinfo->ref_relid == leftvar->varno &&
    4058        2998 :                     ref_attno == leftvar->varattno &&
    4059        1712 :                     fkinfo->con_relid == rightvar->varno &&
    4060        1712 :                     con_attno == rightvar->varattno)
    4061             :                 {
    4062             :                     /* Vars match, but is it the right operator? */
    4063        1634 :                     if (clause->opno == fkinfo->conpfeqop[colno])
    4064             :                     {
    4065        1634 :                         fkinfo->rinfos[colno] = lappend(fkinfo->rinfos[colno],
    4066             :                                                         rinfo);
    4067        1634 :                         fkinfo->nmatched_ri++;
    4068             :                     }
    4069             :                 }
    4070        1490 :                 else if (fkinfo->ref_relid == rightvar->varno &&
    4071          90 :                          ref_attno == rightvar->varattno &&
    4072          36 :                          fkinfo->con_relid == leftvar->varno &&
    4073          36 :                          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          36 :                     if (!OidIsValid(fpeqop))
    4083          36 :                         fpeqop = get_commutator(fkinfo->conpfeqop[colno]);
    4084          36 :                     if (clause->opno == fpeqop)
    4085             :                     {
    4086          36 :                         fkinfo->rinfos[colno] = lappend(fkinfo->rinfos[colno],
    4087             :                                                         rinfo);
    4088          36 :                         fkinfo->nmatched_ri++;
    4089             :                     }
    4090             :                 }
    4091             :             }
    4092             :             /* If we found any matching loose quals, count col as matched */
    4093        1958 :             if (fkinfo->rinfos[colno])
    4094        1670 :                 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        1744 :         if ((fkinfo->nmatched_ec + fkinfo->nmatched_rcols) == fkinfo->nkeys)
    4104        1480 :             newlist = lappend(newlist, fkinfo);
    4105             :     }
    4106             :     /* Replace fkey_list, thereby discarding any useless entries */
    4107      339204 :     root->fkey_list = newlist;
    4108      339204 : }
    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      677076 : check_mergejoinable(RestrictInfo *restrictinfo)
    4128             : {
    4129      677076 :     Expr       *clause = restrictinfo->clause;
    4130             :     Oid         opno;
    4131             :     Node       *leftarg;
    4132             : 
    4133      677076 :     if (restrictinfo->pseudoconstant)
    4134       10736 :         return;
    4135      666340 :     if (!is_opclause(clause))
    4136       82572 :         return;
    4137      583768 :     if (list_length(((OpExpr *) clause)->args) != 2)
    4138          24 :         return;
    4139             : 
    4140      583744 :     opno = ((OpExpr *) clause)->opno;
    4141      583744 :     leftarg = linitial(((OpExpr *) clause)->args);
    4142             : 
    4143      583744 :     if (op_mergejoinable(opno, exprType(leftarg)) &&
    4144      499738 :         !contain_volatile_functions((Node *) restrictinfo))
    4145      499706 :         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      157712 : check_hashjoinable(RestrictInfo *restrictinfo)
    4165             : {
    4166      157712 :     Expr       *clause = restrictinfo->clause;
    4167             :     Oid         opno;
    4168             :     Node       *leftarg;
    4169             : 
    4170      157712 :     if (restrictinfo->pseudoconstant)
    4171        3472 :         return;
    4172      154240 :     if (!is_opclause(clause))
    4173        7560 :         return;
    4174      146680 :     if (list_length(((OpExpr *) clause)->args) != 2)
    4175           0 :         return;
    4176             : 
    4177      146680 :     opno = ((OpExpr *) clause)->opno;
    4178      146680 :     leftarg = linitial(((OpExpr *) clause)->args);
    4179             : 
    4180      146680 :     if (op_hashjoinable(opno, exprType(leftarg)) &&
    4181      143308 :         !contain_volatile_functions((Node *) restrictinfo))
    4182      143300 :         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      157712 : check_memoizable(RestrictInfo *restrictinfo)
    4193             : {
    4194             :     TypeCacheEntry *typentry;
    4195      157712 :     Expr       *clause = restrictinfo->clause;
    4196             :     Oid         lefttype;
    4197             :     Oid         righttype;
    4198             : 
    4199      157712 :     if (restrictinfo->pseudoconstant)
    4200        3472 :         return;
    4201      154240 :     if (!is_opclause(clause))
    4202        7560 :         return;
    4203      146680 :     if (list_length(((OpExpr *) clause)->args) != 2)
    4204           0 :         return;
    4205             : 
    4206      146680 :     lefttype = exprType(linitial(((OpExpr *) clause)->args));
    4207             : 
    4208      146680 :     typentry = lookup_type_cache(lefttype, TYPECACHE_HASH_PROC |
    4209             :                                  TYPECACHE_EQ_OPR);
    4210             : 
    4211      146680 :     if (OidIsValid(typentry->hash_proc) && OidIsValid(typentry->eq_opr))
    4212      146272 :         restrictinfo->left_hasheqoperator = typentry->eq_opr;
    4213             : 
    4214      146680 :     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      146680 :     if (lefttype != righttype)
    4221        2320 :         typentry = lookup_type_cache(righttype, TYPECACHE_HASH_PROC |
    4222             :                                      TYPECACHE_EQ_OPR);
    4223             : 
    4224      146680 :     if (OidIsValid(typentry->hash_proc) && OidIsValid(typentry->eq_opr))
    4225      146068 :         restrictinfo->right_hasheqoperator = typentry->eq_opr;
    4226             : }

Generated by: LCOV version 1.16