LCOV - code coverage report
Current view: top level - src/backend/optimizer/plan - initsplan.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 96.0 % 1642 1576
Test Date: 2026-01-26 10:56:24 Functions: 100.0 % 38 38
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 78.4 % 1136 891

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * initsplan.c
       4                 :             :  *        Target list, group by, qualification, joininfo initialization routines
       5                 :             :  *
       6                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :             :  *
       9                 :             :  *
      10                 :             :  * IDENTIFICATION
      11                 :             :  *        src/backend/optimizer/plan/initsplan.c
      12                 :             :  *
      13                 :             :  *-------------------------------------------------------------------------
      14                 :             :  */
      15                 :             : #include "postgres.h"
      16                 :             : 
      17                 :             : #include "access/nbtree.h"
      18                 :             : #include "catalog/pg_constraint.h"
      19                 :             : #include "catalog/pg_type.h"
      20                 :             : #include "nodes/makefuncs.h"
      21                 :             : #include "nodes/nodeFuncs.h"
      22                 :             : #include "optimizer/clauses.h"
      23                 :             : #include "optimizer/cost.h"
      24                 :             : #include "optimizer/inherit.h"
      25                 :             : #include "optimizer/joininfo.h"
      26                 :             : #include "optimizer/optimizer.h"
      27                 :             : #include "optimizer/pathnode.h"
      28                 :             : #include "optimizer/paths.h"
      29                 :             : #include "optimizer/placeholder.h"
      30                 :             : #include "optimizer/planmain.h"
      31                 :             : #include "optimizer/planner.h"
      32                 :             : #include "optimizer/restrictinfo.h"
      33                 :             : #include "parser/analyze.h"
      34                 :             : #include "rewrite/rewriteManip.h"
      35                 :             : #include "utils/lsyscache.h"
      36                 :             : #include "utils/rel.h"
      37                 :             : #include "utils/typcache.h"
      38                 :             : 
      39                 :             : /* These parameters are set by GUC */
      40                 :             : int                     from_collapse_limit;
      41                 :             : int                     join_collapse_limit;
      42                 :             : 
      43                 :             : 
      44                 :             : /*
      45                 :             :  * deconstruct_jointree requires multiple passes over the join tree, because we
      46                 :             :  * need to finish computing JoinDomains before we start distributing quals.
      47                 :             :  * As long as we have to do that, other information such as the relevant
      48                 :             :  * qualscopes might as well be computed in the first pass too.
      49                 :             :  *
      50                 :             :  * deconstruct_recurse recursively examines the join tree and builds a List
      51                 :             :  * (in depth-first traversal order) of JoinTreeItem structs, which are then
      52                 :             :  * processed iteratively by deconstruct_distribute.  If there are outer
      53                 :             :  * joins, non-degenerate outer join clauses are processed in a third pass
      54                 :             :  * deconstruct_distribute_oj_quals.
      55                 :             :  *
      56                 :             :  * The JoinTreeItem structs themselves can be freed at the end of
      57                 :             :  * deconstruct_jointree, but do not modify or free their substructure,
      58                 :             :  * as the relid sets may also be pointed to by RestrictInfo and
      59                 :             :  * SpecialJoinInfo nodes.
      60                 :             :  */
      61                 :             : typedef struct JoinTreeItem
      62                 :             : {
      63                 :             :         /* Fields filled during deconstruct_recurse: */
      64                 :             :         Node       *jtnode;                     /* jointree node to examine */
      65                 :             :         JoinDomain *jdomain;            /* join domain for its ON/WHERE clauses */
      66                 :             :         struct JoinTreeItem *jti_parent;        /* JoinTreeItem for this node's
      67                 :             :                                                                                  * parent, or NULL if it's the top */
      68                 :             :         Relids          qualscope;              /* base+OJ Relids syntactically included in
      69                 :             :                                                                  * this jointree node */
      70                 :             :         Relids          inner_join_rels;        /* base+OJ Relids syntactically included
      71                 :             :                                                                          * in inner joins appearing at or below
      72                 :             :                                                                          * this jointree node */
      73                 :             :         Relids          left_rels;              /* if join node, Relids of the left side */
      74                 :             :         Relids          right_rels;             /* if join node, Relids of the right side */
      75                 :             :         Relids          nonnullable_rels;       /* if outer join, Relids of the
      76                 :             :                                                                          * non-nullable side */
      77                 :             :         /* Fields filled during deconstruct_distribute: */
      78                 :             :         SpecialJoinInfo *sjinfo;        /* if outer join, its SpecialJoinInfo */
      79                 :             :         List       *oj_joinclauses; /* outer join quals not yet distributed */
      80                 :             :         List       *lateral_clauses;    /* quals postponed from children due to
      81                 :             :                                                                          * lateral references */
      82                 :             : } JoinTreeItem;
      83                 :             : 
      84                 :             : 
      85                 :             : static bool is_partial_agg_memory_risky(PlannerInfo *root);
      86                 :             : static void create_agg_clause_infos(PlannerInfo *root);
      87                 :             : static void create_grouping_expr_infos(PlannerInfo *root);
      88                 :             : static EquivalenceClass *get_eclass_for_sortgroupclause(PlannerInfo *root,
      89                 :             :                                                                                                                 SortGroupClause *sgc,
      90                 :             :                                                                                                                 Expr *expr);
      91                 :             : static void extract_lateral_references(PlannerInfo *root, RelOptInfo *brel,
      92                 :             :                                                                            Index rtindex);
      93                 :             : static List *deconstruct_recurse(PlannerInfo *root, Node *jtnode,
      94                 :             :                                                                  JoinDomain *parent_domain,
      95                 :             :                                                                  JoinTreeItem *parent_jtitem,
      96                 :             :                                                                  List **item_list);
      97                 :             : static void deconstruct_distribute(PlannerInfo *root, JoinTreeItem *jtitem);
      98                 :             : static void process_security_barrier_quals(PlannerInfo *root,
      99                 :             :                                                                                    int rti, JoinTreeItem *jtitem);
     100                 :             : static void mark_rels_nulled_by_join(PlannerInfo *root, Index ojrelid,
     101                 :             :                                                                          Relids lower_rels);
     102                 :             : static SpecialJoinInfo *make_outerjoininfo(PlannerInfo *root,
     103                 :             :                                                                                    Relids left_rels, Relids right_rels,
     104                 :             :                                                                                    Relids inner_join_rels,
     105                 :             :                                                                                    JoinType jointype, Index ojrelid,
     106                 :             :                                                                                    List *clause);
     107                 :             : static void compute_semijoin_info(PlannerInfo *root, SpecialJoinInfo *sjinfo,
     108                 :             :                                                                   List *clause);
     109                 :             : static void deconstruct_distribute_oj_quals(PlannerInfo *root,
     110                 :             :                                                                                         List *jtitems,
     111                 :             :                                                                                         JoinTreeItem *jtitem);
     112                 :             : static void distribute_quals_to_rels(PlannerInfo *root, List *clauses,
     113                 :             :                                                                          JoinTreeItem *jtitem,
     114                 :             :                                                                          SpecialJoinInfo *sjinfo,
     115                 :             :                                                                          Index security_level,
     116                 :             :                                                                          Relids qualscope,
     117                 :             :                                                                          Relids ojscope,
     118                 :             :                                                                          Relids outerjoin_nonnullable,
     119                 :             :                                                                          Relids incompatible_relids,
     120                 :             :                                                                          bool allow_equivalence,
     121                 :             :                                                                          bool has_clone,
     122                 :             :                                                                          bool is_clone,
     123                 :             :                                                                          List **postponed_oj_qual_list);
     124                 :             : static void distribute_qual_to_rels(PlannerInfo *root, Node *clause,
     125                 :             :                                                                         JoinTreeItem *jtitem,
     126                 :             :                                                                         SpecialJoinInfo *sjinfo,
     127                 :             :                                                                         Index security_level,
     128                 :             :                                                                         Relids qualscope,
     129                 :             :                                                                         Relids ojscope,
     130                 :             :                                                                         Relids outerjoin_nonnullable,
     131                 :             :                                                                         Relids incompatible_relids,
     132                 :             :                                                                         bool allow_equivalence,
     133                 :             :                                                                         bool has_clone,
     134                 :             :                                                                         bool is_clone,
     135                 :             :                                                                         List **postponed_oj_qual_list);
     136                 :             : static bool check_redundant_nullability_qual(PlannerInfo *root, Node *clause);
     137                 :             : static Relids get_join_domain_min_rels(PlannerInfo *root, Relids domain_relids);
     138                 :             : static void check_mergejoinable(RestrictInfo *restrictinfo);
     139                 :             : static void check_hashjoinable(RestrictInfo *restrictinfo);
     140                 :             : static void check_memoizable(RestrictInfo *restrictinfo);
     141                 :             : 
     142                 :             : 
     143                 :             : /*****************************************************************************
     144                 :             :  *
     145                 :             :  *       JOIN TREES
     146                 :             :  *
     147                 :             :  *****************************************************************************/
     148                 :             : 
     149                 :             : /*
     150                 :             :  * add_base_rels_to_query
     151                 :             :  *
     152                 :             :  *        Scan the query's jointree and create baserel RelOptInfos for all
     153                 :             :  *        the base relations (e.g., table, subquery, and function RTEs)
     154                 :             :  *        appearing in the jointree.
     155                 :             :  *
     156                 :             :  * The initial invocation must pass root->parse->jointree as the value of
     157                 :             :  * jtnode.  Internally, the function recurses through the jointree.
     158                 :             :  *
     159                 :             :  * At the end of this process, there should be one baserel RelOptInfo for
     160                 :             :  * every non-join RTE that is used in the query.  Some of the baserels
     161                 :             :  * may be appendrel parents, which will require additional "otherrel"
     162                 :             :  * RelOptInfos for their member rels, but those are added later.
     163                 :             :  */
     164                 :             : void
     165                 :       92404 : add_base_rels_to_query(PlannerInfo *root, Node *jtnode)
     166                 :             : {
     167         [ +  - ]:       92404 :         if (jtnode == NULL)
     168                 :           0 :                 return;
     169         [ +  + ]:       92404 :         if (IsA(jtnode, RangeTblRef))
     170                 :             :         {
     171                 :       47629 :                 int                     varno = ((RangeTblRef *) jtnode)->rtindex;
     172                 :             : 
     173                 :       47629 :                 (void) build_simple_rel(root, varno, NULL);
     174                 :       47629 :         }
     175         [ +  + ]:       44775 :         else if (IsA(jtnode, FromExpr))
     176                 :             :         {
     177                 :       35413 :                 FromExpr   *f = (FromExpr *) jtnode;
     178                 :       35413 :                 ListCell   *l;
     179                 :             : 
     180   [ +  -  +  +  :       75188 :                 foreach(l, f->fromlist)
                   +  + ]
     181                 :       39775 :                         add_base_rels_to_query(root, lfirst(l));
     182                 :       35413 :         }
     183         [ +  - ]:        9362 :         else if (IsA(jtnode, JoinExpr))
     184                 :             :         {
     185                 :        9362 :                 JoinExpr   *j = (JoinExpr *) jtnode;
     186                 :             : 
     187                 :        9362 :                 add_base_rels_to_query(root, j->larg);
     188                 :        9362 :                 add_base_rels_to_query(root, j->rarg);
     189                 :        9362 :         }
     190                 :             :         else
     191   [ #  #  #  # ]:           0 :                 elog(ERROR, "unrecognized node type: %d",
     192                 :             :                          (int) nodeTag(jtnode));
     193                 :       92404 : }
     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                 :       33901 : add_other_rels_to_query(PlannerInfo *root)
     204                 :             : {
     205                 :       33901 :         int                     rti;
     206                 :             : 
     207         [ +  + ]:      104517 :         for (rti = 1; rti < root->simple_rel_array_size; rti++)
     208                 :             :         {
     209                 :       70616 :                 RelOptInfo *rel = root->simple_rel_array[rti];
     210                 :       70616 :                 RangeTblEntry *rte = root->simple_rte_array[rti];
     211                 :             : 
     212                 :             :                 /* there may be empty slots corresponding to non-baserel RTEs */
     213         [ +  + ]:       70616 :                 if (rel == NULL)
     214                 :       16382 :                         continue;
     215                 :             : 
     216                 :             :                 /* Ignore any "otherrels" that were already added. */
     217         [ +  + ]:       54234 :                 if (rel->reloptkind != RELOPT_BASEREL)
     218                 :        7800 :                         continue;
     219                 :             : 
     220                 :             :                 /* If it's marked as inheritable, look for children. */
     221         [ +  + ]:       46434 :                 if (rte->inh)
     222                 :        2835 :                         expand_inherited_rtentry(root, rel, rte, rti);
     223      [ -  +  + ]:       70616 :         }
     224                 :       33901 : }
     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                 :       33906 : build_base_rel_tlists(PlannerInfo *root, List *final_tlist)
     243                 :             : {
     244                 :       33906 :         List       *tlist_vars = pull_var_clause((Node *) final_tlist,
     245                 :             :                                                                                          PVC_RECURSE_AGGREGATES |
     246                 :             :                                                                                          PVC_RECURSE_WINDOWFUNCS |
     247                 :             :                                                                                          PVC_INCLUDE_PLACEHOLDERS);
     248                 :             : 
     249         [ +  + ]:       33906 :         if (tlist_vars != NIL)
     250                 :             :         {
     251                 :       31916 :                 add_vars_to_targetlist(root, tlist_vars, bms_make_singleton(0));
     252                 :       31916 :                 list_free(tlist_vars);
     253                 :       31916 :         }
     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         [ +  + ]:       33906 :         if (root->parse->havingQual)
     260                 :             :         {
     261                 :         132 :                 List       *having_vars = pull_var_clause(root->parse->havingQual,
     262                 :             :                                                                                                   PVC_RECURSE_AGGREGATES |
     263                 :             :                                                                                                   PVC_INCLUDE_PLACEHOLDERS);
     264                 :             : 
     265         [ +  + ]:         132 :                 if (having_vars != NIL)
     266                 :             :                 {
     267                 :         224 :                         add_vars_to_targetlist(root, having_vars,
     268                 :         112 :                                                                    bms_make_singleton(0));
     269                 :         112 :                         list_free(having_vars);
     270                 :         112 :                 }
     271                 :         132 :         }
     272                 :       33906 : }
     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                 :       61673 : add_vars_to_targetlist(PlannerInfo *root, List *vars,
     290                 :             :                                            Relids where_needed)
     291                 :             : {
     292                 :       61673 :         ListCell   *temp;
     293                 :             : 
     294         [ +  - ]:       61673 :         Assert(!bms_is_empty(where_needed));
     295                 :             : 
     296   [ +  +  +  +  :      215531 :         foreach(temp, vars)
                   +  + ]
     297                 :             :         {
     298                 :      153858 :                 Node       *node = (Node *) lfirst(temp);
     299                 :             : 
     300         [ +  + ]:      153858 :                 if (IsA(node, Var))
     301                 :             :                 {
     302                 :      153347 :                         Var                *var = (Var *) node;
     303                 :      153347 :                         RelOptInfo *rel = find_base_rel(root, var->varno);
     304                 :      153347 :                         int                     attno = var->varattno;
     305                 :             : 
     306         [ +  + ]:      153347 :                         if (bms_is_subset(where_needed, rel->relids))
     307                 :         241 :                                 continue;
     308         [ +  - ]:      153106 :                         Assert(attno >= rel->min_attr && attno <= rel->max_attr);
     309                 :      153106 :                         attno -= rel->min_attr;
     310         [ +  + ]:      153106 :                         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                 :      114896 :                                 var = copyObject(var);
     320                 :      114896 :                                 var->varnullingrels = NULL;
     321                 :      114896 :                                 rel->reltarget->exprs = lappend(rel->reltarget->exprs, var);
     322                 :             :                                 /* reltarget cost and width will be computed later */
     323                 :      114896 :                         }
     324                 :      306212 :                         rel->attr_needed[attno] = bms_add_members(rel->attr_needed[attno],
     325                 :      153106 :                                                                                                           where_needed);
     326         [ +  + ]:      153347 :                 }
     327         [ +  - ]:         511 :                 else if (IsA(node, PlaceHolderVar))
     328                 :             :                 {
     329                 :         511 :                         PlaceHolderVar *phv = (PlaceHolderVar *) node;
     330                 :         511 :                         PlaceHolderInfo *phinfo = find_placeholder_info(root, phv);
     331                 :             : 
     332                 :        1022 :                         phinfo->ph_needed = bms_add_members(phinfo->ph_needed,
     333                 :         511 :                                                                                                 where_needed);
     334                 :         511 :                 }
     335                 :             :                 else
     336   [ #  #  #  # ]:           0 :                         elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
     337      [ -  +  + ]:      153858 :         }
     338                 :       61673 : }
     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                 :        1479 : add_vars_to_attr_needed(PlannerInfo *root, List *vars,
     361                 :             :                                                 Relids where_needed)
     362                 :             : {
     363                 :        1479 :         ListCell   *temp;
     364                 :             : 
     365         [ +  - ]:        1479 :         Assert(!bms_is_empty(where_needed));
     366                 :             : 
     367   [ +  +  +  +  :        3597 :         foreach(temp, vars)
                   +  + ]
     368                 :             :         {
     369                 :        2118 :                 Node       *node = (Node *) lfirst(temp);
     370                 :             : 
     371         [ +  + ]:        2118 :                 if (IsA(node, Var))
     372                 :             :                 {
     373                 :        2111 :                         Var                *var = (Var *) node;
     374                 :        2111 :                         RelOptInfo *rel = find_base_rel(root, var->varno);
     375                 :        2111 :                         int                     attno = var->varattno;
     376                 :             : 
     377         [ +  + ]:        2111 :                         if (bms_is_subset(where_needed, rel->relids))
     378                 :         138 :                                 continue;
     379         [ +  - ]:        1973 :                         Assert(attno >= rel->min_attr && attno <= rel->max_attr);
     380                 :        1973 :                         attno -= rel->min_attr;
     381                 :        3946 :                         rel->attr_needed[attno] = bms_add_members(rel->attr_needed[attno],
     382                 :        1973 :                                                                                                           where_needed);
     383         [ +  + ]:        2111 :                 }
     384         [ +  - ]:           7 :                 else if (IsA(node, PlaceHolderVar))
     385                 :             :                 {
     386                 :           7 :                         PlaceHolderVar *phv = (PlaceHolderVar *) node;
     387                 :           7 :                         PlaceHolderInfo *phinfo = find_placeholder_info(root, phv);
     388                 :             : 
     389                 :          14 :                         phinfo->ph_needed = bms_add_members(phinfo->ph_needed,
     390                 :           7 :                                                                                                 where_needed);
     391                 :           7 :                 }
     392                 :             :                 else
     393   [ #  #  #  # ]:           0 :                         elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
     394      [ -  +  + ]:        2118 :         }
     395                 :        1479 : }
     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                 :       33901 : remove_useless_groupby_columns(PlannerInfo *root)
     420                 :             : {
     421                 :       33901 :         Query      *parse = root->parse;
     422                 :       33901 :         Bitmapset **groupbyattnos;
     423                 :       33901 :         Bitmapset **surplusvars;
     424                 :       33901 :         bool            tryremove = false;
     425                 :       33901 :         ListCell   *lc;
     426                 :       33901 :         int                     relid;
     427                 :             : 
     428                 :             :         /* No chance to do anything if there are less than two GROUP BY items */
     429         [ +  + ]:       33901 :         if (list_length(root->processed_groupClause) < 2)
     430                 :       33553 :                 return;
     431                 :             : 
     432                 :             :         /* Don't fiddle with the GROUP BY clause if the query has grouping sets */
     433         [ +  + ]:         348 :         if (parse->groupingSets)
     434                 :         121 :                 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                 :         227 :         groupbyattnos = palloc0_array(Bitmapset *, list_length(parse->rtable) + 1);
     442   [ +  -  +  +  :         828 :         foreach(lc, root->processed_groupClause)
                   +  + ]
     443                 :             :         {
     444                 :         601 :                 SortGroupClause *sgc = lfirst_node(SortGroupClause, lc);
     445                 :         601 :                 TargetEntry *tle = get_sortgroupclause_tle(sgc, parse->targetList);
     446                 :         601 :                 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   [ +  +  -  + ]:         601 :                 if (!IsA(var, Var) ||
     457                 :         472 :                         var->varlevelsup > 0)
     458                 :         129 :                         continue;
     459                 :             : 
     460                 :             :                 /* OK, remember we have this Var */
     461                 :         472 :                 relid = var->varno;
     462         [ -  + ]:         472 :                 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                 :         472 :                 tryremove |= !bms_is_empty(groupbyattnos[relid]);
     470                 :         944 :                 groupbyattnos[relid] = bms_add_member(groupbyattnos[relid],
     471                 :         472 :                                                                                           var->varattno - FirstLowInvalidHeapAttributeNumber);
     472         [ +  + ]:         601 :         }
     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         [ +  + ]:         227 :         if (!tryremove)
     479                 :          70 :                 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                 :         157 :         surplusvars = NULL;                     /* don't allocate array unless required */
     488                 :         157 :         relid = 0;
     489   [ +  -  +  +  :         666 :         foreach(lc, parse->rtable)
                   +  + ]
     490                 :             :         {
     491                 :         509 :                 RangeTblEntry *rte = lfirst_node(RangeTblEntry, lc);
     492                 :         509 :                 RelOptInfo *rel;
     493                 :         509 :                 Bitmapset  *relattnos;
     494                 :         509 :                 Bitmapset  *best_keycolumns = NULL;
     495                 :         509 :                 int32           best_nkeycolumns = PG_INT32_MAX;
     496                 :             : 
     497                 :         509 :                 relid++;
     498                 :             : 
     499                 :             :                 /* Only plain relations could have primary-key constraints */
     500         [ +  + ]:         509 :                 if (rte->rtekind != RTE_RELATION)
     501                 :         259 :                         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   [ +  +  +  + ]:         250 :                 if (rte->inh && rte->relkind != RELKIND_PARTITIONED_TABLE)
     509                 :           3 :                         continue;
     510                 :             : 
     511                 :             :                 /* Nothing to do unless this rel has multiple Vars in GROUP BY */
     512                 :         247 :                 relattnos = groupbyattnos[relid];
     513         [ +  + ]:         247 :                 if (bms_membership(relattnos) != BMS_MULTIPLE)
     514                 :          95 :                         continue;
     515                 :             : 
     516                 :         152 :                 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   [ +  +  +  +  :         477 :                 foreach_node(IndexOptInfo, index, rel->indexlist)
             +  +  +  + ]
     524                 :             :                 {
     525                 :         173 :                         Bitmapset  *ind_attnos;
     526                 :         173 :                         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   [ +  +  +  +  :         173 :                         if (!index->unique || !index->immediate || index->indpred != NIL)
                   -  + ]
     534                 :          68 :                                 continue;
     535                 :             : 
     536                 :             :                         /* For simplicity, we currently don't support expression indexes */
     537         [ -  + ]:         105 :                         if (index->indexprs != NIL)
     538                 :           0 :                                 continue;
     539                 :             : 
     540                 :         105 :                         ind_attnos = NULL;
     541                 :         105 :                         nulls_check_ok = true;
     542         [ +  + ]:         266 :                         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   [ +  +  +  + ]:         161 :                                 if (!index->nullsnotdistinct &&
     553                 :         320 :                                         !bms_is_member(index->indexkeys[i],
     554                 :         160 :                                                                    rel->notnullattnums))
     555                 :             :                                 {
     556                 :           1 :                                         nulls_check_ok = false;
     557                 :           1 :                                         break;
     558                 :             :                                 }
     559                 :             : 
     560                 :         160 :                                 ind_attnos =
     561                 :         320 :                                         bms_add_member(ind_attnos,
     562                 :         160 :                                                                    index->indexkeys[i] -
     563                 :             :                                                                    FirstLowInvalidHeapAttributeNumber);
     564                 :         160 :                         }
     565                 :             : 
     566         [ +  + ]:         105 :                         if (!nulls_check_ok)
     567                 :           1 :                                 continue;
     568                 :             : 
     569                 :             :                         /*
     570                 :             :                          * Skip any indexes where the indexed columns aren't a proper
     571                 :             :                          * subset of the GROUP BY.
     572                 :             :                          */
     573         [ +  + ]:         104 :                         if (bms_subset_compare(ind_attnos, relattnos) != BMS_SUBSET1)
     574                 :          48 :                                 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         [ +  + ]:          56 :                         if (index->nkeycolumns < best_nkeycolumns)
     585                 :             :                         {
     586                 :          53 :                                 best_keycolumns = ind_attnos;
     587                 :          53 :                                 best_nkeycolumns = index->nkeycolumns;
     588                 :          53 :                         }
     589         [ +  + ]:         325 :                 }
     590                 :             : 
     591                 :             :                 /* Did we find a suitable index? */
     592         [ +  + ]:         152 :                 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         [ +  + ]:          53 :                         if (surplusvars == NULL)
     599                 :          52 :                                 surplusvars = palloc0_array(Bitmapset *, list_length(parse->rtable) + 1);
     600                 :             : 
     601                 :             :                         /* Remember the attnos of the removable columns */
     602                 :          53 :                         surplusvars[relid] = bms_difference(relattnos, best_keycolumns);
     603                 :          53 :                 }
     604         [ +  + ]:         509 :         }
     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         [ +  + ]:         157 :         if (surplusvars != NULL)
     612                 :             :         {
     613                 :          52 :                 List       *new_groupby = NIL;
     614                 :             : 
     615   [ +  -  +  +  :         214 :                 foreach(lc, root->processed_groupClause)
                   +  + ]
     616                 :             :                 {
     617                 :         162 :                         SortGroupClause *sgc = lfirst_node(SortGroupClause, lc);
     618                 :         162 :                         TargetEntry *tle = get_sortgroupclause_tle(sgc, parse->targetList);
     619                 :         162 :                         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         [ +  - ]:         162 :                         if (!IsA(var, Var) ||
     626   [ +  -  +  + ]:         162 :                                 var->varlevelsup > 0 ||
     627                 :         324 :                                 !bms_is_member(var->varattno - FirstLowInvalidHeapAttributeNumber,
     628                 :         162 :                                                            surplusvars[var->varno]))
     629                 :         102 :                                 new_groupby = lappend(new_groupby, sgc);
     630                 :         162 :                 }
     631                 :             : 
     632                 :          52 :                 root->processed_groupClause = new_groupby;
     633                 :          52 :         }
     634                 :       33901 : }
     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                 :       33901 : setup_eager_aggregation(PlannerInfo *root)
     643                 :             : {
     644                 :             :         /*
     645                 :             :          * Don't apply eager aggregation if disabled by user.
     646                 :             :          */
     647         [ +  + ]:       33901 :         if (!enable_eager_aggregate)
     648                 :          80 :                 return;
     649                 :             : 
     650                 :             :         /*
     651                 :             :          * Don't apply eager aggregation if there are no available GROUP BY
     652                 :             :          * clauses.
     653                 :             :          */
     654         [ +  + ]:       33821 :         if (!root->processed_groupClause)
     655                 :       33179 :                 return;
     656                 :             : 
     657                 :             :         /*
     658                 :             :          * For now we don't try to support grouping sets.
     659                 :             :          */
     660         [ +  + ]:         642 :         if (root->parse->groupingSets)
     661                 :         137 :                 return;
     662                 :             : 
     663                 :             :         /*
     664                 :             :          * For now we don't try to support DISTINCT or ORDER BY aggregates.
     665                 :             :          */
     666         [ +  + ]:         505 :         if (root->numOrderedAggs > 0)
     667                 :          25 :                 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   [ +  +  -  + ]:         480 :         if (root->hasNonPartialAggs || root->hasNonSerialAggs)
     675                 :          24 :                 return;
     676                 :             : 
     677                 :             :         /*
     678                 :             :          * We don't try to apply eager aggregation if there are set-returning
     679                 :             :          * functions in targetlist.
     680                 :             :          */
     681         [ +  + ]:         456 :         if (root->parse->hasTargetSRFs)
     682                 :          14 :                 return;
     683                 :             : 
     684                 :             :         /*
     685                 :             :          * Eager aggregation only makes sense if there are multiple base rels in
     686                 :             :          * the query.
     687                 :             :          */
     688         [ +  + ]:         442 :         if (bms_membership(root->all_baserels) != BMS_MULTIPLE)
     689                 :         288 :                 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         [ -  + ]:         154 :         if (is_partial_agg_memory_risky(root))
     696                 :           0 :                 return;
     697                 :             : 
     698                 :             :         /*
     699                 :             :          * Collect aggregate expressions and plain Vars that appear in the
     700                 :             :          * targetlist and havingQual.
     701                 :             :          */
     702                 :         154 :         create_agg_clause_infos(root);
     703                 :             : 
     704                 :             :         /*
     705                 :             :          * If there are no suitable aggregate expressions, we cannot apply eager
     706                 :             :          * aggregation.
     707                 :             :          */
     708         [ +  + ]:         154 :         if (root->agg_clause_list == NIL)
     709                 :          53 :                 return;
     710                 :             : 
     711                 :             :         /*
     712                 :             :          * Collect grouping expressions that appear in grouping clauses.
     713                 :             :          */
     714                 :         101 :         create_grouping_expr_infos(root);
     715                 :       33901 : }
     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                 :         154 : is_partial_agg_memory_risky(PlannerInfo *root)
     730                 :             : {
     731                 :         154 :         ListCell   *lc;
     732                 :             : 
     733   [ +  +  +  +  :         296 :         foreach(lc, root->aggtransinfos)
             +  +  -  + ]
     734                 :             :         {
     735                 :         142 :                 AggTransInfo *transinfo = lfirst_node(AggTransInfo, lc);
     736                 :             : 
     737         [ +  - ]:         142 :                 if (transinfo->aggtransspace < 0)
     738                 :           0 :                         return true;
     739         [ -  + ]:         142 :         }
     740                 :             : 
     741                 :         154 :         return false;
     742                 :         154 : }
     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                 :         154 : create_agg_clause_infos(PlannerInfo *root)
     751                 :             : {
     752                 :         154 :         List       *tlist_exprs;
     753                 :         154 :         List       *agg_clause_list = NIL;
     754                 :         154 :         List       *tlist_vars = NIL;
     755                 :         154 :         Relids          aggregate_relids = NULL;
     756                 :         154 :         bool            eager_agg_applicable = true;
     757                 :         154 :         ListCell   *lc;
     758                 :             : 
     759         [ +  - ]:         154 :         Assert(root->agg_clause_list == NIL);
     760         [ +  - ]:         154 :         Assert(root->tlist_vars == NIL);
     761                 :             : 
     762                 :         154 :         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         [ +  + ]:         154 :         if (root->parse->havingQual != NULL)
     773                 :             :         {
     774                 :           3 :                 List       *having_exprs;
     775                 :             : 
     776                 :           3 :                 having_exprs = pull_var_clause((Node *) root->parse->havingQual,
     777                 :             :                                                                            PVC_INCLUDE_AGGREGATES |
     778                 :             :                                                                            PVC_RECURSE_PLACEHOLDERS);
     779         [ -  + ]:           3 :                 if (having_exprs != NIL)
     780                 :             :                 {
     781                 :           3 :                         tlist_exprs = list_concat(tlist_exprs, having_exprs);
     782                 :           3 :                         list_free(having_exprs);
     783                 :           3 :                 }
     784                 :           3 :         }
     785                 :             : 
     786   [ +  -  +  +  :         703 :         foreach(lc, tlist_exprs)
                   +  + ]
     787                 :             :         {
     788                 :         549 :                 Expr       *expr = (Expr *) lfirst(lc);
     789                 :         549 :                 Aggref     *aggref;
     790                 :         549 :                 Relids          agg_eval_at;
     791                 :         549 :                 AggClauseInfo *ac_info;
     792                 :             : 
     793                 :             :                 /* For now we don't try to support GROUPING() expressions */
     794         [ -  + ]:         549 :                 if (IsA(expr, GroupingFunc))
     795                 :             :                 {
     796                 :           0 :                         eager_agg_applicable = false;
     797                 :           0 :                         break;
     798                 :             :                 }
     799                 :             : 
     800                 :             :                 /* Collect plain Vars for future reference */
     801         [ +  + ]:         549 :                 if (IsA(expr, Var))
     802                 :             :                 {
     803                 :         406 :                         tlist_vars = list_append_unique(tlist_vars, expr);
     804                 :         406 :                         continue;
     805                 :             :                 }
     806                 :             : 
     807                 :         143 :                 aggref = castNode(Aggref, expr);
     808                 :             : 
     809         [ +  - ]:         143 :                 Assert(aggref->aggorder == NIL);
     810         [ -  + ]:         143 :                 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   [ -  +  #  # ]:         143 :                 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                 :         143 :                 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                 :         143 :                 aggregate_relids = bms_add_members(aggregate_relids, agg_eval_at);
     831         [ +  + ]:         143 :                 if (bms_is_subset(root->all_baserels, aggregate_relids))
     832                 :             :                 {
     833                 :           7 :                         eager_agg_applicable = false;
     834                 :           7 :                         break;
     835                 :             :                 }
     836                 :             : 
     837                 :             :                 /* OK, create the AggClauseInfo node */
     838                 :         136 :                 ac_info = makeNode(AggClauseInfo);
     839                 :         136 :                 ac_info->aggref = aggref;
     840                 :         136 :                 ac_info->agg_eval_at = agg_eval_at;
     841                 :             : 
     842                 :             :                 /* ... and add it to the list */
     843                 :         136 :                 agg_clause_list = list_append_unique(agg_clause_list, ac_info);
     844      [ +  +  + ]:         549 :         }
     845                 :             : 
     846                 :         154 :         list_free(tlist_exprs);
     847                 :             : 
     848         [ +  + ]:         154 :         if (eager_agg_applicable)
     849                 :             :         {
     850                 :         147 :                 root->agg_clause_list = agg_clause_list;
     851                 :         147 :                 root->tlist_vars = tlist_vars;
     852                 :         147 :         }
     853                 :             :         else
     854                 :             :         {
     855                 :           7 :                 list_free_deep(agg_clause_list);
     856                 :           7 :                 list_free(tlist_vars);
     857                 :             :         }
     858                 :         154 : }
     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                 :         101 : create_grouping_expr_infos(PlannerInfo *root)
     869                 :             : {
     870                 :         101 :         List       *exprs = NIL;
     871                 :         101 :         List       *sortgrouprefs = NIL;
     872                 :         101 :         List       *ecs = NIL;
     873                 :         101 :         ListCell   *lc,
     874                 :             :                            *lc1,
     875                 :             :                            *lc2,
     876                 :             :                            *lc3;
     877                 :             : 
     878         [ +  - ]:         101 :         Assert(root->group_expr_list == NIL);
     879                 :             : 
     880   [ +  -  +  +  :         211 :         foreach(lc, root->processed_groupClause)
             +  +  +  + ]
     881                 :             :         {
     882                 :         110 :                 SortGroupClause *sgc = lfirst_node(SortGroupClause, lc);
     883                 :         110 :                 TargetEntry *tle = get_sortgroupclause_tle(sgc, root->processed_tlist);
     884                 :         110 :                 TypeCacheEntry *tce;
     885                 :         110 :                 Oid                     equalimageproc;
     886                 :             : 
     887         [ +  - ]:         110 :                 Assert(tle->ressortgroupref > 0);
     888                 :             : 
     889                 :             :                 /*
     890                 :             :                  * For now we only support plain Vars as grouping expressions.
     891                 :             :                  */
     892         [ +  + ]:         110 :                 if (!IsA(tle->expr, Var))
     893                 :           8 :                         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                 :         102 :                 tce = lookup_type_cache(exprType((Node *) tle->expr),
     906                 :             :                                                                 TYPECACHE_BTREE_OPFAMILY);
     907   [ +  -  -  + ]:         102 :                 if (!OidIsValid(tce->btree_opf) ||
     908                 :         102 :                         !OidIsValid(tce->btree_opintype))
     909                 :           0 :                         return;
     910                 :             : 
     911                 :         204 :                 equalimageproc = get_opfamily_proc(tce->btree_opf,
     912                 :         102 :                                                                                    tce->btree_opintype,
     913                 :         102 :                                                                                    tce->btree_opintype,
     914                 :             :                                                                                    BTEQUALIMAGE_PROC);
     915   [ +  +  -  + ]:         102 :                 if (!OidIsValid(equalimageproc) ||
     916                 :         202 :                         !DatumGetBool(OidFunctionCall1Coll(equalimageproc,
     917                 :         101 :                                                                                            tce->typcollation,
     918                 :         101 :                                                                                            ObjectIdGetDatum(tce->btree_opintype))))
     919                 :           1 :                         return;
     920                 :             : 
     921                 :         101 :                 exprs = lappend(exprs, tle->expr);
     922                 :         101 :                 sortgrouprefs = lappend_int(sortgrouprefs, tle->ressortgroupref);
     923                 :         101 :                 ecs = lappend(ecs, get_eclass_for_sortgroupclause(root, sgc, tle->expr));
     924         [ +  + ]:         110 :         }
     925                 :             : 
     926                 :             :         /*
     927                 :             :          * Construct a GroupingExprInfo for each expression.
     928                 :             :          */
     929   [ +  -  +  +  :         191 :         forthree(lc1, exprs, lc2, sortgrouprefs, lc3, ecs)
          +  -  +  +  +  
          -  +  +  +  +  
             -  +  +  + ]
     930                 :             :         {
     931                 :          99 :                 Expr       *expr = (Expr *) lfirst(lc1);
     932                 :          99 :                 int                     sortgroupref = lfirst_int(lc2);
     933                 :          99 :                 EquivalenceClass *ec = (EquivalenceClass *) lfirst(lc3);
     934                 :          99 :                 GroupingExprInfo *ge_info;
     935                 :             : 
     936                 :          99 :                 ge_info = makeNode(GroupingExprInfo);
     937                 :          99 :                 ge_info->expr = (Expr *) copyObject(expr);
     938                 :          99 :                 ge_info->sortgroupref = sortgroupref;
     939                 :          99 :                 ge_info->ec = ec;
     940                 :             : 
     941                 :          99 :                 root->group_expr_list = lappend(root->group_expr_list, ge_info);
     942                 :          99 :         }
     943         [ -  + ]:         101 : }
     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                 :         101 : get_eclass_for_sortgroupclause(PlannerInfo *root, SortGroupClause *sgc,
     952                 :             :                                                            Expr *expr)
     953                 :             : {
     954                 :         101 :         Oid                     opfamily,
     955                 :             :                                 opcintype,
     956                 :             :                                 collation;
     957                 :         101 :         CompareType cmptype;
     958                 :         101 :         Oid                     equality_op;
     959                 :         101 :         List       *opfamilies;
     960                 :             : 
     961                 :             :         /* Punt if the group clause is not sortable */
     962         [ +  - ]:         101 :         if (!OidIsValid(sgc->sortop))
     963                 :           0 :                 return NULL;
     964                 :             : 
     965                 :             :         /* Find the operator in pg_amop --- failure shouldn't happen */
     966         [ +  - ]:         101 :         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                 :         101 :         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                 :         202 :         equality_op = get_opfamily_member_for_cmptype(opfamily,
     981                 :         101 :                                                                                                   opcintype,
     982                 :         101 :                                                                                                   opcintype,
     983                 :             :                                                                                                   COMPARE_EQ);
     984         [ +  - ]:         101 :         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                 :         101 :         opfamilies = get_mergejoin_opfamilies(equality_op);
     988         [ +  - ]:         101 :         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                 :         202 :         return get_eclass_for_sort_expr(root, expr, opfamilies, opcintype,
     994                 :         101 :                                                                         collation, sgc->tleSortGroupRef,
     995                 :             :                                                                         NULL, false);
     996                 :         101 : }
     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                 :       33901 : find_lateral_references(PlannerInfo *root)
    1026                 :             : {
    1027                 :       33901 :         Index           rti;
    1028                 :             : 
    1029                 :             :         /* We need do nothing if the query contains no LATERAL RTEs */
    1030         [ +  + ]:       33901 :         if (!root->hasLateralRTEs)
    1031                 :       33538 :                 return;
    1032                 :             : 
    1033                 :             :         /*
    1034                 :             :          * Examine all baserels (the rel array has been set up by now).
    1035                 :             :          */
    1036         [ +  + ]:        2081 :         for (rti = 1; rti < root->simple_rel_array_size; rti++)
    1037                 :             :         {
    1038                 :        1718 :                 RelOptInfo *brel = root->simple_rel_array[rti];
    1039                 :             : 
    1040                 :             :                 /* there may be empty slots corresponding to non-baserel RTEs */
    1041         [ +  + ]:        1718 :                 if (brel == NULL)
    1042                 :         768 :                         continue;
    1043                 :             : 
    1044         [ +  - ]:         950 :                 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         [ -  + ]:         950 :                 if (brel->reloptkind != RELOPT_BASEREL)
    1066                 :           0 :                         continue;
    1067                 :             : 
    1068                 :         950 :                 extract_lateral_references(root, brel, rti);
    1069         [ +  + ]:        1718 :         }
    1070                 :       33901 : }
    1071                 :             : 
    1072                 :             : static void
    1073                 :         950 : extract_lateral_references(PlannerInfo *root, RelOptInfo *brel, Index rtindex)
    1074                 :             : {
    1075                 :         950 :         RangeTblEntry *rte = root->simple_rte_array[rtindex];
    1076                 :         950 :         List       *vars;
    1077                 :         950 :         List       *newvars;
    1078                 :         950 :         Relids          where_needed;
    1079                 :         950 :         ListCell   *lc;
    1080                 :             : 
    1081                 :             :         /* No cross-references are possible if it's not LATERAL */
    1082         [ +  + ]:         950 :         if (!rte->lateral)
    1083                 :         670 :                 return;
    1084                 :             : 
    1085                 :             :         /* Fetch the appropriate variables */
    1086         [ +  + ]:         280 :         if (rte->rtekind == RTE_RELATION)
    1087                 :           6 :                 vars = pull_vars_of_level((Node *) rte->tablesample, 0);
    1088         [ +  + ]:         274 :         else if (rte->rtekind == RTE_SUBQUERY)
    1089                 :         114 :                 vars = pull_vars_of_level((Node *) rte->subquery, 1);
    1090         [ +  + ]:         160 :         else if (rte->rtekind == RTE_FUNCTION)
    1091                 :         109 :                 vars = pull_vars_of_level((Node *) rte->functions, 0);
    1092         [ +  + ]:          51 :         else if (rte->rtekind == RTE_TABLEFUNC)
    1093                 :          39 :                 vars = pull_vars_of_level((Node *) rte->tablefunc, 0);
    1094         [ +  - ]:          12 :         else if (rte->rtekind == RTE_VALUES)
    1095                 :          12 :                 vars = pull_vars_of_level((Node *) rte->values_lists, 0);
    1096                 :             :         else
    1097                 :             :         {
    1098                 :           0 :                 Assert(false);
    1099                 :           0 :                 return;                                 /* keep compiler quiet */
    1100                 :             :         }
    1101                 :             : 
    1102         [ +  + ]:         280 :         if (vars == NIL)
    1103                 :          16 :                 return;                                 /* nothing to do */
    1104                 :             : 
    1105                 :             :         /* Copy each Var (or PlaceHolderVar) and adjust it to match our level */
    1106                 :         264 :         newvars = NIL;
    1107   [ +  -  +  +  :         672 :         foreach(lc, vars)
                   +  + ]
    1108                 :             :         {
    1109                 :         408 :                 Node       *node = (Node *) lfirst(lc);
    1110                 :             : 
    1111                 :         408 :                 node = copyObject(node);
    1112         [ +  + ]:         408 :                 if (IsA(node, Var))
    1113                 :             :                 {
    1114                 :         387 :                         Var                *var = (Var *) node;
    1115                 :             : 
    1116                 :             :                         /* Adjustment is easy since it's just one node */
    1117                 :         387 :                         var->varlevelsup = 0;
    1118                 :         387 :                 }
    1119         [ -  + ]:          21 :                 else if (IsA(node, PlaceHolderVar))
    1120                 :             :                 {
    1121                 :          21 :                         PlaceHolderVar *phv = (PlaceHolderVar *) node;
    1122                 :          21 :                         int                     levelsup = phv->phlevelsup;
    1123                 :             : 
    1124                 :             :                         /* Have to work harder to adjust the contained expression too */
    1125         [ +  + ]:          21 :                         if (levelsup != 0)
    1126                 :          15 :                                 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         [ +  + ]:          21 :                         if (levelsup > 0)
    1134                 :          15 :                                 phv->phexpr = preprocess_phv_expression(root, phv->phexpr);
    1135                 :          21 :                 }
    1136                 :             :                 else
    1137                 :           0 :                         Assert(false);
    1138                 :         408 :                 newvars = lappend(newvars, node);
    1139                 :         408 :         }
    1140                 :             : 
    1141                 :         264 :         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                 :         264 :         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                 :         264 :         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                 :         264 :         brel->lateral_vars = newvars;
    1163         [ -  + ]:         950 : }
    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                 :        1193 : rebuild_lateral_attr_needed(PlannerInfo *root)
    1175                 :             : {
    1176                 :        1193 :         Index           rti;
    1177                 :             : 
    1178                 :             :         /* We need do nothing if the query contains no LATERAL RTEs */
    1179         [ +  + ]:        1193 :         if (!root->hasLateralRTEs)
    1180                 :        1158 :                 return;
    1181                 :             : 
    1182                 :             :         /* Examine the same baserels that find_lateral_references did */
    1183         [ +  + ]:         367 :         for (rti = 1; rti < root->simple_rel_array_size; rti++)
    1184                 :             :         {
    1185                 :         332 :                 RelOptInfo *brel = root->simple_rel_array[rti];
    1186                 :         332 :                 Relids          where_needed;
    1187                 :             : 
    1188         [ +  + ]:         332 :                 if (brel == NULL)
    1189                 :         201 :                         continue;
    1190         [ -  + ]:         131 :                 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         [ +  + ]:         131 :                 if (brel->lateral_vars == NIL)
    1198                 :         109 :                         continue;
    1199                 :             : 
    1200                 :          22 :                 where_needed = bms_make_singleton(rti);
    1201                 :             : 
    1202                 :          22 :                 add_vars_to_attr_needed(root, brel->lateral_vars, where_needed);
    1203         [ +  + ]:         332 :         }
    1204                 :        1193 : }
    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                 :       33901 : create_lateral_join_info(PlannerInfo *root)
    1213                 :             : {
    1214                 :       33901 :         bool            found_laterals = false;
    1215                 :       33901 :         Index           rti;
    1216                 :       33901 :         ListCell   *lc;
    1217                 :             : 
    1218                 :             :         /* We need do nothing if the query contains no LATERAL RTEs */
    1219         [ +  + ]:       33901 :         if (!root->hasLateralRTEs)
    1220                 :       33538 :                 return;
    1221                 :             : 
    1222                 :             :         /* We'll need to have the ph_eval_at values for PlaceHolderVars */
    1223         [ +  - ]:         363 :         Assert(root->placeholdersFrozen);
    1224                 :             : 
    1225                 :             :         /*
    1226                 :             :          * Examine all baserels (the rel array has been set up by now).
    1227                 :             :          */
    1228         [ +  + ]:        2081 :         for (rti = 1; rti < root->simple_rel_array_size; rti++)
    1229                 :             :         {
    1230                 :        1718 :                 RelOptInfo *brel = root->simple_rel_array[rti];
    1231                 :        1718 :                 Relids          lateral_relids;
    1232                 :             : 
    1233                 :             :                 /* there may be empty slots corresponding to non-baserel RTEs */
    1234         [ +  + ]:        1718 :                 if (brel == NULL)
    1235                 :         803 :                         continue;
    1236                 :             : 
    1237         [ -  + ]:         915 :                 Assert(brel->relid == rti); /* sanity check on array */
    1238                 :             : 
    1239                 :             :                 /* ignore RTEs that are "other rels" */
    1240         [ -  + ]:         915 :                 if (brel->reloptkind != RELOPT_BASEREL)
    1241                 :           0 :                         continue;
    1242                 :             : 
    1243                 :         915 :                 lateral_relids = NULL;
    1244                 :             : 
    1245                 :             :                 /* consider each laterally-referenced Var or PHV */
    1246   [ +  +  +  +  :        1313 :                 foreach(lc, brel->lateral_vars)
                   +  + ]
    1247                 :             :                 {
    1248                 :         398 :                         Node       *node = (Node *) lfirst(lc);
    1249                 :             : 
    1250         [ +  + ]:         398 :                         if (IsA(node, Var))
    1251                 :             :                         {
    1252                 :         377 :                                 Var                *var = (Var *) node;
    1253                 :             : 
    1254                 :         377 :                                 found_laterals = true;
    1255                 :         754 :                                 lateral_relids = bms_add_member(lateral_relids,
    1256                 :         377 :                                                                                                 var->varno);
    1257                 :         377 :                         }
    1258         [ -  + ]:          21 :                         else if (IsA(node, PlaceHolderVar))
    1259                 :             :                         {
    1260                 :          21 :                                 PlaceHolderVar *phv = (PlaceHolderVar *) node;
    1261                 :          21 :                                 PlaceHolderInfo *phinfo = find_placeholder_info(root, phv);
    1262                 :             : 
    1263                 :          21 :                                 found_laterals = true;
    1264                 :          42 :                                 lateral_relids = bms_add_members(lateral_relids,
    1265                 :          21 :                                                                                                  phinfo->ph_eval_at);
    1266                 :          21 :                         }
    1267                 :             :                         else
    1268                 :           0 :                                 Assert(false);
    1269                 :         398 :                 }
    1270                 :             : 
    1271                 :             :                 /* We now have all the simple lateral refs from this rel */
    1272                 :         915 :                 brel->direct_lateral_relids = lateral_relids;
    1273                 :         915 :                 brel->lateral_relids = bms_copy(lateral_relids);
    1274         [ +  + ]:        1718 :         }
    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   [ +  +  +  +  :         442 :         foreach(lc, root->placeholder_list)
                   +  + ]
    1290                 :             :         {
    1291                 :          79 :                 PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc);
    1292                 :          79 :                 Relids          eval_at = phinfo->ph_eval_at;
    1293                 :          79 :                 Relids          lateral_refs;
    1294                 :          79 :                 int                     varno;
    1295                 :             : 
    1296         [ +  + ]:          79 :                 if (phinfo->ph_lateral == NULL)
    1297                 :          36 :                         continue;                       /* PHV is uninteresting if no lateral refs */
    1298                 :             : 
    1299                 :          43 :                 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                 :          43 :                 lateral_refs = bms_intersect(phinfo->ph_lateral, root->all_baserels);
    1308         [ +  - ]:          43 :                 Assert(!bms_is_empty(lateral_refs));
    1309                 :             : 
    1310         [ +  + ]:          43 :                 if (bms_get_singleton_member(eval_at, &varno))
    1311                 :             :                 {
    1312                 :             :                         /* Evaluation site is a baserel */
    1313                 :          32 :                         RelOptInfo *brel = find_base_rel(root, varno);
    1314                 :             : 
    1315                 :          32 :                         brel->direct_lateral_relids =
    1316                 :          64 :                                 bms_add_members(brel->direct_lateral_relids,
    1317                 :          32 :                                                                 lateral_refs);
    1318                 :          32 :                         brel->lateral_relids =
    1319                 :          64 :                                 bms_add_members(brel->lateral_relids,
    1320                 :          32 :                                                                 lateral_refs);
    1321                 :          32 :                 }
    1322                 :             :                 else
    1323                 :             :                 {
    1324                 :             :                         /* Evaluation site is a join */
    1325                 :          11 :                         varno = -1;
    1326         [ +  + ]:          33 :                         while ((varno = bms_next_member(eval_at, varno)) >= 0)
    1327                 :             :                         {
    1328                 :          22 :                                 RelOptInfo *brel = find_base_rel_ignore_join(root, varno);
    1329                 :             : 
    1330         [ +  - ]:          22 :                                 if (brel == NULL)
    1331                 :           0 :                                         continue;       /* ignore outer joins in eval_at */
    1332                 :          44 :                                 brel->lateral_relids = bms_add_members(brel->lateral_relids,
    1333                 :          22 :                                                                                                            lateral_refs);
    1334         [ -  + ]:          22 :                         }
    1335                 :             :                 }
    1336         [ +  + ]:          79 :         }
    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         [ +  + ]:         363 :         if (!found_laterals)
    1343                 :             :         {
    1344                 :          79 :                 root->hasLateralRTEs = false;
    1345                 :          79 :                 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         [ +  + ]:        1586 :         for (rti = 1; rti < root->simple_rel_array_size; rti++)
    1360                 :             :         {
    1361                 :        1302 :                 RelOptInfo *brel = root->simple_rel_array[rti];
    1362                 :        1302 :                 Relids          outer_lateral_relids;
    1363                 :        1302 :                 Index           rti2;
    1364                 :             : 
    1365   [ +  +  -  + ]:        1302 :                 if (brel == NULL || brel->reloptkind != RELOPT_BASEREL)
    1366                 :         564 :                         continue;
    1367                 :             : 
    1368                 :             :                 /* need not consider baserel further if it has no lateral refs */
    1369                 :         738 :                 outer_lateral_relids = brel->lateral_relids;
    1370         [ +  + ]:         738 :                 if (outer_lateral_relids == NULL)
    1371                 :         430 :                         continue;
    1372                 :             : 
    1373                 :             :                 /* else scan all baserels */
    1374         [ +  + ]:        1768 :                 for (rti2 = 1; rti2 < root->simple_rel_array_size; rti2++)
    1375                 :             :                 {
    1376                 :        1460 :                         RelOptInfo *brel2 = root->simple_rel_array[rti2];
    1377                 :             : 
    1378   [ +  +  -  + ]:        1460 :                         if (brel2 == NULL || brel2->reloptkind != RELOPT_BASEREL)
    1379                 :         633 :                                 continue;
    1380                 :             : 
    1381                 :             :                         /* if brel2 has lateral ref to brel, propagate brel's refs */
    1382         [ +  + ]:         827 :                         if (bms_is_member(rti, brel2->lateral_relids))
    1383                 :          20 :                                 brel2->lateral_relids = bms_add_members(brel2->lateral_relids,
    1384                 :          10 :                                                                                                                 outer_lateral_relids);
    1385         [ +  + ]:        1460 :                 }
    1386         [ +  + ]:        1302 :         }
    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         [ +  + ]:        1586 :         for (rti = 1; rti < root->simple_rel_array_size; rti++)
    1394                 :             :         {
    1395                 :        1302 :                 RelOptInfo *brel = root->simple_rel_array[rti];
    1396                 :        1302 :                 Relids          lateral_relids;
    1397                 :        1302 :                 int                     rti2;
    1398                 :             : 
    1399   [ +  +  -  + ]:        1302 :                 if (brel == NULL || brel->reloptkind != RELOPT_BASEREL)
    1400                 :         564 :                         continue;
    1401                 :             : 
    1402                 :             :                 /* Nothing to do at rels with no lateral refs */
    1403                 :         738 :                 lateral_relids = brel->lateral_relids;
    1404         [ +  + ]:         738 :                 if (bms_is_empty(lateral_relids))
    1405                 :         430 :                         continue;
    1406                 :             : 
    1407                 :             :                 /* No rel should have a lateral dependency on itself */
    1408         [ +  - ]:         308 :                 Assert(!bms_is_member(rti, lateral_relids));
    1409                 :             : 
    1410                 :             :                 /* Mark this rel's referencees */
    1411                 :         308 :                 rti2 = -1;
    1412         [ +  + ]:         661 :                 while ((rti2 = bms_next_member(lateral_relids, rti2)) >= 0)
    1413                 :             :                 {
    1414                 :         353 :                         RelOptInfo *brel2 = root->simple_rel_array[rti2];
    1415                 :             : 
    1416         [ +  + ]:         353 :                         if (brel2 == NULL)
    1417                 :           2 :                                 continue;               /* must be an OJ */
    1418                 :             : 
    1419         [ +  - ]:         351 :                         Assert(brel2->reloptkind == RELOPT_BASEREL);
    1420                 :         351 :                         brel2->lateral_referencers =
    1421                 :         351 :                                 bms_add_member(brel2->lateral_referencers, rti);
    1422         [ +  + ]:         353 :                 }
    1423         [ +  + ]:        1302 :         }
    1424                 :       33901 : }
    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                 :       33901 : deconstruct_jointree(PlannerInfo *root)
    1452                 :             : {
    1453                 :       33901 :         List       *result;
    1454                 :       33901 :         JoinDomain *top_jdomain;
    1455                 :       33901 :         List       *item_list = NIL;
    1456                 :       33901 :         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                 :       33901 :         root->placeholdersFrozen = true;
    1464                 :             : 
    1465                 :             :         /* Fetch the already-created top-level join domain for the query */
    1466                 :       33901 :         top_jdomain = linitial_node(JoinDomain, root->join_domains);
    1467                 :       33901 :         top_jdomain->jd_relids = NULL;       /* filled during deconstruct_recurse */
    1468                 :             : 
    1469                 :             :         /* Start recursion at top of jointree */
    1470         [ +  - ]:       33901 :         Assert(root->parse->jointree != NULL &&
    1471                 :             :                    IsA(root->parse->jointree, FromExpr));
    1472                 :             : 
    1473                 :             :         /* These are filled as we scan the jointree */
    1474                 :       33901 :         root->all_baserels = NULL;
    1475                 :       33901 :         root->outer_join_rels = NULL;
    1476                 :             : 
    1477                 :             :         /* Perform the initial scan of the jointree */
    1478                 :       67802 :         result = deconstruct_recurse(root, (Node *) root->parse->jointree,
    1479                 :       33901 :                                                                  top_jdomain, NULL,
    1480                 :             :                                                                  &item_list);
    1481                 :             : 
    1482                 :             :         /* Now we can form the value of all_query_rels, too */
    1483                 :       33901 :         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         [ +  - ]:       33901 :         Assert(bms_equal(root->all_query_rels, top_jdomain->jd_relids));
    1487                 :             : 
    1488                 :             :         /* Now scan all the jointree nodes again, and distribute quals */
    1489   [ +  -  +  +  :      126301 :         foreach(lc, item_list)
                   +  + ]
    1490                 :             :         {
    1491                 :       92400 :                 JoinTreeItem *jtitem = (JoinTreeItem *) lfirst(lc);
    1492                 :             : 
    1493                 :       92400 :                 deconstruct_distribute(root, jtitem);
    1494                 :       92400 :         }
    1495                 :             : 
    1496                 :             :         /*
    1497                 :             :          * If there were any special joins then we may have some postponed LEFT
    1498                 :             :          * JOIN clauses to deal with.
    1499                 :             :          */
    1500         [ +  + ]:       33901 :         if (root->join_info_list)
    1501                 :             :         {
    1502   [ +  -  +  +  :       25656 :                 foreach(lc, item_list)
                   +  + ]
    1503                 :             :                 {
    1504                 :       21503 :                         JoinTreeItem *jtitem = (JoinTreeItem *) lfirst(lc);
    1505                 :             : 
    1506         [ +  + ]:       21503 :                         if (jtitem->oj_joinclauses != NIL)
    1507                 :        3887 :                                 deconstruct_distribute_oj_quals(root, item_list, jtitem);
    1508                 :       21503 :                 }
    1509                 :        4153 :         }
    1510                 :             : 
    1511                 :             :         /* Don't need the JoinTreeItems any more */
    1512                 :       33901 :         list_free_deep(item_list);
    1513                 :             : 
    1514                 :       67802 :         return result;
    1515                 :       33901 : }
    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                 :       92400 : deconstruct_recurse(PlannerInfo *root, Node *jtnode,
    1534                 :             :                                         JoinDomain *parent_domain,
    1535                 :             :                                         JoinTreeItem *parent_jtitem,
    1536                 :             :                                         List **item_list)
    1537                 :             : {
    1538                 :       92400 :         List       *joinlist;
    1539                 :       92400 :         JoinTreeItem *jtitem;
    1540                 :             : 
    1541         [ +  - ]:       92400 :         Assert(jtnode != NULL);
    1542                 :             : 
    1543                 :             :         /* Make the new JoinTreeItem, but don't add it to item_list yet */
    1544                 :       92400 :         jtitem = palloc0_object(JoinTreeItem);
    1545                 :       92400 :         jtitem->jtnode = jtnode;
    1546                 :       92400 :         jtitem->jti_parent = parent_jtitem;
    1547                 :             : 
    1548         [ +  + ]:       92400 :         if (IsA(jtnode, RangeTblRef))
    1549                 :             :         {
    1550                 :       47627 :                 int                     varno = ((RangeTblRef *) jtnode)->rtindex;
    1551                 :             : 
    1552                 :             :                 /* Fill all_baserels as we encounter baserel jointree nodes */
    1553                 :       47627 :                 root->all_baserels = bms_add_member(root->all_baserels, varno);
    1554                 :             :                 /* This node belongs to parent_domain */
    1555                 :       47627 :                 jtitem->jdomain = parent_domain;
    1556                 :       95254 :                 parent_domain->jd_relids = bms_add_member(parent_domain->jd_relids,
    1557                 :       47627 :                                                                                                   varno);
    1558                 :             :                 /* qualscope is just the one RTE */
    1559                 :       47627 :                 jtitem->qualscope = bms_make_singleton(varno);
    1560                 :             :                 /* A single baserel does not create an inner join */
    1561                 :       47627 :                 jtitem->inner_join_rels = NULL;
    1562                 :       47627 :                 joinlist = list_make1(jtnode);
    1563                 :       47627 :         }
    1564         [ +  + ]:       44773 :         else if (IsA(jtnode, FromExpr))
    1565                 :             :         {
    1566                 :       35411 :                 FromExpr   *f = (FromExpr *) jtnode;
    1567                 :       35411 :                 int                     remaining;
    1568                 :       35411 :                 ListCell   *l;
    1569                 :             : 
    1570                 :             :                 /* This node belongs to parent_domain, as do its children */
    1571                 :       35411 :                 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                 :       35411 :                 jtitem->qualscope = NULL;
    1581                 :       35411 :                 jtitem->inner_join_rels = NULL;
    1582                 :       35411 :                 joinlist = NIL;
    1583                 :       35411 :                 remaining = list_length(f->fromlist);
    1584   [ +  -  +  +  :       75186 :                 foreach(l, f->fromlist)
                   +  + ]
    1585                 :             :                 {
    1586                 :       39775 :                         JoinTreeItem *sub_item;
    1587                 :       39775 :                         List       *sub_joinlist;
    1588                 :       39775 :                         int                     sub_members;
    1589                 :             : 
    1590                 :       79550 :                         sub_joinlist = deconstruct_recurse(root, lfirst(l),
    1591                 :       39775 :                                                                                            parent_domain,
    1592                 :       39775 :                                                                                            jtitem,
    1593                 :       39775 :                                                                                            item_list);
    1594                 :       39775 :                         sub_item = (JoinTreeItem *) llast(*item_list);
    1595                 :       79550 :                         jtitem->qualscope = bms_add_members(jtitem->qualscope,
    1596                 :       39775 :                                                                                                 sub_item->qualscope);
    1597                 :       39775 :                         jtitem->inner_join_rels = sub_item->inner_join_rels;
    1598                 :       39775 :                         sub_members = list_length(sub_joinlist);
    1599                 :       39775 :                         remaining--;
    1600   [ +  +  +  + ]:       39775 :                         if (sub_members <= 1 ||
    1601                 :        6499 :                                 list_length(joinlist) + sub_members + remaining <= from_collapse_limit)
    1602                 :       39773 :                                 joinlist = list_concat(joinlist, sub_joinlist);
    1603                 :             :                         else
    1604                 :           2 :                                 joinlist = lappend(joinlist, sub_joinlist);
    1605                 :       39775 :                 }
    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         [ +  + ]:       35411 :                 if (list_length(f->fromlist) > 1)
    1615                 :        3821 :                         jtitem->inner_join_rels = jtitem->qualscope;
    1616                 :       35411 :         }
    1617         [ +  - ]:        9362 :         else if (IsA(jtnode, JoinExpr))
    1618                 :             :         {
    1619                 :        9362 :                 JoinExpr   *j = (JoinExpr *) jtnode;
    1620                 :        9362 :                 JoinDomain *child_domain,
    1621                 :             :                                    *fj_domain;
    1622                 :        9362 :                 JoinTreeItem *left_item,
    1623                 :             :                                    *right_item;
    1624                 :        9362 :                 List       *leftjoinlist,
    1625                 :             :                                    *rightjoinlist;
    1626                 :             : 
    1627   [ +  +  +  +  :        9362 :                 switch (j->jointype)
                      - ]
    1628                 :             :                 {
    1629                 :             :                         case JOIN_INNER:
    1630                 :             :                                 /* This node belongs to parent_domain, as do its children */
    1631                 :        4057 :                                 jtitem->jdomain = parent_domain;
    1632                 :             :                                 /* Recurse */
    1633                 :        8114 :                                 leftjoinlist = deconstruct_recurse(root, j->larg,
    1634                 :        4057 :                                                                                                    parent_domain,
    1635                 :        4057 :                                                                                                    jtitem,
    1636                 :        4057 :                                                                                                    item_list);
    1637                 :        4057 :                                 left_item = (JoinTreeItem *) llast(*item_list);
    1638                 :        8114 :                                 rightjoinlist = deconstruct_recurse(root, j->rarg,
    1639                 :        4057 :                                                                                                         parent_domain,
    1640                 :        4057 :                                                                                                         jtitem,
    1641                 :        4057 :                                                                                                         item_list);
    1642                 :        4057 :                                 right_item = (JoinTreeItem *) llast(*item_list);
    1643                 :             :                                 /* Compute qualscope etc */
    1644                 :        8114 :                                 jtitem->qualscope = bms_union(left_item->qualscope,
    1645                 :        4057 :                                                                                           right_item->qualscope);
    1646                 :        4057 :                                 jtitem->inner_join_rels = jtitem->qualscope;
    1647                 :        4057 :                                 jtitem->left_rels = left_item->qualscope;
    1648                 :        4057 :                                 jtitem->right_rels = right_item->qualscope;
    1649                 :             :                                 /* Inner join adds no restrictions for quals */
    1650                 :        4057 :                                 jtitem->nonnullable_rels = NULL;
    1651                 :        4057 :                                 break;
    1652                 :             :                         case JOIN_LEFT:
    1653                 :             :                         case JOIN_ANTI:
    1654                 :             :                                 /* Make new join domain for my quals and the RHS */
    1655                 :        4464 :                                 child_domain = makeNode(JoinDomain);
    1656                 :        4464 :                                 child_domain->jd_relids = NULL; /* filled by recursion */
    1657                 :        4464 :                                 root->join_domains = lappend(root->join_domains, child_domain);
    1658                 :        4464 :                                 jtitem->jdomain = child_domain;
    1659                 :             :                                 /* Recurse */
    1660                 :        8928 :                                 leftjoinlist = deconstruct_recurse(root, j->larg,
    1661                 :        4464 :                                                                                                    parent_domain,
    1662                 :        4464 :                                                                                                    jtitem,
    1663                 :        4464 :                                                                                                    item_list);
    1664                 :        4464 :                                 left_item = (JoinTreeItem *) llast(*item_list);
    1665                 :        8928 :                                 rightjoinlist = deconstruct_recurse(root, j->rarg,
    1666                 :        4464 :                                                                                                         child_domain,
    1667                 :        4464 :                                                                                                         jtitem,
    1668                 :        4464 :                                                                                                         item_list);
    1669                 :        4464 :                                 right_item = (JoinTreeItem *) llast(*item_list);
    1670                 :             :                                 /* Compute join domain contents, qualscope etc */
    1671                 :        4464 :                                 parent_domain->jd_relids =
    1672                 :        8928 :                                         bms_add_members(parent_domain->jd_relids,
    1673                 :        4464 :                                                                         child_domain->jd_relids);
    1674                 :        8928 :                                 jtitem->qualscope = bms_union(left_item->qualscope,
    1675                 :        4464 :                                                                                           right_item->qualscope);
    1676                 :             :                                 /* caution: ANTI join derived from SEMI will lack rtindex */
    1677         [ +  + ]:        4464 :                                 if (j->rtindex != 0)
    1678                 :             :                                 {
    1679                 :        4175 :                                         parent_domain->jd_relids =
    1680                 :        8350 :                                                 bms_add_member(parent_domain->jd_relids,
    1681                 :        4175 :                                                                            j->rtindex);
    1682                 :        8350 :                                         jtitem->qualscope = bms_add_member(jtitem->qualscope,
    1683                 :        4175 :                                                                                                            j->rtindex);
    1684                 :        8350 :                                         root->outer_join_rels = bms_add_member(root->outer_join_rels,
    1685                 :        4175 :                                                                                                                    j->rtindex);
    1686                 :        8350 :                                         mark_rels_nulled_by_join(root, j->rtindex,
    1687                 :        4175 :                                                                                          right_item->qualscope);
    1688                 :        4175 :                                 }
    1689                 :        8928 :                                 jtitem->inner_join_rels = bms_union(left_item->inner_join_rels,
    1690                 :        4464 :                                                                                                         right_item->inner_join_rels);
    1691                 :        4464 :                                 jtitem->left_rels = left_item->qualscope;
    1692                 :        4464 :                                 jtitem->right_rels = right_item->qualscope;
    1693                 :        4464 :                                 jtitem->nonnullable_rels = left_item->qualscope;
    1694                 :        4464 :                                 break;
    1695                 :             :                         case JOIN_SEMI:
    1696                 :             :                                 /* This node belongs to parent_domain, as do its children */
    1697                 :         700 :                                 jtitem->jdomain = parent_domain;
    1698                 :             :                                 /* Recurse */
    1699                 :        1400 :                                 leftjoinlist = deconstruct_recurse(root, j->larg,
    1700                 :         700 :                                                                                                    parent_domain,
    1701                 :         700 :                                                                                                    jtitem,
    1702                 :         700 :                                                                                                    item_list);
    1703                 :         700 :                                 left_item = (JoinTreeItem *) llast(*item_list);
    1704                 :        1400 :                                 rightjoinlist = deconstruct_recurse(root, j->rarg,
    1705                 :         700 :                                                                                                         parent_domain,
    1706                 :         700 :                                                                                                         jtitem,
    1707                 :         700 :                                                                                                         item_list);
    1708                 :         700 :                                 right_item = (JoinTreeItem *) llast(*item_list);
    1709                 :             :                                 /* Compute qualscope etc */
    1710                 :        1400 :                                 jtitem->qualscope = bms_union(left_item->qualscope,
    1711                 :         700 :                                                                                           right_item->qualscope);
    1712                 :             :                                 /* SEMI join never has rtindex, so don't add to anything */
    1713         [ +  - ]:         700 :                                 Assert(j->rtindex == 0);
    1714                 :        1400 :                                 jtitem->inner_join_rels = bms_union(left_item->inner_join_rels,
    1715                 :         700 :                                                                                                         right_item->inner_join_rels);
    1716                 :         700 :                                 jtitem->left_rels = left_item->qualscope;
    1717                 :         700 :                                 jtitem->right_rels = right_item->qualscope;
    1718                 :             :                                 /* Semi join adds no restrictions for quals */
    1719                 :         700 :                                 jtitem->nonnullable_rels = NULL;
    1720                 :         700 :                                 break;
    1721                 :             :                         case JOIN_FULL:
    1722                 :             :                                 /* The FULL JOIN's quals need their very own domain */
    1723                 :         141 :                                 fj_domain = makeNode(JoinDomain);
    1724                 :         141 :                                 root->join_domains = lappend(root->join_domains, fj_domain);
    1725                 :         141 :                                 jtitem->jdomain = fj_domain;
    1726                 :             :                                 /* Recurse, giving each side its own join domain */
    1727                 :         141 :                                 child_domain = makeNode(JoinDomain);
    1728                 :         141 :                                 child_domain->jd_relids = NULL; /* filled by recursion */
    1729                 :         141 :                                 root->join_domains = lappend(root->join_domains, child_domain);
    1730                 :         282 :                                 leftjoinlist = deconstruct_recurse(root, j->larg,
    1731                 :         141 :                                                                                                    child_domain,
    1732                 :         141 :                                                                                                    jtitem,
    1733                 :         141 :                                                                                                    item_list);
    1734                 :         141 :                                 left_item = (JoinTreeItem *) llast(*item_list);
    1735                 :         141 :                                 fj_domain->jd_relids = bms_copy(child_domain->jd_relids);
    1736                 :         141 :                                 child_domain = makeNode(JoinDomain);
    1737                 :         141 :                                 child_domain->jd_relids = NULL; /* filled by recursion */
    1738                 :         141 :                                 root->join_domains = lappend(root->join_domains, child_domain);
    1739                 :         282 :                                 rightjoinlist = deconstruct_recurse(root, j->rarg,
    1740                 :         141 :                                                                                                         child_domain,
    1741                 :         141 :                                                                                                         jtitem,
    1742                 :         141 :                                                                                                         item_list);
    1743                 :         141 :                                 right_item = (JoinTreeItem *) llast(*item_list);
    1744                 :             :                                 /* Compute qualscope etc */
    1745                 :         282 :                                 fj_domain->jd_relids = bms_add_members(fj_domain->jd_relids,
    1746                 :         141 :                                                                                                            child_domain->jd_relids);
    1747                 :         282 :                                 parent_domain->jd_relids = bms_add_members(parent_domain->jd_relids,
    1748                 :         141 :                                                                                                                    fj_domain->jd_relids);
    1749                 :         282 :                                 jtitem->qualscope = bms_union(left_item->qualscope,
    1750                 :         141 :                                                                                           right_item->qualscope);
    1751         [ +  - ]:         141 :                                 Assert(j->rtindex != 0);
    1752                 :         282 :                                 parent_domain->jd_relids = bms_add_member(parent_domain->jd_relids,
    1753                 :         141 :                                                                                                                   j->rtindex);
    1754                 :         282 :                                 jtitem->qualscope = bms_add_member(jtitem->qualscope,
    1755                 :         141 :                                                                                                    j->rtindex);
    1756                 :         282 :                                 root->outer_join_rels = bms_add_member(root->outer_join_rels,
    1757                 :         141 :                                                                                                            j->rtindex);
    1758                 :         282 :                                 mark_rels_nulled_by_join(root, j->rtindex,
    1759                 :         141 :                                                                                  left_item->qualscope);
    1760                 :         282 :                                 mark_rels_nulled_by_join(root, j->rtindex,
    1761                 :         141 :                                                                                  right_item->qualscope);
    1762                 :         282 :                                 jtitem->inner_join_rels = bms_union(left_item->inner_join_rels,
    1763                 :         141 :                                                                                                         right_item->inner_join_rels);
    1764                 :         141 :                                 jtitem->left_rels = left_item->qualscope;
    1765                 :         141 :                                 jtitem->right_rels = right_item->qualscope;
    1766                 :             :                                 /* each side is both outer and inner */
    1767                 :         141 :                                 jtitem->nonnullable_rels = jtitem->qualscope;
    1768                 :         141 :                                 break;
    1769                 :             :                         default:
    1770                 :             :                                 /* JOIN_RIGHT was eliminated during reduce_outer_joins() */
    1771   [ #  #  #  # ]:           0 :                                 elog(ERROR, "unrecognized join type: %d",
    1772                 :             :                                          (int) j->jointype);
    1773                 :           0 :                                 leftjoinlist = rightjoinlist = NIL; /* keep compiler quiet */
    1774                 :           0 :                                 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         [ +  + ]:        9362 :                 if (j->jointype == JOIN_FULL)
    1782                 :             :                 {
    1783                 :             :                         /* force the join order exactly at this node */
    1784                 :         141 :                         joinlist = list_make1(list_make2(leftjoinlist, rightjoinlist));
    1785                 :         141 :                 }
    1786   [ +  +  +  + ]:       18442 :                 else if (list_length(leftjoinlist) + list_length(rightjoinlist) <=
    1787                 :        9221 :                                  join_collapse_limit)
    1788                 :             :                 {
    1789                 :             :                         /* OK to combine subproblems */
    1790                 :        9193 :                         joinlist = list_concat(leftjoinlist, rightjoinlist);
    1791                 :        9193 :                 }
    1792                 :             :                 else
    1793                 :             :                 {
    1794                 :             :                         /* can't combine, but needn't force join order above here */
    1795                 :          28 :                         Node       *leftpart,
    1796                 :             :                                            *rightpart;
    1797                 :             : 
    1798                 :             :                         /* avoid creating useless 1-element sublists */
    1799         [ +  + ]:          28 :                         if (list_length(leftjoinlist) == 1)
    1800                 :           5 :                                 leftpart = (Node *) linitial(leftjoinlist);
    1801                 :             :                         else
    1802                 :          23 :                                 leftpart = (Node *) leftjoinlist;
    1803         [ +  + ]:          28 :                         if (list_length(rightjoinlist) == 1)
    1804                 :           4 :                                 rightpart = (Node *) linitial(rightjoinlist);
    1805                 :             :                         else
    1806                 :          24 :                                 rightpart = (Node *) rightjoinlist;
    1807                 :          28 :                         joinlist = list_make2(leftpart, rightpart);
    1808                 :          28 :                 }
    1809                 :        9362 :         }
    1810                 :             :         else
    1811                 :             :         {
    1812   [ #  #  #  # ]:           0 :                 elog(ERROR, "unrecognized node type: %d",
    1813                 :             :                          (int) nodeTag(jtnode));
    1814                 :           0 :                 joinlist = NIL;                 /* keep compiler quiet */
    1815                 :             :         }
    1816                 :             : 
    1817                 :             :         /* Finally, we can add the new JoinTreeItem to item_list */
    1818                 :       92400 :         *item_list = lappend(*item_list, jtitem);
    1819                 :             : 
    1820                 :      184800 :         return joinlist;
    1821                 :       92400 : }
    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                 :       92400 : deconstruct_distribute(PlannerInfo *root, JoinTreeItem *jtitem)
    1832                 :             : {
    1833                 :       92400 :         Node       *jtnode = jtitem->jtnode;
    1834                 :             : 
    1835         [ +  + ]:       92400 :         if (IsA(jtnode, RangeTblRef))
    1836                 :             :         {
    1837                 :       47627 :                 int                     varno = ((RangeTblRef *) jtnode)->rtindex;
    1838                 :             : 
    1839                 :             :                 /* Deal with any securityQuals attached to the RTE */
    1840         [ +  + ]:       47627 :                 if (root->qual_security_level > 0)
    1841                 :         988 :                         process_security_barrier_quals(root,
    1842                 :         494 :                                                                                    varno,
    1843                 :         494 :                                                                                    jtitem);
    1844                 :       47627 :         }
    1845         [ +  + ]:       44773 :         else if (IsA(jtnode, FromExpr))
    1846                 :             :         {
    1847                 :       35411 :                 FromExpr   *f = (FromExpr *) jtnode;
    1848                 :             : 
    1849                 :             :                 /*
    1850                 :             :                  * Process any lateral-referencing quals that were postponed to this
    1851                 :             :                  * level by children.
    1852                 :             :                  */
    1853                 :       70822 :                 distribute_quals_to_rels(root, jtitem->lateral_clauses,
    1854                 :       35411 :                                                                  jtitem,
    1855                 :             :                                                                  NULL,
    1856                 :       35411 :                                                                  root->qual_security_level,
    1857                 :       35411 :                                                                  jtitem->qualscope,
    1858                 :             :                                                                  NULL, NULL, NULL,
    1859                 :             :                                                                  true, false, false,
    1860                 :             :                                                                  NULL);
    1861                 :             : 
    1862                 :             :                 /*
    1863                 :             :                  * Now process the top-level quals.
    1864                 :             :                  */
    1865                 :       70822 :                 distribute_quals_to_rels(root, (List *) f->quals,
    1866                 :       35411 :                                                                  jtitem,
    1867                 :             :                                                                  NULL,
    1868                 :       35411 :                                                                  root->qual_security_level,
    1869                 :       35411 :                                                                  jtitem->qualscope,
    1870                 :             :                                                                  NULL, NULL, NULL,
    1871                 :             :                                                                  true, false, false,
    1872                 :             :                                                                  NULL);
    1873                 :       35411 :         }
    1874         [ +  - ]:        9362 :         else if (IsA(jtnode, JoinExpr))
    1875                 :             :         {
    1876                 :        9362 :                 JoinExpr   *j = (JoinExpr *) jtnode;
    1877                 :        9362 :                 Relids          ojscope;
    1878                 :        9362 :                 List       *my_quals;
    1879                 :        9362 :                 SpecialJoinInfo *sjinfo;
    1880                 :        9362 :                 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                 :       18724 :                 my_quals = list_concat(jtitem->lateral_clauses,
    1889                 :        9362 :                                                            (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         [ +  + ]:        9362 :                 if (j->jointype != JOIN_INNER)
    1899                 :             :                 {
    1900                 :       10610 :                         sjinfo = make_outerjoininfo(root,
    1901                 :        5305 :                                                                                 jtitem->left_rels,
    1902                 :        5305 :                                                                                 jtitem->right_rels,
    1903                 :        5305 :                                                                                 jtitem->inner_join_rels,
    1904                 :        5305 :                                                                                 j->jointype,
    1905                 :        5305 :                                                                                 j->rtindex,
    1906                 :        5305 :                                                                                 my_quals);
    1907                 :        5305 :                         jtitem->sjinfo = sjinfo;
    1908         [ +  + ]:        5305 :                         if (j->jointype == JOIN_SEMI)
    1909                 :         700 :                                 ojscope = NULL;
    1910                 :             :                         else
    1911                 :        9210 :                                 ojscope = bms_union(sjinfo->min_lefthand,
    1912                 :        4605 :                                                                         sjinfo->min_righthand);
    1913                 :        5305 :                 }
    1914                 :             :                 else
    1915                 :             :                 {
    1916                 :        4057 :                         sjinfo = NULL;
    1917                 :        4057 :                         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   [ +  +  +  + ]:        9362 :                 if (j->jointype == JOIN_LEFT && sjinfo->lhs_strict)
    1928                 :             :                 {
    1929                 :        3887 :                         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                 :        3887 :                         ojscope = bms_add_members(ojscope, sjinfo->commute_below_l);
    1941                 :        3887 :                         ojscope = bms_add_members(ojscope, sjinfo->commute_below_r);
    1942                 :        3887 :                 }
    1943                 :             :                 else
    1944                 :        5475 :                         postponed_oj_qual_list = NULL;
    1945                 :             : 
    1946                 :             :                 /* Process the JOIN's qual clauses */
    1947                 :       18724 :                 distribute_quals_to_rels(root, my_quals,
    1948                 :        9362 :                                                                  jtitem,
    1949                 :        9362 :                                                                  sjinfo,
    1950                 :        9362 :                                                                  root->qual_security_level,
    1951                 :        9362 :                                                                  jtitem->qualscope,
    1952                 :        9362 :                                                                  ojscope, jtitem->nonnullable_rels,
    1953                 :             :                                                                  NULL,  /* incompatible_relids */
    1954                 :             :                                                                  true,  /* allow_equivalence */
    1955                 :             :                                                                  false, false,  /* not clones */
    1956                 :        9362 :                                                                  postponed_oj_qual_list);
    1957                 :             : 
    1958                 :             :                 /* And add the SpecialJoinInfo to join_info_list */
    1959         [ +  + ]:        9362 :                 if (sjinfo)
    1960                 :        5305 :                         root->join_info_list = lappend(root->join_info_list, sjinfo);
    1961                 :        9362 :         }
    1962                 :             :         else
    1963                 :             :         {
    1964   [ #  #  #  # ]:           0 :                 elog(ERROR, "unrecognized node type: %d",
    1965                 :             :                          (int) nodeTag(jtnode));
    1966                 :             :         }
    1967                 :       92400 : }
    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                 :         494 : process_security_barrier_quals(PlannerInfo *root,
    1984                 :             :                                                            int rti, JoinTreeItem *jtitem)
    1985                 :             : {
    1986                 :         494 :         RangeTblEntry *rte = root->simple_rte_array[rti];
    1987                 :         494 :         Index           security_level = 0;
    1988                 :         494 :         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   [ +  +  +  +  :        1009 :         foreach(lc, rte->securityQuals)
                   +  + ]
    1997                 :             :         {
    1998                 :         515 :                 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                 :        1030 :                 distribute_quals_to_rels(root, qualset,
    2007                 :         515 :                                                                  jtitem,
    2008                 :             :                                                                  NULL,
    2009                 :         515 :                                                                  security_level,
    2010                 :         515 :                                                                  jtitem->qualscope,
    2011                 :         515 :                                                                  jtitem->qualscope,
    2012                 :             :                                                                  NULL,
    2013                 :             :                                                                  NULL,
    2014                 :             :                                                                  true,
    2015                 :             :                                                                  false, false,  /* not clones */
    2016                 :             :                                                                  NULL);
    2017                 :         515 :                 security_level++;
    2018                 :         515 :         }
    2019                 :             : 
    2020                 :             :         /* Assert that qual_security_level is higher than anything we just used */
    2021         [ +  - ]:         494 :         Assert(security_level <= root->qual_security_level);
    2022                 :         494 : }
    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                 :        4457 : mark_rels_nulled_by_join(PlannerInfo *root, Index ojrelid,
    2034                 :             :                                                  Relids lower_rels)
    2035                 :             : {
    2036                 :        4457 :         int                     relid = -1;
    2037                 :             : 
    2038         [ +  + ]:        9323 :         while ((relid = bms_next_member(lower_rels, relid)) > 0)
    2039                 :             :         {
    2040                 :        4866 :                 RelOptInfo *rel = root->simple_rel_array[relid];
    2041                 :             : 
    2042                 :             :                 /* ignore the RTE_GROUP RTE */
    2043         [ -  + ]:        4866 :                 if (relid == root->group_rtindex)
    2044                 :           0 :                         continue;
    2045                 :             : 
    2046         [ +  + ]:        4866 :                 if (rel == NULL)                /* must be an outer join */
    2047                 :             :                 {
    2048         [ -  + ]:         118 :                         Assert(bms_is_member(relid, root->outer_join_rels));
    2049                 :         118 :                         continue;
    2050                 :             :                 }
    2051                 :        4748 :                 rel->nulling_relids = bms_add_member(rel->nulling_relids, ojrelid);
    2052      [ -  +  + ]:        4866 :         }
    2053                 :        4457 : }
    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                 :        5305 : 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                 :        5305 :         SpecialJoinInfo *sjinfo = makeNode(SpecialJoinInfo);
    2082                 :        5305 :         Relids          clause_relids;
    2083                 :        5305 :         Relids          strict_relids;
    2084                 :        5305 :         Relids          min_lefthand;
    2085                 :        5305 :         Relids          min_righthand;
    2086                 :        5305 :         Relids          commute_below_l;
    2087                 :        5305 :         Relids          commute_below_r;
    2088                 :        5305 :         ListCell   *l;
    2089                 :             : 
    2090                 :             :         /*
    2091                 :             :          * We should not see RIGHT JOIN here because left/right were switched
    2092                 :             :          * earlier
    2093                 :             :          */
    2094         [ +  - ]:        5305 :         Assert(jointype != JOIN_INNER);
    2095         [ +  - ]:        5305 :         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   [ -  +  #  #  :        5305 :         foreach(l, root->parse->rowMarks)
                   -  + ]
    2113                 :             :         {
    2114                 :           0 :                 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
    2115                 :             : 
    2116         [ #  # ]:           0 :                 if (bms_is_member(rc->rti, right_rels) ||
    2117         [ #  # ]:           0 :                         (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                 :           0 :         }
    2125                 :             : 
    2126                 :        5305 :         sjinfo->syn_lefthand = left_rels;
    2127                 :        5305 :         sjinfo->syn_righthand = right_rels;
    2128                 :        5305 :         sjinfo->jointype = jointype;
    2129                 :        5305 :         sjinfo->ojrelid = ojrelid;
    2130                 :             :         /* these fields may get added to later: */
    2131                 :        5305 :         sjinfo->commute_above_l = NULL;
    2132                 :        5305 :         sjinfo->commute_above_r = NULL;
    2133                 :        5305 :         sjinfo->commute_below_l = NULL;
    2134                 :        5305 :         sjinfo->commute_below_r = NULL;
    2135                 :             : 
    2136                 :        5305 :         compute_semijoin_info(root, sjinfo, clause);
    2137                 :             : 
    2138                 :             :         /* If it's a full join, no need to be very smart */
    2139         [ +  + ]:        5305 :         if (jointype == JOIN_FULL)
    2140                 :             :         {
    2141                 :         141 :                 sjinfo->min_lefthand = bms_copy(left_rels);
    2142                 :         141 :                 sjinfo->min_righthand = bms_copy(right_rels);
    2143                 :         141 :                 sjinfo->lhs_strict = false; /* don't care about this */
    2144                 :         141 :                 return sjinfo;
    2145                 :             :         }
    2146                 :             : 
    2147                 :             :         /*
    2148                 :             :          * Retrieve all relids mentioned within the join clause.
    2149                 :             :          */
    2150                 :        5164 :         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                 :        5164 :         strict_relids = find_nonnullable_rels((Node *) clause);
    2157                 :             : 
    2158                 :             :         /* Remember whether the clause is strict for any LHS relations */
    2159                 :        5164 :         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                 :        5164 :         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                 :       10328 :         min_righthand = bms_int_members(bms_union(clause_relids, inner_join_rels),
    2172                 :        5164 :                                                                         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                 :        5164 :         commute_below_l = commute_below_r = NULL;
    2184   [ +  +  +  +  :        6482 :         foreach(l, root->join_info_list)
                   +  + ]
    2185                 :             :         {
    2186                 :        1318 :                 SpecialJoinInfo *otherinfo = (SpecialJoinInfo *) lfirst(l);
    2187                 :        1318 :                 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         [ +  + ]:        1318 :                 if (otherinfo->jointype == JOIN_FULL)
    2195                 :             :                 {
    2196         [ -  + ]:           9 :                         Assert(otherinfo->ojrelid != 0);
    2197   [ +  +  -  + ]:           9 :                         if (bms_overlap(left_rels, otherinfo->syn_lefthand) ||
    2198                 :           5 :                                 bms_overlap(left_rels, otherinfo->syn_righthand))
    2199                 :             :                         {
    2200                 :           8 :                                 min_lefthand = bms_add_members(min_lefthand,
    2201                 :           4 :                                                                                            otherinfo->syn_lefthand);
    2202                 :           8 :                                 min_lefthand = bms_add_members(min_lefthand,
    2203                 :           4 :                                                                                            otherinfo->syn_righthand);
    2204                 :           8 :                                 min_lefthand = bms_add_member(min_lefthand,
    2205                 :           4 :                                                                                           otherinfo->ojrelid);
    2206                 :           4 :                         }
    2207   [ +  +  -  + ]:           9 :                         if (bms_overlap(right_rels, otherinfo->syn_lefthand) ||
    2208                 :           4 :                                 bms_overlap(right_rels, otherinfo->syn_righthand))
    2209                 :             :                         {
    2210                 :          10 :                                 min_righthand = bms_add_members(min_righthand,
    2211                 :           5 :                                                                                                 otherinfo->syn_lefthand);
    2212                 :          10 :                                 min_righthand = bms_add_members(min_righthand,
    2213                 :           5 :                                                                                                 otherinfo->syn_righthand);
    2214                 :          10 :                                 min_righthand = bms_add_member(min_righthand,
    2215                 :           5 :                                                                                            otherinfo->ojrelid);
    2216                 :           5 :                         }
    2217                 :             :                         /* Needn't do anything else with the full join */
    2218                 :           9 :                         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         [ +  + ]:        1309 :                 if (otherinfo->ojrelid != 0)
    2226                 :        1289 :                         have_unsafe_phvs =
    2227                 :        2578 :                                 contain_placeholder_references_to(root,
    2228                 :        1289 :                                                                                                   (Node *) clause,
    2229                 :        1289 :                                                                                                   otherinfo->ojrelid);
    2230                 :             :                 else
    2231                 :          20 :                         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         [ +  + ]:        1309 :                 if (bms_overlap(left_rels, otherinfo->syn_righthand))
    2252                 :             :                 {
    2253   [ +  +  +  + ]:        1287 :                         if (bms_overlap(clause_relids, otherinfo->syn_righthand) &&
    2254         [ +  + ]:         102 :                                 (have_unsafe_phvs ||
    2255   [ +  -  +  - ]:         100 :                                  jointype == JOIN_SEMI || jointype == JOIN_ANTI ||
    2256                 :         100 :                                  !bms_overlap(strict_relids, otherinfo->min_righthand)))
    2257                 :             :                         {
    2258                 :             :                                 /* Preserve ordering */
    2259                 :          14 :                                 min_lefthand = bms_add_members(min_lefthand,
    2260                 :           7 :                                                                                            otherinfo->syn_lefthand);
    2261                 :          14 :                                 min_lefthand = bms_add_members(min_lefthand,
    2262                 :           7 :                                                                                            otherinfo->syn_righthand);
    2263         [ -  + ]:           7 :                                 if (otherinfo->ojrelid != 0)
    2264                 :          14 :                                         min_lefthand = bms_add_member(min_lefthand,
    2265                 :           7 :                                                                                                   otherinfo->ojrelid);
    2266                 :           7 :                         }
    2267         [ +  + ]:        1180 :                         else if (jointype == JOIN_LEFT &&
    2268         [ +  - ]:        1162 :                                          otherinfo->jointype == JOIN_LEFT &&
    2269   [ +  +  +  + ]:        1162 :                                          bms_overlap(strict_relids, otherinfo->min_righthand) &&
    2270                 :          95 :                                          !bms_overlap(clause_relids, otherinfo->syn_lefthand))
    2271                 :             :                         {
    2272                 :             :                                 /* Identity 3 applies, so remove the ordering restriction */
    2273                 :          89 :                                 min_lefthand = bms_del_member(min_lefthand, otherinfo->ojrelid);
    2274                 :             :                                 /* Record the (still tentative) commutability relationship */
    2275                 :          89 :                                 commute_below_l =
    2276                 :          89 :                                         bms_add_member(commute_below_l, otherinfo->ojrelid);
    2277                 :          89 :                         }
    2278                 :        1187 :                 }
    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         [ +  + ]:        1309 :                 if (bms_overlap(right_rels, otherinfo->syn_righthand))
    2299                 :             :                 {
    2300         [ +  + ]:         111 :                         if (bms_overlap(clause_relids, otherinfo->syn_righthand) ||
    2301         [ +  + ]:         103 :                                 !bms_overlap(clause_relids, otherinfo->min_lefthand) ||
    2302         [ +  - ]:          51 :                                 have_unsafe_phvs ||
    2303         [ +  + ]:          51 :                                 jointype == JOIN_SEMI ||
    2304         [ +  + ]:          41 :                                 jointype == JOIN_ANTI ||
    2305         [ +  + ]:          40 :                                 otherinfo->jointype == JOIN_SEMI ||
    2306   [ +  -  +  + ]:          38 :                                 otherinfo->jointype == JOIN_ANTI ||
    2307                 :          38 :                                 !otherinfo->lhs_strict)
    2308                 :             :                         {
    2309                 :             :                                 /* Preserve ordering */
    2310                 :         154 :                                 min_righthand = bms_add_members(min_righthand,
    2311                 :          77 :                                                                                                 otherinfo->syn_lefthand);
    2312                 :         154 :                                 min_righthand = bms_add_members(min_righthand,
    2313                 :          77 :                                                                                                 otherinfo->syn_righthand);
    2314         [ +  + ]:          77 :                                 if (otherinfo->ojrelid != 0)
    2315                 :         130 :                                         min_righthand = bms_add_member(min_righthand,
    2316                 :          65 :                                                                                                    otherinfo->ojrelid);
    2317                 :          77 :                         }
    2318         [ +  - ]:          34 :                         else if (jointype == JOIN_LEFT &&
    2319   [ +  -  -  + ]:          34 :                                          otherinfo->jointype == JOIN_LEFT &&
    2320                 :          34 :                                          otherinfo->lhs_strict)
    2321                 :             :                         {
    2322                 :             :                                 /* Identity 3 applies, so remove the ordering restriction */
    2323                 :          68 :                                 min_righthand = bms_del_member(min_righthand,
    2324                 :          34 :                                                                                            otherinfo->ojrelid);
    2325                 :             :                                 /* Record the (still tentative) commutability relationship */
    2326                 :          34 :                                 commute_below_r =
    2327                 :          34 :                                         bms_add_member(commute_below_r, otherinfo->ojrelid);
    2328                 :          34 :                         }
    2329                 :         111 :                 }
    2330         [ +  + ]:        1318 :         }
    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   [ +  +  +  +  :        5373 :         foreach(l, root->placeholder_list)
                   +  + ]
    2341                 :             :         {
    2342                 :         209 :                 PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(l);
    2343                 :         209 :                 Relids          ph_syn_level = phinfo->ph_var->phrels;
    2344                 :             : 
    2345                 :             :                 /* Ignore placeholder if it didn't syntactically come from RHS */
    2346         [ +  + ]:         209 :                 if (!bms_is_subset(ph_syn_level, right_rels))
    2347                 :          68 :                         continue;
    2348                 :             : 
    2349                 :             :                 /* Else, prevent join from being formed before we eval the PHV */
    2350                 :         141 :                 min_righthand = bms_add_members(min_righthand, phinfo->ph_eval_at);
    2351         [ +  + ]:         209 :         }
    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         [ +  + ]:        5164 :         if (bms_is_empty(min_lefthand))
    2360                 :         157 :                 min_lefthand = bms_copy(left_rels);
    2361         [ +  + ]:        5164 :         if (bms_is_empty(min_righthand))
    2362                 :          93 :                 min_righthand = bms_copy(right_rels);
    2363                 :             : 
    2364                 :             :         /* Now they'd better be nonempty */
    2365         [ +  - ]:        5164 :         Assert(!bms_is_empty(min_lefthand));
    2366         [ +  - ]:        5164 :         Assert(!bms_is_empty(min_righthand));
    2367                 :             :         /* Shouldn't overlap either */
    2368         [ +  - ]:        5164 :         Assert(!bms_overlap(min_lefthand, min_righthand));
    2369                 :             : 
    2370                 :        5164 :         sjinfo->min_lefthand = min_lefthand;
    2371                 :        5164 :         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                 :        5164 :         commute_below_l = bms_del_members(commute_below_l, min_lefthand);
    2383                 :        5164 :         commute_below_r = bms_del_members(commute_below_r, min_righthand);
    2384                 :             : 
    2385                 :             :         /* Anything left? */
    2386   [ +  +  +  + ]:        5164 :         if (commute_below_l || commute_below_r)
    2387                 :             :         {
    2388                 :             :                 /* Yup, so we must update the derived data in the SpecialJoinInfos */
    2389                 :         110 :                 sjinfo->commute_below_l = commute_below_l;
    2390                 :         110 :                 sjinfo->commute_below_r = commute_below_r;
    2391   [ +  -  +  +  :         276 :                 foreach(l, root->join_info_list)
                   +  + ]
    2392                 :             :                 {
    2393                 :         166 :                         SpecialJoinInfo *otherinfo = (SpecialJoinInfo *) lfirst(l);
    2394                 :             : 
    2395         [ +  + ]:         166 :                         if (bms_is_member(otherinfo->ojrelid, commute_below_l))
    2396                 :          89 :                                 otherinfo->commute_above_l =
    2397                 :          89 :                                         bms_add_member(otherinfo->commute_above_l, ojrelid);
    2398         [ +  + ]:          77 :                         else if (bms_is_member(otherinfo->ojrelid, commute_below_r))
    2399                 :          29 :                                 otherinfo->commute_above_r =
    2400                 :          29 :                                         bms_add_member(otherinfo->commute_above_r, ojrelid);
    2401                 :         166 :                 }
    2402                 :         110 :         }
    2403                 :             : 
    2404                 :        5164 :         return sjinfo;
    2405                 :        5305 : }
    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                 :        5305 : compute_semijoin_info(PlannerInfo *root, SpecialJoinInfo *sjinfo, List *clause)
    2416                 :             : {
    2417                 :        5305 :         List       *semi_operators;
    2418                 :        5305 :         List       *semi_rhs_exprs;
    2419                 :        5305 :         bool            all_btree;
    2420                 :        5305 :         bool            all_hash;
    2421                 :        5305 :         ListCell   *lc;
    2422                 :             : 
    2423                 :             :         /* Initialize semijoin-related fields in case we can't unique-ify */
    2424                 :        5305 :         sjinfo->semi_can_btree = false;
    2425                 :        5305 :         sjinfo->semi_can_hash = false;
    2426                 :        5305 :         sjinfo->semi_operators = NIL;
    2427                 :        5305 :         sjinfo->semi_rhs_exprs = NIL;
    2428                 :             : 
    2429                 :             :         /* Nothing more to do if it's not a semijoin */
    2430         [ +  + ]:        5305 :         if (sjinfo->jointype != JOIN_SEMI)
    2431                 :        4605 :                 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                 :         700 :         semi_operators = NIL;
    2460                 :         700 :         semi_rhs_exprs = NIL;
    2461                 :         700 :         all_btree = true;
    2462                 :         700 :         all_hash = enable_hashagg;      /* don't consider hash if not enabled */
    2463   [ +  -  +  +  :        1473 :         foreach(lc, clause)
             +  +  +  + ]
    2464                 :             :         {
    2465                 :         773 :                 OpExpr     *op = (OpExpr *) lfirst(lc);
    2466                 :         773 :                 Oid                     opno;
    2467                 :         773 :                 Node       *left_expr;
    2468                 :         773 :                 Node       *right_expr;
    2469                 :         773 :                 Relids          left_varnos;
    2470                 :         773 :                 Relids          right_varnos;
    2471                 :         773 :                 Relids          all_varnos;
    2472                 :         773 :                 Oid                     opinputtype;
    2473                 :             : 
    2474                 :             :                 /* Is it a binary opclause? */
    2475   [ +  +  -  + ]:         773 :                 if (!IsA(op, OpExpr) ||
    2476                 :         758 :                         list_length(op->args) != 2)
    2477                 :             :                 {
    2478                 :             :                         /* No, but does it reference both sides? */
    2479                 :          15 :                         all_varnos = pull_varnos(root, (Node *) op);
    2480   [ +  +  +  + ]:          15 :                         if (!bms_overlap(all_varnos, sjinfo->syn_righthand) ||
    2481                 :          13 :                                 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         [ -  + ]:          13 :                                 if (contain_volatile_functions((Node *) op))
    2489                 :           0 :                                         return;
    2490                 :          13 :                                 continue;
    2491                 :             :                         }
    2492                 :             :                         /* Non-operator clause referencing both sides, must punt */
    2493                 :           2 :                         return;
    2494                 :             :                 }
    2495                 :             : 
    2496                 :             :                 /* Extract data from binary opclause */
    2497                 :         758 :                 opno = op->opno;
    2498                 :         758 :                 left_expr = linitial(op->args);
    2499                 :         758 :                 right_expr = lsecond(op->args);
    2500                 :         758 :                 left_varnos = pull_varnos(root, left_expr);
    2501                 :         758 :                 right_varnos = pull_varnos(root, right_expr);
    2502                 :         758 :                 all_varnos = bms_union(left_varnos, right_varnos);
    2503                 :         758 :                 opinputtype = exprType(left_expr);
    2504                 :             : 
    2505                 :             :                 /* Does it reference both sides? */
    2506   [ +  +  +  + ]:         758 :                 if (!bms_overlap(all_varnos, sjinfo->syn_righthand) ||
    2507                 :         756 :                         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         [ -  + ]:          14 :                         if (contain_volatile_functions((Node *) op))
    2514                 :           0 :                                 return;
    2515                 :          14 :                         continue;
    2516                 :             :                 }
    2517                 :             : 
    2518                 :             :                 /* check rel membership of arguments */
    2519         [ +  - ]:         744 :                 if (!bms_is_empty(right_varnos) &&
    2520   [ +  +  -  + ]:         744 :                         bms_is_subset(right_varnos, sjinfo->syn_righthand) &&
    2521                 :         693 :                         !bms_overlap(left_varnos, sjinfo->syn_righthand))
    2522                 :             :                 {
    2523                 :             :                         /* typical case, right_expr is RHS variable */
    2524                 :         693 :                 }
    2525         [ +  - ]:          51 :                 else if (!bms_is_empty(left_varnos) &&
    2526   [ +  +  -  + ]:          51 :                                  bms_is_subset(left_varnos, sjinfo->syn_righthand) &&
    2527                 :          50 :                                  !bms_overlap(right_varnos, sjinfo->syn_righthand))
    2528                 :             :                 {
    2529                 :             :                         /* flipped case, left_expr is RHS variable */
    2530                 :          50 :                         opno = get_commutator(opno);
    2531         [ +  - ]:          50 :                         if (!OidIsValid(opno))
    2532                 :           0 :                                 return;
    2533                 :          50 :                         right_expr = left_expr;
    2534                 :          50 :                 }
    2535                 :             :                 else
    2536                 :             :                 {
    2537                 :             :                         /* mixed membership of args, punt */
    2538                 :           1 :                         return;
    2539                 :             :                 }
    2540                 :             : 
    2541                 :             :                 /* all operators must be btree equality or hash equality */
    2542         [ -  + ]:         743 :                 if (all_btree)
    2543                 :             :                 {
    2544                 :             :                         /* oprcanmerge is considered a hint... */
    2545   [ +  +  +  - ]:         743 :                         if (!op_mergejoinable(opno, opinputtype) ||
    2546                 :         730 :                                 get_mergejoin_opfamilies(opno) == NIL)
    2547                 :          13 :                                 all_btree = false;
    2548                 :         743 :                 }
    2549         [ +  + ]:         743 :                 if (all_hash)
    2550                 :             :                 {
    2551                 :             :                         /* ... but oprcanhash had better be correct */
    2552         [ +  + ]:         734 :                         if (!op_hashjoinable(opno, opinputtype))
    2553                 :          13 :                                 all_hash = false;
    2554                 :         734 :                 }
    2555   [ +  +  -  + ]:         743 :                 if (!(all_btree || all_hash))
    2556                 :          13 :                         return;
    2557                 :             : 
    2558                 :             :                 /* so far so good, keep building lists */
    2559                 :         730 :                 semi_operators = lappend_oid(semi_operators, opno);
    2560                 :         730 :                 semi_rhs_exprs = lappend(semi_rhs_exprs, copyObject(right_expr));
    2561      [ +  +  + ]:         773 :         }
    2562                 :             : 
    2563                 :             :         /* Punt if we didn't find at least one column to unique-ify */
    2564         [ +  + ]:         684 :         if (semi_rhs_exprs == NIL)
    2565                 :           2 :                 return;
    2566                 :             : 
    2567                 :             :         /*
    2568                 :             :          * The expressions we'd need to unique-ify mustn't be volatile.
    2569                 :             :          */
    2570         [ -  + ]:         682 :         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                 :         682 :         sjinfo->semi_can_btree = all_btree;
    2578                 :         682 :         sjinfo->semi_can_hash = all_hash;
    2579                 :         682 :         sjinfo->semi_operators = semi_operators;
    2580                 :         682 :         sjinfo->semi_rhs_exprs = semi_rhs_exprs;
    2581         [ -  + ]:        5305 : }
    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                 :        3887 : deconstruct_distribute_oj_quals(PlannerInfo *root,
    2594                 :             :                                                                 List *jtitems,
    2595                 :             :                                                                 JoinTreeItem *jtitem)
    2596                 :             : {
    2597                 :        3887 :         SpecialJoinInfo *sjinfo = jtitem->sjinfo;
    2598                 :        3887 :         Relids          qualscope,
    2599                 :             :                                 ojscope,
    2600                 :             :                                 nonnullable_rels;
    2601                 :             : 
    2602                 :             :         /* Recompute syntactic and semantic scopes of this left join */
    2603                 :        3887 :         qualscope = bms_union(sjinfo->syn_lefthand, sjinfo->syn_righthand);
    2604                 :        3887 :         qualscope = bms_add_member(qualscope, sjinfo->ojrelid);
    2605                 :        3887 :         ojscope = bms_union(sjinfo->min_lefthand, sjinfo->min_righthand);
    2606                 :        3887 :         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         [ +  - ]:        3887 :         Assert(sjinfo->lhs_strict); /* else we shouldn't be here */
    2616   [ +  +  +  + ]:        3887 :         if (sjinfo->commute_above_r || sjinfo->commute_below_l)
    2617                 :             :         {
    2618                 :         112 :                 Relids          joins_above;
    2619                 :         112 :                 Relids          joins_below;
    2620                 :         112 :                 Relids          incompatible_joins;
    2621                 :         112 :                 Relids          joins_so_far;
    2622                 :         112 :                 List       *quals;
    2623                 :         112 :                 int                     save_last_rinfo_serial;
    2624                 :         112 :                 ListCell   *lc;
    2625                 :             : 
    2626                 :             :                 /* Identify the outer joins this one commutes with */
    2627                 :         112 :                 joins_above = sjinfo->commute_above_r;
    2628                 :         112 :                 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                 :         112 :                 quals = jtitem->oj_joinclauses;
    2649         [ +  + ]:         112 :                 if (!bms_is_empty(joins_below))
    2650                 :         166 :                         quals = (List *) remove_nulling_relids((Node *) quals,
    2651                 :          83 :                                                                                                    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                 :         112 :                 incompatible_joins = bms_union(joins_below, joins_above);
    2660                 :         224 :                 incompatible_joins = bms_add_member(incompatible_joins,
    2661                 :         112 :                                                                                         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                 :         112 :                 save_last_rinfo_serial = root->last_rinfo_serial;
    2672                 :             : 
    2673                 :         112 :                 joins_so_far = NULL;
    2674   [ +  -  +  +  :        1074 :                 foreach(lc, jtitems)
                   +  + ]
    2675                 :             :                 {
    2676                 :         962 :                         JoinTreeItem *otherjtitem = (JoinTreeItem *) lfirst(lc);
    2677                 :         962 :                         SpecialJoinInfo *othersj = otherjtitem->sjinfo;
    2678                 :         962 :                         bool            below_sjinfo = false;
    2679                 :         962 :                         bool            above_sjinfo = false;
    2680                 :         962 :                         Relids          this_qualscope;
    2681                 :         962 :                         Relids          this_ojscope;
    2682                 :         962 :                         bool            allow_equivalence,
    2683                 :             :                                                 has_clone,
    2684                 :             :                                                 is_clone;
    2685                 :             : 
    2686         [ +  + ]:         962 :                         if (othersj == NULL)
    2687                 :         644 :                                 continue;               /* not an outer-join item, ignore */
    2688                 :             : 
    2689         [ +  + ]:         318 :                         if (bms_is_member(othersj->ojrelid, joins_below))
    2690                 :             :                         {
    2691                 :             :                                 /* othersj commutes with sjinfo from below left */
    2692                 :          89 :                                 below_sjinfo = true;
    2693                 :          89 :                         }
    2694         [ +  + ]:         229 :                         else if (othersj == sjinfo)
    2695                 :             :                         {
    2696                 :             :                                 /* found our join in syntactic order */
    2697         [ -  + ]:         112 :                                 Assert(bms_equal(joins_so_far, joins_below));
    2698                 :         112 :                         }
    2699         [ +  + ]:         117 :                         else if (bms_is_member(othersj->ojrelid, joins_above))
    2700                 :             :                         {
    2701                 :             :                                 /* othersj commutes with sjinfo from above */
    2702                 :          29 :                                 above_sjinfo = true;
    2703                 :          29 :                         }
    2704                 :             :                         else
    2705                 :             :                         {
    2706                 :             :                                 /* othersj is not relevant, ignore */
    2707                 :          88 :                                 continue;
    2708                 :             :                         }
    2709                 :             : 
    2710                 :             :                         /* Reset serial counter for this version of the quals */
    2711                 :         230 :                         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         [ +  + ]:         230 :                         if (above_sjinfo)
    2727                 :             :                         {
    2728                 :          29 :                                 quals = (List *)
    2729                 :          58 :                                         add_nulling_relids((Node *) quals,
    2730                 :          29 :                                                                            sjinfo->syn_lefthand,
    2731                 :          29 :                                                                            bms_make_singleton(othersj->ojrelid));
    2732                 :          58 :                                 incompatible_joins = bms_del_member(incompatible_joins,
    2733                 :          29 :                                                                                                         othersj->ojrelid);
    2734                 :          29 :                         }
    2735                 :             : 
    2736                 :             :                         /* Compute qualscope and ojscope for this join level */
    2737                 :         230 :                         this_qualscope = bms_union(qualscope, joins_so_far);
    2738                 :         230 :                         this_ojscope = bms_union(ojscope, joins_so_far);
    2739         [ +  + ]:         230 :                         if (above_sjinfo)
    2740                 :             :                         {
    2741                 :             :                                 /* othersj is not yet in joins_so_far, but we need it */
    2742                 :          58 :                                 this_qualscope = bms_add_member(this_qualscope,
    2743                 :          29 :                                                                                                 othersj->ojrelid);
    2744                 :          58 :                                 this_ojscope = bms_add_member(this_ojscope,
    2745                 :          29 :                                                                                           othersj->ojrelid);
    2746                 :             :                                 /* sjinfo is in joins_so_far, and we don't want it */
    2747                 :          58 :                                 this_ojscope = bms_del_member(this_ojscope,
    2748                 :          29 :                                                                                           sjinfo->ojrelid);
    2749                 :          29 :                         }
    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                 :         230 :                         allow_equivalence = (joins_so_far == NULL);
    2767                 :         230 :                         has_clone = allow_equivalence;
    2768                 :         230 :                         is_clone = !has_clone;
    2769                 :             : 
    2770                 :         460 :                         distribute_quals_to_rels(root, quals,
    2771                 :         230 :                                                                          otherjtitem,
    2772                 :         230 :                                                                          sjinfo,
    2773                 :         230 :                                                                          root->qual_security_level,
    2774                 :         230 :                                                                          this_qualscope,
    2775                 :         230 :                                                                          this_ojscope, nonnullable_rels,
    2776                 :         230 :                                                                          bms_copy(incompatible_joins),
    2777                 :         230 :                                                                          allow_equivalence,
    2778                 :         230 :                                                                          has_clone,
    2779                 :         230 :                                                                          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         [ +  + ]:         230 :                         if (below_sjinfo)
    2792                 :             :                         {
    2793                 :          89 :                                 quals = (List *)
    2794                 :         178 :                                         add_nulling_relids((Node *) quals,
    2795                 :          89 :                                                                            othersj->syn_righthand,
    2796                 :          89 :                                                                            bms_make_singleton(othersj->ojrelid));
    2797                 :         178 :                                 incompatible_joins = bms_del_member(incompatible_joins,
    2798                 :          89 :                                                                                                         othersj->ojrelid);
    2799                 :          89 :                         }
    2800                 :             : 
    2801                 :             :                         /* ... and track joins processed so far */
    2802                 :         230 :                         joins_so_far = bms_add_member(joins_so_far, othersj->ojrelid);
    2803      [ -  +  + ]:         962 :                 }
    2804                 :         112 :         }
    2805                 :             :         else
    2806                 :             :         {
    2807                 :             :                 /* No commutation possible, just process the postponed clauses */
    2808                 :        7550 :                 distribute_quals_to_rels(root, jtitem->oj_joinclauses,
    2809                 :        3775 :                                                                  jtitem,
    2810                 :        3775 :                                                                  sjinfo,
    2811                 :        3775 :                                                                  root->qual_security_level,
    2812                 :        3775 :                                                                  qualscope,
    2813                 :        3775 :                                                                  ojscope, nonnullable_rels,
    2814                 :             :                                                                  NULL,  /* incompatible_relids */
    2815                 :             :                                                                  true,  /* allow_equivalence */
    2816                 :             :                                                                  false, false,  /* not clones */
    2817                 :             :                                                                  NULL); /* no more postponement */
    2818                 :             :         }
    2819                 :        3887 : }
    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                 :       84704 : 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                 :       84704 :         ListCell   *lc;
    2848                 :             : 
    2849   [ +  +  +  +  :      138777 :         foreach(lc, clauses)
                   +  + ]
    2850                 :             :         {
    2851                 :       54073 :                 Node       *clause = (Node *) lfirst(lc);
    2852                 :             : 
    2853                 :      108146 :                 distribute_qual_to_rels(root, clause,
    2854                 :       54073 :                                                                 jtitem,
    2855                 :       54073 :                                                                 sjinfo,
    2856                 :       54073 :                                                                 security_level,
    2857                 :       54073 :                                                                 qualscope,
    2858                 :       54073 :                                                                 ojscope,
    2859                 :       54073 :                                                                 outerjoin_nonnullable,
    2860                 :       54073 :                                                                 incompatible_relids,
    2861                 :       54073 :                                                                 allow_equivalence,
    2862                 :       54073 :                                                                 has_clone,
    2863                 :       54073 :                                                                 is_clone,
    2864                 :       54073 :                                                                 postponed_oj_qual_list);
    2865                 :       54073 :         }
    2866                 :       84704 : }
    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                 :       54073 : 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                 :       54073 :         Relids          relids;
    2926                 :       54073 :         bool            is_pushed_down;
    2927                 :       54073 :         bool            pseudoconstant = false;
    2928                 :       54073 :         bool            maybe_equivalence;
    2929                 :       54073 :         bool            maybe_outer_join;
    2930                 :       54073 :         RestrictInfo *restrictinfo;
    2931                 :             : 
    2932                 :             :         /*
    2933                 :             :          * Retrieve all relids mentioned within the clause.
    2934                 :             :          */
    2935                 :       54073 :         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         [ +  + ]:       54073 :         if (!bms_is_subset(relids, qualscope))
    2950                 :             :         {
    2951                 :          17 :                 JoinTreeItem *pitem;
    2952                 :             : 
    2953         [ +  - ]:          17 :                 Assert(root->hasLateralRTEs);        /* shouldn't happen otherwise */
    2954         [ +  - ]:          17 :                 Assert(sjinfo == NULL); /* mustn't postpone past outer join */
    2955         [ +  - ]:          18 :                 for (pitem = jtitem->jti_parent; pitem; pitem = pitem->jti_parent)
    2956                 :             :                 {
    2957         [ +  + ]:          18 :                         if (bms_is_subset(relids, pitem->qualscope))
    2958                 :             :                         {
    2959                 :          34 :                                 pitem->lateral_clauses = lappend(pitem->lateral_clauses,
    2960                 :          17 :                                                                                                  clause);
    2961                 :          17 :                                 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         [ +  - ]:           1 :                         Assert(pitem->sjinfo == NULL);
    2969                 :           1 :                 }
    2970   [ #  #  #  # ]:           0 :                 elog(ERROR, "failed to postpone qual containing lateral reference");
    2971         [ +  - ]:          17 :         }
    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   [ +  +  +  - ]:       54056 :         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         [ +  + ]:       54056 :         if (bms_is_empty(relids))
    3001                 :             :         {
    3002         [ +  + ]:        1808 :                 if (ojscope)
    3003                 :             :                 {
    3004                 :             :                         /* clause is attached to outer join, eval it there */
    3005                 :          52 :                         relids = bms_copy(ojscope);
    3006                 :             :                         /* mustn't use as gating qual, so don't mark pseudoconstant */
    3007                 :          52 :                 }
    3008         [ +  + ]:        1756 :                 else if (contain_volatile_functions(clause))
    3009                 :             :                 {
    3010                 :             :                         /* eval at original syntactic level */
    3011                 :           8 :                         relids = bms_copy(qualscope);
    3012                 :             :                         /* again, can't mark pseudoconstant */
    3013                 :           8 :                 }
    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         [ +  + ]:        1748 :                         if (jtitem->jdomain == (JoinDomain *) linitial(root->join_domains))
    3026                 :        1738 :                                 relids = bms_copy(jtitem->jdomain->jd_relids);
    3027                 :             :                         else
    3028                 :          10 :                                 relids = bms_copy(qualscope);
    3029                 :             :                         /* mark as gating qual */
    3030                 :        1748 :                         pseudoconstant = true;
    3031                 :             :                         /* tell createplan.c to check for gating quals */
    3032                 :        1748 :                         root->hasPseudoConstantQuals = true;
    3033                 :             :                 }
    3034                 :        1808 :         }
    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         [ +  + ]:       54056 :         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         [ +  + ]:        9308 :                 if (postponed_oj_qual_list != NULL)
    3078                 :             :                 {
    3079                 :        4230 :                         *postponed_oj_qual_list = lappend(*postponed_oj_qual_list, clause);
    3080                 :        4230 :                         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                 :        5078 :                 is_pushed_down = false;
    3091                 :        5078 :                 maybe_equivalence = false;
    3092                 :        5078 :                 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         [ +  - ]:        5078 :                 Assert(ojscope);
    3102                 :        5078 :                 relids = ojscope;
    3103         [ +  - ]:        5078 :                 Assert(!pseudoconstant);
    3104                 :        5078 :         }
    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                 :       44748 :                 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         [ +  + ]:       44748 :                 if (check_redundant_nullability_qual(root, clause))
    3120                 :         125 :                         return;
    3121                 :             : 
    3122                 :             :                 /* Feed qual to the equivalence machinery, if allowed by caller */
    3123                 :       44623 :                 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                 :       44623 :                 maybe_outer_join = false;
    3130                 :             :         }
    3131                 :             : 
    3132                 :             :         /*
    3133                 :             :          * Build the RestrictInfo node itself.
    3134                 :             :          */
    3135                 :       99402 :         restrictinfo = make_restrictinfo(root,
    3136                 :       49701 :                                                                          (Expr *) clause,
    3137                 :       49701 :                                                                          is_pushed_down,
    3138                 :       49701 :                                                                          has_clone,
    3139                 :       49701 :                                                                          is_clone,
    3140                 :       49701 :                                                                          pseudoconstant,
    3141                 :       49701 :                                                                          security_level,
    3142                 :       49701 :                                                                          relids,
    3143                 :       49701 :                                                                          incompatible_relids,
    3144                 :       49701 :                                                                          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         [ +  + ]:       49701 :         if (bms_membership(relids) == BMS_MULTIPLE)
    3168                 :             :         {
    3169                 :       14465 :                 List       *vars = pull_var_clause(clause,
    3170                 :             :                                                                                    PVC_RECURSE_AGGREGATES |
    3171                 :             :                                                                                    PVC_RECURSE_WINDOWFUNCS |
    3172                 :             :                                                                                    PVC_INCLUDE_PLACEHOLDERS);
    3173                 :       14465 :                 Relids          where_needed;
    3174                 :             : 
    3175         [ +  + ]:       14465 :                 if (is_clone)
    3176                 :         125 :                         where_needed = bms_intersect(relids, root->all_baserels);
    3177                 :             :                 else
    3178                 :       14340 :                         where_needed = relids;
    3179                 :       14465 :                 add_vars_to_targetlist(root, vars, where_needed);
    3180                 :       14465 :                 list_free(vars);
    3181                 :       14465 :         }
    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                 :       49701 :         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         [ +  + ]:       49701 :         if (restrictinfo->mergeopfamilies)
    3223                 :             :         {
    3224         [ +  + ]:       32754 :                 if (maybe_equivalence)
    3225                 :             :                 {
    3226         [ +  + ]:       27825 :                         if (process_equivalence(root, &restrictinfo, jtitem->jdomain))
    3227                 :       27782 :                                 return;
    3228                 :             :                         /* EC rejected it, so set left_ec/right_ec the hard way ... */
    3229         [ +  + ]:          43 :                         if (restrictinfo->mergeopfamilies)   /* EC might have changed this */
    3230                 :          34 :                                 initialize_mergeclause_eclasses(root, restrictinfo);
    3231                 :             :                         /* ... and fall through to distribute_restrictinfo_to_rels */
    3232                 :          43 :                 }
    3233   [ +  -  +  + ]:        4929 :                 else if (maybe_outer_join && restrictinfo->can_join)
    3234                 :             :                 {
    3235                 :             :                         /* we need to set up left_ec/right_ec the hard way */
    3236                 :        4877 :                         initialize_mergeclause_eclasses(root, restrictinfo);
    3237                 :             :                         /* now see if it should go to any outer-join lists */
    3238         [ +  - ]:        4877 :                         Assert(sjinfo != NULL);
    3239                 :        9754 :                         if (bms_is_subset(restrictinfo->left_relids,
    3240   [ +  +  +  +  :        9754 :                                                           outerjoin_nonnullable) &&
                   +  + ]
    3241                 :        5746 :                                 !bms_overlap(restrictinfo->right_relids,
    3242                 :        2873 :                                                          outerjoin_nonnullable))
    3243                 :             :                         {
    3244                 :             :                                 /* we have outervar = innervar */
    3245                 :        2693 :                                 OuterJoinClauseInfo *ojcinfo = makeNode(OuterJoinClauseInfo);
    3246                 :             : 
    3247                 :        2693 :                                 ojcinfo->rinfo = restrictinfo;
    3248                 :        2693 :                                 ojcinfo->sjinfo = sjinfo;
    3249                 :        5386 :                                 root->left_join_clauses = lappend(root->left_join_clauses,
    3250                 :        2693 :                                                                                                   ojcinfo);
    3251                 :             :                                 return;
    3252                 :        2693 :                         }
    3253                 :        4368 :                         if (bms_is_subset(restrictinfo->right_relids,
    3254   [ +  +  +  +  :        4368 :                                                           outerjoin_nonnullable) &&
                   +  + ]
    3255                 :        4320 :                                 !bms_overlap(restrictinfo->left_relids,
    3256                 :        2160 :                                                          outerjoin_nonnullable))
    3257                 :             :                         {
    3258                 :             :                                 /* we have innervar = outervar */
    3259                 :        1980 :                                 OuterJoinClauseInfo *ojcinfo = makeNode(OuterJoinClauseInfo);
    3260                 :             : 
    3261                 :        1980 :                                 ojcinfo->rinfo = restrictinfo;
    3262                 :        1980 :                                 ojcinfo->sjinfo = sjinfo;
    3263                 :        3960 :                                 root->right_join_clauses = lappend(root->right_join_clauses,
    3264                 :        1980 :                                                                                                    ojcinfo);
    3265                 :             :                                 return;
    3266                 :        1980 :                         }
    3267         [ +  + ]:         204 :                         if (sjinfo->jointype == JOIN_FULL)
    3268                 :             :                         {
    3269                 :             :                                 /* FULL JOIN (above tests cannot match in this case) */
    3270                 :         174 :                                 OuterJoinClauseInfo *ojcinfo = makeNode(OuterJoinClauseInfo);
    3271                 :             : 
    3272                 :         174 :                                 ojcinfo->rinfo = restrictinfo;
    3273                 :         174 :                                 ojcinfo->sjinfo = sjinfo;
    3274                 :         348 :                                 root->full_join_clauses = lappend(root->full_join_clauses,
    3275                 :         174 :                                                                                                   ojcinfo);
    3276                 :             :                                 return;
    3277                 :         174 :                         }
    3278                 :             :                         /* nope, so fall through to distribute_restrictinfo_to_rels */
    3279                 :          30 :                 }
    3280                 :             :                 else
    3281                 :             :                 {
    3282                 :             :                         /* we still need to set up left_ec/right_ec */
    3283                 :          52 :                         initialize_mergeclause_eclasses(root, restrictinfo);
    3284                 :             :                 }
    3285                 :         125 :         }
    3286                 :             : 
    3287                 :             :         /* No EC special case applies, so push it into the clause lists */
    3288                 :       17072 :         distribute_restrictinfo_to_rels(root, restrictinfo);
    3289         [ -  + ]:       54073 : }
    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                 :       44748 : check_redundant_nullability_qual(PlannerInfo *root, Node *clause)
    3303                 :             : {
    3304                 :       44748 :         Var                *forced_null_var;
    3305                 :       44748 :         ListCell   *lc;
    3306                 :             : 
    3307                 :             :         /* Check for IS NULL, and identify the Var forced to NULL */
    3308                 :       44748 :         forced_null_var = find_forced_null_var(clause);
    3309         [ +  + ]:       44748 :         if (forced_null_var == NULL)
    3310                 :       44399 :                 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         [ +  + ]:         349 :         if (forced_null_var->varnullingrels == NULL)
    3319                 :         215 :                 return false;
    3320                 :             : 
    3321   [ +  -  +  +  :         275 :         foreach(lc, root->join_info_list)
             +  +  +  + ]
    3322                 :             :         {
    3323                 :         141 :                 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   [ +  +  +  -  :         141 :                 if (sjinfo->jointype == JOIN_ANTI && sjinfo->ojrelid != 0 &&
                   -  + ]
    3331                 :         125 :                         bms_is_member(sjinfo->ojrelid, forced_null_var->varnullingrels))
    3332                 :         125 :                         return true;
    3333         [ +  + ]:         141 :         }
    3334                 :             : 
    3335                 :           9 :         return false;
    3336                 :       44748 : }
    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                 :       36694 : add_base_clause_to_rel(PlannerInfo *root, Index relid,
    3348                 :             :                                            RestrictInfo *restrictinfo)
    3349                 :             : {
    3350                 :       36694 :         RelOptInfo *rel = find_base_rel(root, relid);
    3351                 :       36694 :         RangeTblEntry *rte = root->simple_rte_array[relid];
    3352                 :             : 
    3353         [ +  - ]:       36694 :         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   [ +  +  +  + ]:       36694 :         if (!rte->inh || rte->relkind == RELKIND_PARTITIONED_TABLE)
    3371                 :             :         {
    3372                 :             :                 /* Don't add the clause if it is always true */
    3373         [ +  + ]:       36371 :                 if (restriction_is_always_true(root, restrictinfo))
    3374                 :          36 :                         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         [ +  - ]:       36335 :                 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                 :           0 :                                                                                          restrictinfo->required_relids,
    3399                 :           0 :                                                                                          restrictinfo->incompatible_relids,
    3400                 :           0 :                                                                                          restrictinfo->outer_relids);
    3401                 :           0 :                         restrictinfo->rinfo_serial = save_rinfo_serial;
    3402                 :           0 :                         root->last_rinfo_serial = save_last_rinfo_serial;
    3403                 :           0 :                 }
    3404                 :       36335 :         }
    3405                 :             : 
    3406                 :             :         /* Add clause to rel's restriction list */
    3407                 :       36658 :         rel->baserestrictinfo = lappend(rel->baserestrictinfo, restrictinfo);
    3408                 :             : 
    3409                 :             :         /* Update security level info */
    3410         [ +  + ]:       36658 :         rel->baserestrict_min_security = Min(rel->baserestrict_min_security,
    3411                 :             :                                                                                  restrictinfo->security_level);
    3412         [ -  + ]:       36694 : }
    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                 :       48600 : 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   [ +  +  +  + ]:       48600 :         if (restrictinfo->has_clone || restrictinfo->is_clone)
    3432                 :         244 :                 return false;
    3433                 :             : 
    3434                 :             :         /* Check for NullTest qual */
    3435         [ +  + ]:       48356 :         if (IsA(restrictinfo->clause, NullTest))
    3436                 :             :         {
    3437                 :        1174 :                 NullTest   *nulltest = (NullTest *) restrictinfo->clause;
    3438                 :             : 
    3439                 :             :                 /* is this NullTest an IS_NOT_NULL qual? */
    3440         [ +  + ]:        1174 :                 if (nulltest->nulltesttype != IS_NOT_NULL)
    3441                 :         417 :                         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         [ +  + ]:         757 :                 if (nulltest->argisrow)
    3448                 :          20 :                         return false;
    3449                 :             : 
    3450                 :         737 :                 return expr_is_nonnullable(root, nulltest->arg, true);
    3451                 :        1174 :         }
    3452                 :             : 
    3453                 :             :         /* If it's an OR, check its sub-clauses */
    3454         [ +  + ]:       47182 :         if (restriction_is_or_clause(restrictinfo))
    3455                 :             :         {
    3456                 :         848 :                 ListCell   *lc;
    3457                 :             : 
    3458         [ +  - ]:         848 :                 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   [ +  -  +  +  :        2925 :                 foreach(lc, ((BoolExpr *) restrictinfo->orclause)->args)
             +  +  -  + ]
    3465                 :             :                 {
    3466                 :        2077 :                         Node       *orarg = (Node *) lfirst(lc);
    3467                 :             : 
    3468         [ +  + ]:        2077 :                         if (!IsA(orarg, RestrictInfo))
    3469                 :         374 :                                 continue;
    3470                 :             : 
    3471         [ -  + ]:        1703 :                         if (restriction_is_always_true(root, (RestrictInfo *) orarg))
    3472                 :           0 :                                 return true;
    3473      [ +  -  + ]:        2077 :                 }
    3474      [ -  -  + ]:         848 :         }
    3475                 :             : 
    3476                 :       47182 :         return false;
    3477                 :       48600 : }
    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                 :       47572 : 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   [ +  +  +  + ]:       47572 :         if (restrictinfo->has_clone || restrictinfo->is_clone)
    3497                 :         244 :                 return false;
    3498                 :             : 
    3499                 :             :         /* Check for NullTest qual */
    3500         [ +  + ]:       47328 :         if (IsA(restrictinfo->clause, NullTest))
    3501                 :             :         {
    3502                 :        1076 :                 NullTest   *nulltest = (NullTest *) restrictinfo->clause;
    3503                 :             : 
    3504                 :             :                 /* is this NullTest an IS_NULL qual? */
    3505         [ +  + ]:        1076 :                 if (nulltest->nulltesttype != IS_NULL)
    3506                 :         695 :                         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         [ +  + ]:         381 :                 if (nulltest->argisrow)
    3513                 :          14 :                         return false;
    3514                 :             : 
    3515                 :         367 :                 return expr_is_nonnullable(root, nulltest->arg, true);
    3516                 :        1076 :         }
    3517                 :             : 
    3518                 :             :         /* If it's an OR, check its sub-clauses */
    3519         [ +  + ]:       46252 :         if (restriction_is_or_clause(restrictinfo))
    3520                 :             :         {
    3521                 :         848 :                 ListCell   *lc;
    3522                 :             : 
    3523         [ +  - ]:         848 :                 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   [ +  -  -  +  :        1696 :                 foreach(lc, ((BoolExpr *) restrictinfo->orclause)->args)
             +  -  +  - ]
    3535                 :             :                 {
    3536                 :         848 :                         Node       *orarg = (Node *) lfirst(lc);
    3537                 :             : 
    3538   [ +  +  +  - ]:         848 :                         if (!IsA(orarg, RestrictInfo) ||
    3539                 :         711 :                                 !restriction_is_always_false(root, (RestrictInfo *) orarg))
    3540                 :         848 :                                 return false;
    3541         [ +  - ]:         848 :                 }
    3542                 :           0 :                 return true;
    3543                 :         848 :         }
    3544                 :             : 
    3545                 :       45404 :         return false;
    3546                 :       47572 : }
    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                 :       42820 : distribute_restrictinfo_to_rels(PlannerInfo *root,
    3559                 :             :                                                                 RestrictInfo *restrictinfo)
    3560                 :             : {
    3561                 :       42820 :         Relids          relids = restrictinfo->required_relids;
    3562                 :             : 
    3563         [ +  - ]:       42820 :         if (!bms_is_empty(relids))
    3564                 :             :         {
    3565                 :       42820 :                 int                     relid;
    3566                 :             : 
    3567         [ +  + ]:       42820 :                 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                 :       36694 :                         add_base_clause_to_rel(root, relid, restrictinfo);
    3574                 :       36694 :                 }
    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                 :        6126 :                         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                 :        6126 :                         check_memoizable(restrictinfo);
    3594                 :             : 
    3595                 :             :                         /*
    3596                 :             :                          * Add clause to the join lists of all the relevant relations.
    3597                 :             :                          */
    3598                 :        6126 :                         add_join_clause_to_rels(root, restrictinfo, relids);
    3599                 :             :                 }
    3600                 :       42820 :         }
    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                 :       42820 : }
    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                 :        2942 : 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                 :        2942 :         RestrictInfo *restrictinfo;
    3653                 :        2942 :         Node       *clause;
    3654                 :        2942 :         Relids          relids;
    3655                 :        2942 :         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                 :        5884 :         clause = (Node *) make_opclause(opno,
    3662                 :             :                                                                         BOOLOID,        /* opresulttype */
    3663                 :             :                                                                         false,  /* opretset */
    3664                 :        2942 :                                                                         copyObject(item1),
    3665                 :        2942 :                                                                         copyObject(item2),
    3666                 :             :                                                                         InvalidOid,
    3667                 :        2942 :                                                                         collation);
    3668                 :             : 
    3669                 :             :         /* If both constant, try to reduce to a boolean constant. */
    3670         [ +  + ]:        2942 :         if (both_const)
    3671                 :             :         {
    3672                 :          22 :                 clause = eval_const_expressions(root, clause);
    3673                 :             : 
    3674                 :             :                 /* If we produced const TRUE, just drop the clause */
    3675   [ +  -  +  + ]:          22 :                 if (clause && IsA(clause, Const))
    3676                 :             :                 {
    3677                 :          21 :                         Const      *cclause = (Const *) clause;
    3678                 :             : 
    3679         [ +  - ]:          21 :                         Assert(cclause->consttype == BOOLOID);
    3680   [ +  -  +  - ]:          21 :                         if (!cclause->constisnull && DatumGetBool(cclause->constvalue))
    3681                 :           0 :                                 return NULL;
    3682         [ -  + ]:          21 :                 }
    3683                 :          22 :         }
    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                 :        2942 :         relids = pull_varnos(root, clause);
    3693         [ +  - ]:        2942 :         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         [ +  + ]:        2942 :         if (bms_is_empty(relids))
    3702                 :             :         {
    3703                 :             :                 /* eval at join domain's safe level */
    3704                 :          22 :                 relids = get_join_domain_min_rels(root, qualscope);
    3705                 :             :                 /* mark as gating qual */
    3706                 :          22 :                 pseudoconstant = true;
    3707                 :             :                 /* tell createplan.c to check for gating quals */
    3708                 :          22 :                 root->hasPseudoConstantQuals = true;
    3709                 :          22 :         }
    3710                 :             : 
    3711                 :             :         /*
    3712                 :             :          * Build the RestrictInfo node itself.
    3713                 :             :          */
    3714                 :        5884 :         restrictinfo = make_restrictinfo(root,
    3715                 :        2942 :                                                                          (Expr *) clause,
    3716                 :             :                                                                          true,  /* is_pushed_down */
    3717                 :             :                                                                          false, /* !has_clone */
    3718                 :             :                                                                          false, /* !is_clone */
    3719                 :        2942 :                                                                          pseudoconstant,
    3720                 :        2942 :                                                                          security_level,
    3721                 :        2942 :                                                                          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         [ +  + ]:        2942 :         if (bms_membership(relids) == BMS_MULTIPLE)
    3742                 :             :         {
    3743                 :          10 :                 List       *vars = pull_var_clause(clause,
    3744                 :             :                                                                                    PVC_RECURSE_AGGREGATES |
    3745                 :             :                                                                                    PVC_RECURSE_WINDOWFUNCS |
    3746                 :             :                                                                                    PVC_INCLUDE_PLACEHOLDERS);
    3747                 :             : 
    3748                 :          10 :                 add_vars_to_targetlist(root, vars, relids);
    3749                 :          10 :                 list_free(vars);
    3750                 :          10 :         }
    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                 :        2942 :         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                 :        2942 :         distribute_restrictinfo_to_rels(root, restrictinfo);
    3769                 :             : 
    3770                 :        2942 :         return restrictinfo;
    3771                 :        2942 : }
    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                 :        8375 : 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                 :        8375 :         RestrictInfo *restrictinfo;
    3796                 :        8375 :         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                 :       16750 :         clause = make_opclause(opno,
    3803                 :             :                                                    BOOLOID, /* opresulttype */
    3804                 :             :                                                    false,       /* opretset */
    3805                 :        8375 :                                                    copyObject(item1),
    3806                 :        8375 :                                                    copyObject(item2),
    3807                 :             :                                                    InvalidOid,
    3808                 :        8375 :                                                    collation);
    3809                 :             : 
    3810                 :             :         /*
    3811                 :             :          * Build the RestrictInfo node itself.
    3812                 :             :          */
    3813                 :       16750 :         restrictinfo = make_restrictinfo(root,
    3814                 :        8375 :                                                                          clause,
    3815                 :             :                                                                          true,  /* is_pushed_down */
    3816                 :             :                                                                          false, /* !has_clone */
    3817                 :             :                                                                          false, /* !is_clone */
    3818                 :             :                                                                          false, /* pseudoconstant */
    3819                 :        8375 :                                                                          security_level,        /* security_level */
    3820                 :        8375 :                                                                          qualscope, /* required_relids */
    3821                 :             :                                                                          NULL,  /* incompatible_relids */
    3822                 :             :                                                                          NULL); /* outer_relids */
    3823                 :             : 
    3824                 :             :         /* Set mergejoinability/hashjoinability flags */
    3825                 :        8375 :         check_mergejoinable(restrictinfo);
    3826                 :        8375 :         check_hashjoinable(restrictinfo);
    3827                 :        8375 :         check_memoizable(restrictinfo);
    3828                 :             : 
    3829                 :       16750 :         return restrictinfo;
    3830                 :        8375 : }
    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                 :          22 : get_join_domain_min_rels(PlannerInfo *root, Relids domain_relids)
    3857                 :             : {
    3858                 :          22 :         Relids          result = bms_copy(domain_relids);
    3859                 :          22 :         ListCell   *lc;
    3860                 :             : 
    3861                 :             :         /* Top-level join domain? */
    3862         [ +  + ]:          22 :         if (bms_equal(result, root->all_query_rels))
    3863                 :          11 :                 return result;
    3864                 :             : 
    3865                 :             :         /* Nope, look for lower outer joins that could potentially commute out */
    3866   [ +  -  +  +  :          23 :         foreach(lc, root->join_info_list)
                   +  + ]
    3867                 :             :         {
    3868                 :          12 :                 SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
    3869                 :             : 
    3870   [ +  -  +  + ]:          12 :                 if (sjinfo->jointype == JOIN_LEFT &&
    3871                 :          12 :                         bms_is_member(sjinfo->ojrelid, result))
    3872                 :             :                 {
    3873                 :           1 :                         result = bms_del_member(result, sjinfo->ojrelid);
    3874                 :           1 :                         result = bms_del_members(result, sjinfo->syn_righthand);
    3875                 :           1 :                 }
    3876                 :          12 :         }
    3877                 :          11 :         return result;
    3878                 :          22 : }
    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                 :        1193 : 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                 :        1193 :         Bitmapset  *seen_serials = NULL;
    3901                 :        1193 :         Index           rti;
    3902                 :             : 
    3903                 :             :         /* Scan all baserels for join clauses */
    3904         [ +  + ]:        7446 :         for (rti = 1; rti < root->simple_rel_array_size; rti++)
    3905                 :             :         {
    3906                 :        6253 :                 RelOptInfo *brel = root->simple_rel_array[rti];
    3907                 :        6253 :                 ListCell   *lc;
    3908                 :             : 
    3909         [ +  + ]:        6253 :                 if (brel == NULL)
    3910                 :        4132 :                         continue;
    3911         [ -  + ]:        2121 :                 if (brel->reloptkind != RELOPT_BASEREL)
    3912                 :           0 :                         continue;
    3913                 :             : 
    3914   [ +  +  +  +  :        3534 :                 foreach(lc, brel->joininfo)
                   +  + ]
    3915                 :             :                 {
    3916                 :        1413 :                         RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    3917                 :        1413 :                         Relids          relids = rinfo->required_relids;
    3918                 :             : 
    3919         [ +  + ]:        1413 :                         if (!rinfo->is_clone)        /* else serial number is not unique */
    3920                 :             :                         {
    3921         [ +  + ]:        1397 :                                 if (bms_is_member(rinfo->rinfo_serial, seen_serials))
    3922                 :         758 :                                         continue;       /* saw it already */
    3923                 :        1278 :                                 seen_serials = bms_add_member(seen_serials,
    3924                 :         639 :                                                                                           rinfo->rinfo_serial);
    3925                 :         639 :                         }
    3926                 :             : 
    3927         [ -  + ]:         655 :                         if (bms_membership(relids) == BMS_MULTIPLE)
    3928                 :             :                         {
    3929                 :         655 :                                 List       *vars = pull_var_clause((Node *) rinfo->clause,
    3930                 :             :                                                                                                    PVC_RECURSE_AGGREGATES |
    3931                 :             :                                                                                                    PVC_RECURSE_WINDOWFUNCS |
    3932                 :             :                                                                                                    PVC_INCLUDE_PLACEHOLDERS);
    3933                 :         655 :                                 Relids          where_needed;
    3934                 :             : 
    3935         [ +  + ]:         655 :                                 if (rinfo->is_clone)
    3936                 :          16 :                                         where_needed = bms_intersect(relids, root->all_baserels);
    3937                 :             :                                 else
    3938                 :         639 :                                         where_needed = relids;
    3939                 :         655 :                                 add_vars_to_attr_needed(root, vars, where_needed);
    3940                 :         655 :                                 list_free(vars);
    3941                 :         655 :                         }
    3942         [ +  + ]:        1413 :                 }
    3943         [ +  + ]:        6253 :         }
    3944                 :        1193 : }
    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                 :       33901 : match_foreign_keys_to_quals(PlannerInfo *root)
    3963                 :             : {
    3964                 :       33901 :         List       *newlist = NIL;
    3965                 :       33901 :         ListCell   *lc;
    3966                 :             : 
    3967   [ +  +  +  +  :       34190 :         foreach(lc, root->fkey_list)
                   +  + ]
    3968                 :             :         {
    3969                 :         289 :                 ForeignKeyOptInfo *fkinfo = (ForeignKeyOptInfo *) lfirst(lc);
    3970                 :         289 :                 RelOptInfo *con_rel;
    3971                 :         289 :                 RelOptInfo *ref_rel;
    3972                 :         289 :                 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   [ +  -  -  + ]:         289 :                 if (fkinfo->con_relid >= root->simple_rel_array_size ||
    3981                 :         289 :                         fkinfo->ref_relid >= root->simple_rel_array_size)
    3982                 :           0 :                         continue;                       /* just paranoia */
    3983                 :         289 :                 con_rel = root->simple_rel_array[fkinfo->con_relid];
    3984         [ +  + ]:         289 :                 if (con_rel == NULL)
    3985                 :           2 :                         continue;
    3986                 :         287 :                 ref_rel = root->simple_rel_array[fkinfo->ref_relid];
    3987         [ +  + ]:         287 :                 if (ref_rel == NULL)
    3988                 :           4 :                         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   [ +  -  -  + ]:         283 :                 if (con_rel->reloptkind != RELOPT_BASEREL ||
    3995                 :         283 :                         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         [ +  + ]:         652 :                 for (colno = 0; colno < fkinfo->nkeys; colno++)
    4007                 :             :                 {
    4008                 :         369 :                         EquivalenceClass *ec;
    4009                 :         369 :                         AttrNumber      con_attno,
    4010                 :             :                                                 ref_attno;
    4011                 :         369 :                         Oid                     fpeqop;
    4012                 :         369 :                         ListCell   *lc2;
    4013                 :             : 
    4014                 :         369 :                         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         [ +  + ]:         369 :                         if (ec != NULL)
    4017                 :             :                         {
    4018                 :          95 :                                 fkinfo->nmatched_ec++;
    4019         [ +  + ]:          95 :                                 if (ec->ec_has_const)
    4020                 :           4 :                                         fkinfo->nconst_ec++;
    4021                 :          95 :                                 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                 :         274 :                         con_attno = fkinfo->conkey[colno];
    4029                 :         274 :                         ref_attno = fkinfo->confkey[colno];
    4030                 :         274 :                         fpeqop = InvalidOid;    /* we'll look this up only if needed */
    4031                 :             : 
    4032   [ +  +  +  +  :         746 :                         foreach(lc2, con_rel->joininfo)
                   +  + ]
    4033                 :             :                         {
    4034                 :         472 :                                 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc2);
    4035                 :         472 :                                 OpExpr     *clause = (OpExpr *) rinfo->clause;
    4036                 :         472 :                                 Var                *leftvar;
    4037                 :         472 :                                 Var                *rightvar;
    4038                 :             : 
    4039                 :             :                                 /* Only binary OpExprs are useful for consideration */
    4040   [ +  +  -  + ]:         472 :                                 if (!IsA(clause, OpExpr) ||
    4041                 :         460 :                                         list_length(clause->args) != 2)
    4042                 :          12 :                                         continue;
    4043                 :         460 :                                 leftvar = (Var *) get_leftop((Expr *) clause);
    4044                 :         460 :                                 rightvar = (Var *) get_rightop((Expr *) clause);
    4045                 :             : 
    4046                 :             :                                 /* Operands must be Vars, possibly with RelabelType */
    4047   [ -  +  +  + ]:         501 :                                 while (leftvar && IsA(leftvar, RelabelType))
    4048                 :          41 :                                         leftvar = (Var *) ((RelabelType *) leftvar)->arg;
    4049   [ +  -  +  + ]:         460 :                                 if (!(leftvar && IsA(leftvar, Var)))
    4050                 :          12 :                                         continue;
    4051   [ -  +  +  + ]:         486 :                                 while (rightvar && IsA(rightvar, RelabelType))
    4052                 :          38 :                                         rightvar = (Var *) ((RelabelType *) rightvar)->arg;
    4053   [ +  -  +  + ]:         448 :                                 if (!(rightvar && IsA(rightvar, Var)))
    4054                 :           5 :                                         continue;
    4055                 :             : 
    4056                 :             :                                 /* Now try to match the vars to the current foreign key cols */
    4057         [ +  + ]:         443 :                                 if (fkinfo->ref_relid == leftvar->varno &&
    4058         [ +  + ]:         422 :                                         ref_attno == leftvar->varattno &&
    4059   [ +  -  +  + ]:         221 :                                         fkinfo->con_relid == rightvar->varno &&
    4060                 :         221 :                                         con_attno == rightvar->varattno)
    4061                 :             :                                 {
    4062                 :             :                                         /* Vars match, but is it the right operator? */
    4063         [ -  + ]:         208 :                                         if (clause->opno == fkinfo->conpfeqop[colno])
    4064                 :             :                                         {
    4065                 :         416 :                                                 fkinfo->rinfos[colno] = lappend(fkinfo->rinfos[colno],
    4066                 :         208 :                                                                                                                 rinfo);
    4067                 :         208 :                                                 fkinfo->nmatched_ri++;
    4068                 :         208 :                                         }
    4069                 :         208 :                                 }
    4070         [ +  + ]:         235 :                                 else if (fkinfo->ref_relid == rightvar->varno &&
    4071         [ +  + ]:          15 :                                                  ref_attno == rightvar->varattno &&
    4072   [ +  -  -  + ]:           6 :                                                  fkinfo->con_relid == leftvar->varno &&
    4073                 :           6 :                                                  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         [ -  + ]:           6 :                                         if (!OidIsValid(fpeqop))
    4083                 :           6 :                                                 fpeqop = get_commutator(fkinfo->conpfeqop[colno]);
    4084         [ -  + ]:           6 :                                         if (clause->opno == fpeqop)
    4085                 :             :                                         {
    4086                 :          12 :                                                 fkinfo->rinfos[colno] = lappend(fkinfo->rinfos[colno],
    4087                 :           6 :                                                                                                                 rinfo);
    4088                 :           6 :                                                 fkinfo->nmatched_ri++;
    4089                 :           6 :                                         }
    4090                 :           6 :                                 }
    4091         [ +  + ]:         472 :                         }
    4092                 :             :                         /* If we found any matching loose quals, count col as matched */
    4093         [ +  + ]:         274 :                         if (fkinfo->rinfos[colno])
    4094                 :         214 :                                 fkinfo->nmatched_rcols++;
    4095         [ +  + ]:         369 :                 }
    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         [ +  + ]:         283 :                 if ((fkinfo->nmatched_ec + fkinfo->nmatched_rcols) == fkinfo->nkeys)
    4104                 :         227 :                         newlist = lappend(newlist, fkinfo);
    4105         [ +  + ]:         289 :         }
    4106                 :             :         /* Replace fkey_list, thereby discarding any useless entries */
    4107                 :       33901 :         root->fkey_list = newlist;
    4108                 :       33901 : }
    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                 :       61018 : check_mergejoinable(RestrictInfo *restrictinfo)
    4128                 :             : {
    4129                 :       61018 :         Expr       *clause = restrictinfo->clause;
    4130                 :       61018 :         Oid                     opno;
    4131                 :       61018 :         Node       *leftarg;
    4132                 :             : 
    4133         [ +  + ]:       61018 :         if (restrictinfo->pseudoconstant)
    4134                 :        1770 :                 return;
    4135         [ +  + ]:       59248 :         if (!is_opclause(clause))
    4136                 :        6537 :                 return;
    4137         [ +  + ]:       52711 :         if (list_length(((OpExpr *) clause)->args) != 2)
    4138                 :           4 :                 return;
    4139                 :             : 
    4140                 :       52707 :         opno = ((OpExpr *) clause)->opno;
    4141                 :       52707 :         leftarg = linitial(((OpExpr *) clause)->args);
    4142                 :             : 
    4143   [ +  +  +  + ]:       52707 :         if (op_mergejoinable(opno, exprType(leftarg)) &&
    4144                 :       44054 :                 !contain_volatile_functions((Node *) restrictinfo))
    4145                 :       44049 :                 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         [ -  + ]:       61018 : }
    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                 :       14501 : check_hashjoinable(RestrictInfo *restrictinfo)
    4165                 :             : {
    4166                 :       14501 :         Expr       *clause = restrictinfo->clause;
    4167                 :       14501 :         Oid                     opno;
    4168                 :       14501 :         Node       *leftarg;
    4169                 :             : 
    4170         [ +  + ]:       14501 :         if (restrictinfo->pseudoconstant)
    4171                 :         556 :                 return;
    4172         [ +  + ]:       13945 :         if (!is_opclause(clause))
    4173                 :         508 :                 return;
    4174         [ -  + ]:       13437 :         if (list_length(((OpExpr *) clause)->args) != 2)
    4175                 :           0 :                 return;
    4176                 :             : 
    4177                 :       13437 :         opno = ((OpExpr *) clause)->opno;
    4178                 :       13437 :         leftarg = linitial(((OpExpr *) clause)->args);
    4179                 :             : 
    4180   [ +  +  +  + ]:       13437 :         if (op_hashjoinable(opno, exprType(leftarg)) &&
    4181                 :       13085 :                 !contain_volatile_functions((Node *) restrictinfo))
    4182                 :       13084 :                 restrictinfo->hashjoinoperator = opno;
    4183         [ -  + ]:       14501 : }
    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                 :       14501 : check_memoizable(RestrictInfo *restrictinfo)
    4193                 :             : {
    4194                 :       14501 :         TypeCacheEntry *typentry;
    4195                 :       14501 :         Expr       *clause = restrictinfo->clause;
    4196                 :       14501 :         Oid                     lefttype;
    4197                 :       14501 :         Oid                     righttype;
    4198                 :             : 
    4199         [ +  + ]:       14501 :         if (restrictinfo->pseudoconstant)
    4200                 :         556 :                 return;
    4201         [ +  + ]:       13945 :         if (!is_opclause(clause))
    4202                 :         508 :                 return;
    4203         [ -  + ]:       13437 :         if (list_length(((OpExpr *) clause)->args) != 2)
    4204                 :           0 :                 return;
    4205                 :             : 
    4206                 :       13437 :         lefttype = exprType(linitial(((OpExpr *) clause)->args));
    4207                 :             : 
    4208                 :       13437 :         typentry = lookup_type_cache(lefttype, TYPECACHE_HASH_PROC |
    4209                 :             :                                                                  TYPECACHE_EQ_OPR);
    4210                 :             : 
    4211   [ +  +  -  + ]:       13437 :         if (OidIsValid(typentry->hash_proc) && OidIsValid(typentry->eq_opr))
    4212                 :       13369 :                 restrictinfo->left_hasheqoperator = typentry->eq_opr;
    4213                 :             : 
    4214                 :       13437 :         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         [ +  + ]:       13437 :         if (lefttype != righttype)
    4221                 :         206 :                 typentry = lookup_type_cache(righttype, TYPECACHE_HASH_PROC |
    4222                 :             :                                                                          TYPECACHE_EQ_OPR);
    4223                 :             : 
    4224   [ +  +  -  + ]:       13437 :         if (OidIsValid(typentry->hash_proc) && OidIsValid(typentry->eq_opr))
    4225                 :       13335 :                 restrictinfo->right_hasheqoperator = typentry->eq_opr;
    4226         [ -  + ]:       14501 : }
        

Generated by: LCOV version 2.3.2-1