LCOV - code coverage report
Current view: top level - src/backend/optimizer/plan - analyzejoins.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 94.9 % 602 571
Test Date: 2026-10-15 23:15:58 Functions: 100.0 % 26 26
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 83.6 % 584 488

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * analyzejoins.c
       4                 :             :  *    Routines for simplifying joins after initial query analysis
       5                 :             :  *
       6                 :             :  * While we do a great deal of join simplification in prep/prepjointree.c,
       7                 :             :  * certain optimizations cannot be performed at that stage for lack of
       8                 :             :  * detailed information about the query.  The routines here are invoked
       9                 :             :  * after initsplan.c has done its work, and can do additional join removal
      10                 :             :  * and simplification steps based on the information extracted.
      11                 :             :  *
      12                 :             :  * Although the decisions about what can be removed are made using the
      13                 :             :  * planner's derived data structures, the removals themselves are implemented
      14                 :             :  * by editing the query's jointree, which is a far simpler and more stable
      15                 :             :  * representation.  We make no attempt to update the derived data structures
      16                 :             :  * to match; instead, query_planner() throws them all away and recomputes them
      17                 :             :  * whenever we report having removed something.
      18                 :             :  *
      19                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      20                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
      21                 :             :  *
      22                 :             :  *
      23                 :             :  * IDENTIFICATION
      24                 :             :  *    src/backend/optimizer/plan/analyzejoins.c
      25                 :             :  *
      26                 :             :  *-------------------------------------------------------------------------
      27                 :             :  */
      28                 :             : #include "postgres.h"
      29                 :             : 
      30                 :             : #include "catalog/pg_class.h"
      31                 :             : #include "nodes/makefuncs.h"
      32                 :             : #include "nodes/nodeFuncs.h"
      33                 :             : #include "optimizer/optimizer.h"
      34                 :             : #include "optimizer/pathnode.h"
      35                 :             : #include "optimizer/paths.h"
      36                 :             : #include "optimizer/planmain.h"
      37                 :             : #include "optimizer/prep.h"
      38                 :             : #include "optimizer/restrictinfo.h"
      39                 :             : #include "parser/parse_agg.h"
      40                 :             : #include "parser/parse_relation.h"
      41                 :             : #include "rewrite/rewriteManip.h"
      42                 :             : #include "utils/lsyscache.h"
      43                 :             : 
      44                 :             : /*
      45                 :             :  * Utility structure.  A sorting procedure is needed to simplify the search
      46                 :             :  * for SJE-candidate baserels, which must reference the same database relation
      47                 :             :  * with the same reader permissions (checkAsUser value).  We require the
      48                 :             :  * checkAsUser fields to match to ensure that merged RTEs carry the same
      49                 :             :  * securityQuals; in future this rule might keep us out of trouble with other
      50                 :             :  * role-based features, too.  Having collected all baserels from the jointree,
      51                 :             :  * remove_self_joins_recurse sorts them according to their reloid and useroid
      52                 :             :  * values, groups them in another pass and attempts to remove self-joins
      53                 :             :  * within each group.  This preliminary sorting prevents quadratic behavior
      54                 :             :  * in the case of numerous joins.
      55                 :             :  */
      56                 :             : typedef struct
      57                 :             : {
      58                 :             :     int         relid;
      59                 :             :     Oid         reloid;
      60                 :             :     Oid         useroid;
      61                 :             : } SelfJoinCandidate;
      62                 :             : 
      63                 :             : bool        enable_self_join_elimination;
      64                 :             : 
      65                 :             : /* local functions */
      66                 :             : static bool join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo);
      67                 :             : static Node *remove_join_from_jointree(Node *jtnode, int ojrelid,
      68                 :             :                                        int *nremoved);
      69                 :             : static void remove_rels_from_query_tree(PlannerInfo *root,
      70                 :             :                                         Relids removed_relids);
      71                 :             : static bool reduce_semijoin_in_jointree(Node *jtnode, Relids syn_righthand);
      72                 :             : static bool rel_supports_distinctness(PlannerInfo *root, RelOptInfo *rel);
      73                 :             : static bool rel_is_distinct_for(PlannerInfo *root, RelOptInfo *rel,
      74                 :             :                                 List *clause_list, List **extra_clauses);
      75                 :             : static DistinctColInfo *distinct_col_search(int colno, List *distinct_cols);
      76                 :             : static bool innerrel_is_unique_ext(PlannerInfo *root,
      77                 :             :                                    Relids joinrelids,
      78                 :             :                                    Relids outerrelids,
      79                 :             :                                    RelOptInfo *innerrel,
      80                 :             :                                    JoinType jointype,
      81                 :             :                                    List *restrictlist,
      82                 :             :                                    bool force_cache,
      83                 :             :                                    List **extra_clauses);
      84                 :             : static bool is_innerrel_unique_for(PlannerInfo *root,
      85                 :             :                                    Relids joinrelids,
      86                 :             :                                    Relids outerrelids,
      87                 :             :                                    RelOptInfo *innerrel,
      88                 :             :                                    JoinType jointype,
      89                 :             :                                    List *restrictlist,
      90                 :             :                                    List **extra_clauses);
      91                 :             : static Node *remove_rel_from_jointree(Node *jtnode, int relid,
      92                 :             :                                       Node **orphan_quals, int *nremoved);
      93                 :             : static Node *merge_quals(Node *quals1, Node *quals2);
      94                 :             : static void fixup_selfjoin_jointree(PlannerInfo *root, Node *jtnode, int relid,
      95                 :             :                                     Node **hoist_quals, bool *found_relid);
      96                 :             : static List *fixup_selfjoin_quals(PlannerInfo *root, List *quals, int relid);
      97                 :             : static Node *replace_selfjoin_qual(Node *qual);
      98                 :             : static int  self_join_candidates_cmp(const void *a, const void *b);
      99                 :             : 
     100                 :             : 
     101                 :             : /*
     102                 :             :  * remove_useless_outer_joins
     103                 :             :  *      Check for relations that don't actually need to be joined at all,
     104                 :             :  *      and remove them from the query's jointree.
     105                 :             :  *
     106                 :             :  * Returns true if we removed anything.  In that case the caller must discard
     107                 :             :  * everything it has derived from the jointree and compute it over again,
     108                 :             :  * since we don't try to update any of that here.
     109                 :             :  */
     110                 :             : bool
     111                 :      255125 : remove_useless_outer_joins(PlannerInfo *root)
     112                 :             : {
     113                 :      255125 :     Relids      removed_relids = NULL;
     114                 :             :     ListCell   *lc;
     115                 :             : 
     116                 :             :     /*
     117                 :             :      * We are only interested in relations that are left-joined to, so we can
     118                 :             :      * scan the join_info_list to find them easily.
     119                 :             :      */
     120   [ +  +  +  +  :      304191 :     foreach(lc, root->join_info_list)
                   +  + ]
     121                 :             :     {
     122                 :       49066 :         SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
     123                 :             :         int         innerrelid;
     124                 :             :         int         nremoved;
     125                 :             :         RangeTblEntry *rte;
     126                 :             : 
     127                 :             :         /* Skip if not removable */
     128         [ +  + ]:       49066 :         if (!join_is_removable(root, sjinfo))
     129                 :       40397 :             continue;
     130                 :             : 
     131                 :             :         /*
     132                 :             :          * join_is_removable insists that the join's syntactic righthand side
     133                 :             :          * be a single baserel, so we can implement the removal by dropping
     134                 :             :          * the JoinExpr and everything below its righthand side.
     135                 :             :          */
     136                 :        8669 :         innerrelid = bms_singleton_member(sjinfo->syn_righthand);
     137                 :             : 
     138                 :             :         /* We verify that exactly one JoinExpr gets removed */
     139                 :        8669 :         nremoved = 0;
     140                 :       17338 :         root->parse->jointree = (FromExpr *)
     141                 :        8669 :             remove_join_from_jointree((Node *) root->parse->jointree,
     142                 :        8669 :                                       sjinfo->ojrelid, &nremoved);
     143         [ -  + ]:        8669 :         if (nremoved != 1)
     144         [ #  # ]:           0 :             elog(ERROR, "failed to find join %d in jointree", sjinfo->ojrelid);
     145                 :             : 
     146                 :             :         /* Track all the relids we've removed, for use below */
     147                 :        8669 :         removed_relids = bms_add_member(removed_relids, innerrelid);
     148                 :        8669 :         removed_relids = bms_add_member(removed_relids, sjinfo->ojrelid);
     149                 :             : 
     150                 :             :         /*
     151                 :             :          * As in pull_up_simple_subquery, discard no-longer-needed subqueries.
     152                 :             :          * This is not just an optimization, but is necessary to prevent
     153                 :             :          * subsequent processing from descending into stale subtrees and
     154                 :             :          * seeing inconsistent data.  For the same reason, discard any
     155                 :             :          * tablesample and securityQuals subtrees of the removed rel.
     156                 :             :          * (Although simple_rte_array[] will be rebuilt shortly, we can still
     157                 :             :          * use it to find the RTE in the parse tree.)
     158                 :             :          */
     159                 :        8669 :         rte = root->simple_rte_array[innerrelid];
     160         [ +  + ]:        8669 :         if (rte->rtekind == RTE_SUBQUERY)
     161                 :         193 :             rte->subquery = NULL;
     162                 :        8669 :         rte->tablesample = NULL;
     163                 :        8669 :         rte->securityQuals = NIL;
     164                 :             : 
     165                 :             :         /*
     166                 :             :          * It's okay to keep scanning join_info_list for more removable joins,
     167                 :             :          * even though the data that join_is_removable consults is now
     168                 :             :          * slightly out of date.  Removing a join can only delete attr_needed
     169                 :             :          * bits and join clauses, and any attr_needed bit or join clause that
     170                 :             :          * mentions the removed rel above its own join level would have
     171                 :             :          * prevented that rel from being removable.  So what remains to be
     172                 :             :          * examined is unchanged by what we just did.
     173                 :             :          *
     174                 :             :          * The converse doesn't hold: dropping a join can make some other join
     175                 :             :          * removable that didn't look so before.  That's why our caller loops
     176                 :             :          * until we report finding nothing more to remove.
     177                 :             :          */
     178                 :             :     }
     179                 :             : 
     180         [ +  + ]:      255125 :     if (bms_is_empty(removed_relids))
     181                 :      247170 :         return false;
     182                 :             : 
     183                 :             :     /* Clean up the traces that the removed rels have left elsewhere */
     184                 :        7955 :     remove_rels_from_query_tree(root, removed_relids);
     185                 :             : 
     186                 :        7955 :     return true;
     187                 :             : }
     188                 :             : 
     189                 :             : /*
     190                 :             :  * join_is_removable
     191                 :             :  *    Check whether we need not perform this special join at all, because
     192                 :             :  *    it will just duplicate its left input.
     193                 :             :  *
     194                 :             :  * This is true for a left join for which the join condition cannot match
     195                 :             :  * more than one inner-side row.  (There are other possibly interesting
     196                 :             :  * cases, but we don't have the infrastructure to prove them.)  We also
     197                 :             :  * have to check that the inner side doesn't generate any variables needed
     198                 :             :  * above the join.
     199                 :             :  */
     200                 :             : static bool
     201                 :       49066 : join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo)
     202                 :             : {
     203                 :             :     int         innerrelid;
     204                 :             :     RelOptInfo *innerrel;
     205                 :             :     Relids      inputrelids;
     206                 :             :     Relids      joinrelids;
     207                 :       49066 :     List       *clause_list = NIL;
     208                 :             :     ListCell   *l;
     209                 :             :     int         attroff;
     210                 :             : 
     211                 :             :     /*
     212                 :             :      * Must be a left join to a single baserel, else we aren't going to be
     213                 :             :      * able to do anything with it.
     214                 :             :      */
     215         [ +  + ]:       49066 :     if (sjinfo->jointype != JOIN_LEFT)
     216                 :       13650 :         return false;
     217                 :             : 
     218                 :             :     /*
     219                 :             :      * We test the syntactic righthand side, not min_righthand, because the
     220                 :             :      * removal is done by deleting the whole righthand subtree of the join.
     221                 :             :      * (min_righthand can be a singleton when syn_righthand is not, but in
     222                 :             :      * such a case the attr_needed tests below would reject the join anyway.)
     223                 :             :      */
     224         [ +  + ]:       35416 :     if (!bms_get_singleton_member(sjinfo->syn_righthand, &innerrelid))
     225                 :        1634 :         return false;
     226                 :             :     Assert(bms_equal(sjinfo->min_righthand, sjinfo->syn_righthand));
     227                 :             : 
     228                 :             :     /*
     229                 :             :      * Never try to eliminate a left join to the query result rel.  Although
     230                 :             :      * the case is syntactically impossible in standard SQL, MERGE will build
     231                 :             :      * a join tree that looks exactly like that.
     232                 :             :      */
     233         [ +  + ]:       33782 :     if (innerrelid == root->parse->resultRelation)
     234                 :         636 :         return false;
     235                 :             : 
     236                 :       33146 :     innerrel = find_base_rel(root, innerrelid);
     237                 :             : 
     238                 :             :     /*
     239                 :             :      * Before we go to the effort of checking whether any innerrel variables
     240                 :             :      * are needed above the join, make a quick check to eliminate cases in
     241                 :             :      * which we will surely be unable to prove uniqueness of the innerrel.
     242                 :             :      */
     243         [ +  + ]:       33146 :     if (!rel_supports_distinctness(root, innerrel))
     244                 :        2754 :         return false;
     245                 :             : 
     246                 :             :     /* Compute the relid set for the join we are considering */
     247                 :       30392 :     inputrelids = bms_union(sjinfo->min_lefthand, sjinfo->min_righthand);
     248                 :             :     Assert(sjinfo->ojrelid != 0);
     249                 :       30392 :     joinrelids = bms_copy(inputrelids);
     250                 :       30392 :     joinrelids = bms_add_member(joinrelids, sjinfo->ojrelid);
     251                 :             : 
     252                 :             :     /*
     253                 :             :      * We can't remove the join if any inner-rel attributes are used above the
     254                 :             :      * join.  Here, "above" the join includes pushed-down conditions, so we
     255                 :             :      * should reject if attr_needed includes the OJ's own relid; therefore,
     256                 :             :      * compare to inputrelids not joinrelids.
     257                 :             :      *
     258                 :             :      * As a micro-optimization, it seems better to start with max_attr and
     259                 :             :      * count down rather than starting with min_attr and counting up, on the
     260                 :             :      * theory that the system attributes are somewhat less likely to be wanted
     261                 :             :      * and should be tested last.
     262                 :             :      */
     263                 :       30392 :     for (attroff = innerrel->max_attr - innerrel->min_attr;
     264         [ +  + ]:      277305 :          attroff >= 0;
     265                 :      246913 :          attroff--)
     266                 :             :     {
     267         [ +  + ]:      268337 :         if (!bms_is_subset(innerrel->attr_needed[attroff], inputrelids))
     268                 :       21424 :             return false;
     269                 :             :     }
     270                 :             : 
     271                 :             :     /*
     272                 :             :      * Similarly check that the inner rel isn't needed by any PlaceHolderVars
     273                 :             :      * that will be used above the join.  The PHV case is a little bit more
     274                 :             :      * complicated, because PHVs may have been assigned a ph_eval_at location
     275                 :             :      * that includes the innerrel, yet their contained expression might not
     276                 :             :      * actually reference the innerrel (it could be just a constant, for
     277                 :             :      * instance).  If such a PHV is due to be evaluated above the join then it
     278                 :             :      * needn't prevent join removal.
     279                 :             :      */
     280   [ +  +  +  +  :        9189 :     foreach(l, root->placeholder_list)
                   +  + ]
     281                 :             :     {
     282                 :         251 :         PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(l);
     283                 :             : 
     284         [ -  + ]:         251 :         if (bms_overlap(phinfo->ph_lateral, innerrel->relids))
     285                 :          30 :             return false;       /* it references innerrel laterally */
     286         [ +  + ]:         251 :         if (!bms_overlap(phinfo->ph_eval_at, innerrel->relids))
     287                 :          91 :             continue;           /* it definitely doesn't reference innerrel */
     288         [ -  + ]:         160 :         if (bms_is_subset(phinfo->ph_needed, inputrelids))
     289                 :           0 :             continue;           /* PHV is not used above the join */
     290         [ +  + ]:         160 :         if (!bms_is_member(sjinfo->ojrelid, phinfo->ph_eval_at))
     291                 :          25 :             return false;       /* it has to be evaluated below the join */
     292                 :             : 
     293                 :             :         /*
     294                 :             :          * We need to be sure there will still be a place to evaluate the PHV
     295                 :             :          * if we remove the join, ie that ph_eval_at wouldn't become empty.
     296                 :             :          */
     297         [ +  + ]:         135 :         if (!bms_overlap(sjinfo->min_lefthand, phinfo->ph_eval_at))
     298                 :           5 :             return false;       /* there isn't any other place to eval PHV */
     299                 :             :         /* Check contained expression last, since this is a bit expensive */
     300         [ -  + ]:         130 :         if (bms_overlap(pull_varnos(root, (Node *) phinfo->ph_var->phexpr),
     301                 :         130 :                         innerrel->relids))
     302                 :           0 :             return false;       /* contained expression references innerrel */
     303                 :             :     }
     304                 :             : 
     305                 :             :     /*
     306                 :             :      * Search for mergejoinable clauses that constrain the inner rel against
     307                 :             :      * either the outer rel or a pseudoconstant.  If an operator is
     308                 :             :      * mergejoinable then it behaves like equality for some btree opclass, so
     309                 :             :      * it's what we want.  The mergejoinability test also eliminates clauses
     310                 :             :      * containing volatile functions, which we couldn't depend on.
     311                 :             :      */
     312   [ +  +  +  +  :       18055 :     foreach(l, innerrel->joininfo)
                   +  + ]
     313                 :             :     {
     314                 :        9117 :         RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
     315                 :             : 
     316                 :             :         /*
     317                 :             :          * If the current join commutes with some other outer join(s) via
     318                 :             :          * outer join identity 3, there will be multiple clones of its join
     319                 :             :          * clauses in the joininfo list.  We want to consider only the
     320                 :             :          * has_clone form of such clauses.  Processing more than one form
     321                 :             :          * would be wasteful, and also some of the others would confuse the
     322                 :             :          * RINFO_IS_PUSHED_DOWN test below.
     323                 :             :          */
     324         [ +  + ]:        9117 :         if (restrictinfo->is_clone)
     325                 :          87 :             continue;           /* ignore it */
     326                 :             : 
     327                 :             :         /*
     328                 :             :          * If it's not a join clause for this outer join, we can't use it.
     329                 :             :          * Note that if the clause is pushed-down, then it is logically from
     330                 :             :          * above the outer join, even if it references no other rels (it might
     331                 :             :          * be from WHERE, for example).
     332                 :             :          */
     333   [ +  +  +  + ]:        9030 :         if (RINFO_IS_PUSHED_DOWN(restrictinfo, joinrelids))
     334                 :         125 :             continue;           /* ignore; not useful here */
     335                 :             : 
     336                 :             :         /* Ignore if it's not a mergejoinable clause */
     337         [ +  + ]:        8905 :         if (!restrictinfo->can_join ||
     338         [ -  + ]:        8740 :             restrictinfo->mergeopfamilies == NIL)
     339                 :         165 :             continue;           /* not mergejoinable */
     340                 :             : 
     341                 :             :         /*
     342                 :             :          * Check if the clause has the form "outer op inner" or "inner op
     343                 :             :          * outer", and if so mark which side is inner.
     344                 :             :          */
     345         [ +  + ]:        8740 :         if (!clause_sides_match_join(restrictinfo, sjinfo->min_lefthand,
     346                 :             :                                      innerrel->relids))
     347                 :           5 :             continue;           /* no good for these input relations */
     348                 :             : 
     349                 :             :         /* OK, add to list */
     350                 :        8735 :         clause_list = lappend(clause_list, restrictinfo);
     351                 :             :     }
     352                 :             : 
     353                 :             :     /*
     354                 :             :      * Now that we have the relevant equality join clauses, try to prove the
     355                 :             :      * innerrel distinct.
     356                 :             :      */
     357         [ +  + ]:        8938 :     if (rel_is_distinct_for(root, innerrel, clause_list, NULL))
     358                 :        8669 :         return true;
     359                 :             : 
     360                 :             :     /*
     361                 :             :      * Some day it would be nice to check for other methods of establishing
     362                 :             :      * distinctness.
     363                 :             :      */
     364                 :         269 :     return false;
     365                 :             : }
     366                 :             : 
     367                 :             : /*
     368                 :             :  * remove_join_from_jointree
     369                 :             :  *      Delete the JoinExpr with the given RT index, along with everything
     370                 :             :  *      below its righthand side, from the query's jointree.
     371                 :             :  *
     372                 :             :  * The JoinExpr is replaced by its lefthand input.  Its ON conditions can just
     373                 :             :  * be dropped: since this is a left join, they could only have determined
     374                 :             :  * which righthand rows join to a given lefthand row, and there are no
     375                 :             :  * righthand rows anymore.
     376                 :             :  *
     377                 :             :  * *nremoved is incremented by the number of JoinExprs removed (there should
     378                 :             :  * be exactly one, but the caller checks that).
     379                 :             :  */
     380                 :             : static Node *
     381                 :       27612 : remove_join_from_jointree(Node *jtnode, int ojrelid, int *nremoved)
     382                 :             : {
     383         [ -  + ]:       27612 :     if (jtnode == NULL)
     384                 :           0 :         return NULL;
     385         [ +  + ]:       27612 :     if (IsA(jtnode, RangeTblRef))
     386                 :             :     {
     387                 :             :         /* nothing to do here */
     388                 :             :     }
     389         [ +  + ]:       22338 :     else if (IsA(jtnode, FromExpr))
     390                 :             :     {
     391                 :        8699 :         FromExpr   *f = (FromExpr *) jtnode;
     392                 :             :         ListCell   *l;
     393                 :             : 
     394   [ +  -  +  +  :       17702 :         foreach(l, f->fromlist)
                   +  + ]
     395                 :        9003 :             lfirst(l) = remove_join_from_jointree((Node *) lfirst(l),
     396                 :             :                                                   ojrelid, nremoved);
     397                 :             :     }
     398         [ +  - ]:       13639 :     else if (IsA(jtnode, JoinExpr))
     399                 :             :     {
     400                 :       13639 :         JoinExpr   *j = (JoinExpr *) jtnode;
     401                 :             : 
     402         [ +  + ]:       13639 :         if (j->rtindex == ojrelid)
     403                 :             :         {
     404                 :        8669 :             (*nremoved)++;
     405                 :        8669 :             return j->larg;
     406                 :             :         }
     407                 :        4970 :         j->larg = remove_join_from_jointree(j->larg, ojrelid, nremoved);
     408                 :        4970 :         j->rarg = remove_join_from_jointree(j->rarg, ojrelid, nremoved);
     409                 :             :     }
     410                 :             :     else
     411         [ #  # ]:           0 :         elog(ERROR, "unrecognized jointree node type: %d",
     412                 :             :              (int) nodeTag(jtnode));
     413                 :             : 
     414                 :       18943 :     return jtnode;
     415                 :             : }
     416                 :             : 
     417                 :             : /*
     418                 :             :  * remove_rels_from_query_tree
     419                 :             :  *      Delete all remaining references to the given relids from the query.
     420                 :             :  *
     421                 :             :  * Having removed some relations and outer joins from the jointree, we must
     422                 :             :  * get rid of any references to them that are left behind elsewhere.  There
     423                 :             :  * should be no ordinary Vars of a removed relation left, but OJ relids can
     424                 :             :  * still appear in the nullingrels sets of surviving Vars and PlaceHolderVars,
     425                 :             :  * and both regular and OJ relids can appear in the phrels sets of
     426                 :             :  * PlaceHolderVars.  ChangeVarNodes knows how to strip a relid out of all of
     427                 :             :  * those.
     428                 :             :  */
     429                 :             : static void
     430                 :        7955 : remove_rels_from_query_tree(PlannerInfo *root, Relids removed_relids)
     431                 :             : {
     432                 :        7955 :     int         relid = -1;
     433                 :             : 
     434         [ +  + ]:       25293 :     while ((relid = bms_next_member(removed_relids, relid)) >= 0)
     435                 :             :     {
     436                 :       17338 :         ChangeVarNodes((Node *) root->parse, relid, INVALID_VAR, 0);
     437                 :             : 
     438                 :             :         /*
     439                 :             :          * processed_tlist shares some but not all of its nodes with
     440                 :             :          * parse->targetList, so it has to be processed separately.  (That's
     441                 :             :          * harmless: ChangeVarNodes works in-place, and removing a relid that
     442                 :             :          * isn't there is idempotent.)
     443                 :             :          */
     444                 :       17338 :         ChangeVarNodes((Node *) root->processed_tlist, relid, INVALID_VAR, 0);
     445                 :             : 
     446                 :             :         /* There could be references in the append_rel_list, too */
     447         [ +  + ]:       17338 :         if (root->append_rel_list != NIL)
     448                 :          20 :             ChangeVarNodes((Node *) root->append_rel_list, relid, INVALID_VAR, 0);
     449                 :             :     }
     450                 :        7955 : }
     451                 :             : 
     452                 :             : /*
     453                 :             :  * reduce_unique_semijoins
     454                 :             :  *      Check for semijoins that can be simplified to plain inner joins
     455                 :             :  *      because the inner relation is provably unique for the join clauses.
     456                 :             :  *
     457                 :             :  * Ideally this would happen during reduce_outer_joins, but we don't have
     458                 :             :  * enough information at that point.
     459                 :             :  *
     460                 :             :  * Like the join removal cases, we do this on the query's jointree, so
     461                 :             :  * returning true means the caller must recompute the derived data.
     462                 :             :  */
     463                 :             : bool
     464                 :      247170 : reduce_unique_semijoins(PlannerInfo *root)
     465                 :             : {
     466                 :      247170 :     bool        changed = false;
     467                 :             :     ListCell   *lc;
     468                 :             : 
     469                 :             :     /*
     470                 :             :      * Scan the join_info_list to find semijoins.
     471                 :             :      */
     472   [ +  +  +  +  :      284689 :     foreach(lc, root->join_info_list)
                   +  + ]
     473                 :             :     {
     474                 :       37519 :         SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
     475                 :             :         int         innerrelid;
     476                 :             :         RelOptInfo *innerrel;
     477                 :             :         Relids      joinrelids;
     478                 :             :         List       *restrictlist;
     479                 :             : 
     480                 :             :         /*
     481                 :             :          * Must be a semijoin to a single baserel, else we aren't going to be
     482                 :             :          * able to do anything with it.
     483                 :             :          */
     484         [ +  + ]:       37519 :         if (sjinfo->jointype != JOIN_SEMI)
     485                 :       37275 :             continue;
     486                 :             : 
     487                 :             :         /*
     488                 :             :          * We test the syntactic righthand side, since that's what identifies
     489                 :             :          * the JoinExpr we'll modify.
     490                 :             :          */
     491         [ +  + ]:        4109 :         if (!bms_get_singleton_member(sjinfo->syn_righthand, &innerrelid))
     492                 :         140 :             continue;
     493                 :             :         Assert(bms_equal(sjinfo->min_righthand, sjinfo->syn_righthand));
     494                 :             : 
     495                 :        3969 :         innerrel = find_base_rel(root, innerrelid);
     496                 :             : 
     497                 :             :         /*
     498                 :             :          * Before we trouble to run generate_join_implied_equalities, make a
     499                 :             :          * quick check to eliminate cases in which we will surely be unable to
     500                 :             :          * prove uniqueness of the innerrel.
     501                 :             :          */
     502         [ +  + ]:        3969 :         if (!rel_supports_distinctness(root, innerrel))
     503                 :         876 :             continue;
     504                 :             : 
     505                 :             :         /* Compute the relid set for the join we are considering */
     506                 :        3093 :         joinrelids = bms_union(sjinfo->min_lefthand, sjinfo->min_righthand);
     507                 :             :         Assert(sjinfo->ojrelid == 0);    /* SEMI joins don't have RT indexes */
     508                 :             : 
     509                 :             :         /*
     510                 :             :          * Since we're only considering a single-rel RHS, any join clauses it
     511                 :             :          * has must be clauses linking it to the semijoin's min_lefthand.  We
     512                 :             :          * can also consider EC-derived join clauses.
     513                 :             :          */
     514                 :             :         restrictlist =
     515                 :        3093 :             list_concat(generate_join_implied_equalities(root,
     516                 :             :                                                          joinrelids,
     517                 :             :                                                          sjinfo->min_lefthand,
     518                 :             :                                                          innerrel,
     519                 :             :                                                          NULL),
     520                 :        3093 :                         innerrel->joininfo);
     521                 :             : 
     522                 :             :         /* Test whether the innerrel is unique for those clauses. */
     523         [ +  + ]:        3093 :         if (!innerrel_is_unique(root,
     524                 :             :                                 joinrelids, sjinfo->min_lefthand, innerrel,
     525                 :             :                                 JOIN_SEMI, restrictlist, true))
     526                 :        2849 :             continue;
     527                 :             : 
     528                 :             :         /* OK, reduce the join to a plain inner join in the jointree. */
     529         [ -  + ]:         244 :         if (!reduce_semijoin_in_jointree((Node *) root->parse->jointree,
     530                 :             :                                          sjinfo->syn_righthand))
     531         [ #  # ]:           0 :             elog(ERROR, "failed to find semijoin in jointree");
     532                 :         244 :         changed = true;
     533                 :             :     }
     534                 :             : 
     535                 :      247170 :     return changed;
     536                 :             : }
     537                 :             : 
     538                 :             : /*
     539                 :             :  * reduce_semijoin_in_jointree
     540                 :             :  *      Find the JoinExpr for the semijoin with the given syntactic righthand
     541                 :             :  *      side, and turn it into an inner join.
     542                 :             :  *
     543                 :             :  * Semijoins have no RT index of their own, so we have to identify the one
     544                 :             :  * we want by the set of relids on its righthand side.
     545                 :             :  */
     546                 :             : static bool
     547                 :         559 : reduce_semijoin_in_jointree(Node *jtnode, Relids syn_righthand)
     548                 :             : {
     549         [ -  + ]:         559 :     if (jtnode == NULL)
     550                 :           0 :         return false;
     551         [ +  + ]:         559 :     if (IsA(jtnode, RangeTblRef))
     552                 :             :     {
     553                 :             :         /* nothing to do here */
     554                 :             :     }
     555         [ +  + ]:         534 :     else if (IsA(jtnode, FromExpr))
     556                 :             :     {
     557                 :         251 :         FromExpr   *f = (FromExpr *) jtnode;
     558                 :             :         ListCell   *l;
     559                 :             : 
     560   [ +  -  +  -  :         251 :         foreach(l, f->fromlist)
                   +  - ]
     561                 :             :         {
     562         [ +  - ]:         251 :             if (reduce_semijoin_in_jointree((Node *) lfirst(l), syn_righthand))
     563                 :         251 :                 return true;
     564                 :             :         }
     565                 :             :     }
     566         [ +  - ]:         283 :     else if (IsA(jtnode, JoinExpr))
     567                 :             :     {
     568                 :         283 :         JoinExpr   *j = (JoinExpr *) jtnode;
     569                 :             : 
     570   [ +  +  +  + ]:         541 :         if (j->jointype == JOIN_SEMI &&
     571                 :         258 :             bms_equal(get_relids_in_jointree(j->rarg, true, false),
     572                 :             :                       syn_righthand))
     573                 :             :         {
     574                 :         244 :             j->jointype = JOIN_INNER;
     575                 :         244 :             return true;
     576                 :             :         }
     577         [ +  + ]:          39 :         if (reduce_semijoin_in_jointree(j->larg, syn_righthand))
     578                 :          14 :             return true;
     579         [ +  - ]:          25 :         if (reduce_semijoin_in_jointree(j->rarg, syn_righthand))
     580                 :          25 :             return true;
     581                 :             :     }
     582                 :             :     else
     583         [ #  # ]:           0 :         elog(ERROR, "unrecognized jointree node type: %d",
     584                 :             :              (int) nodeTag(jtnode));
     585                 :             : 
     586                 :          25 :     return false;
     587                 :             : }
     588                 :             : 
     589                 :             : 
     590                 :             : /*
     591                 :             :  * rel_supports_distinctness
     592                 :             :  *      Could the relation possibly be proven distinct on some set of columns?
     593                 :             :  *
     594                 :             :  * This is effectively a pre-checking function for rel_is_distinct_for().
     595                 :             :  * It must return true if rel_is_distinct_for() could possibly return true
     596                 :             :  * with this rel, but it should not expend a lot of cycles.  The idea is
     597                 :             :  * that callers can avoid doing possibly-expensive processing to compute
     598                 :             :  * rel_is_distinct_for()'s argument lists if the call could not possibly
     599                 :             :  * succeed.
     600                 :             :  */
     601                 :             : static bool
     602                 :      541781 : rel_supports_distinctness(PlannerInfo *root, RelOptInfo *rel)
     603                 :             : {
     604                 :             :     /* We only know about baserels ... */
     605         [ +  + ]:      541781 :     if (rel->reloptkind != RELOPT_BASEREL)
     606                 :      197668 :         return false;
     607         [ +  + ]:      344113 :     if (rel->rtekind == RTE_RELATION)
     608                 :             :     {
     609                 :             :         /*
     610                 :             :          * For a plain relation, we only know how to prove uniqueness by
     611                 :             :          * reference to unique indexes.  Make sure there's at least one
     612                 :             :          * suitable unique index.  It must be immediately enforced, and not a
     613                 :             :          * partial index. (Keep these conditions in sync with
     614                 :             :          * relation_has_unique_index_for!)
     615                 :             :          */
     616                 :             :         ListCell   *lc;
     617                 :             : 
     618   [ +  +  +  +  :      428229 :         foreach(lc, rel->indexlist)
                   +  + ]
     619                 :             :         {
     620                 :      377660 :             IndexOptInfo *ind = (IndexOptInfo *) lfirst(lc);
     621                 :             : 
     622   [ +  +  +  -  :      377660 :             if (ind->unique && ind->immediate && ind->indpred == NIL)
                   +  + ]
     623                 :      266867 :                 return true;
     624                 :             :         }
     625                 :             :     }
     626         [ +  + ]:       26677 :     else if (rel->rtekind == RTE_SUBQUERY)
     627                 :             :     {
     628                 :       10106 :         Query      *subquery = root->simple_rte_array[rel->relid]->subquery;
     629                 :             : 
     630                 :             :         /* Check if the subquery has any qualities that support distinctness */
     631         [ +  + ]:       10106 :         if (query_supports_distinctness(subquery))
     632                 :        8625 :             return true;
     633                 :             :     }
     634                 :             :     /* We have no proof rules for any other rtekinds. */
     635                 :       68621 :     return false;
     636                 :             : }
     637                 :             : 
     638                 :             : /*
     639                 :             :  * rel_is_distinct_for
     640                 :             :  *      Does the relation return only distinct rows according to clause_list?
     641                 :             :  *
     642                 :             :  * clause_list is a list of join restriction clauses involving this rel and
     643                 :             :  * some other one.  Return true if no two rows emitted by this rel could
     644                 :             :  * possibly join to the same row of the other rel.
     645                 :             :  *
     646                 :             :  * The caller must have already determined that each condition is a
     647                 :             :  * mergejoinable equality with an expression in this relation on one side, and
     648                 :             :  * an expression not involving this relation on the other.  The transient
     649                 :             :  * outer_is_left flag is used to identify which side references this relation:
     650                 :             :  * left side if outer_is_left is false, right side if it is true.
     651                 :             :  *
     652                 :             :  * Note that the passed-in clause_list may be destructively modified!  This
     653                 :             :  * is OK for current uses, because the clause_list is built by the caller for
     654                 :             :  * the sole purpose of passing to this function.
     655                 :             :  *
     656                 :             :  * (*extra_clauses) to be set to the right sides of baserestrictinfo clauses,
     657                 :             :  * looking like "x = const" if distinctness is derived from such clauses, not
     658                 :             :  * joininfo clauses.  Pass NULL to the extra_clauses if this value is not
     659                 :             :  * needed.
     660                 :             :  */
     661                 :             : static bool
     662                 :      178204 : rel_is_distinct_for(PlannerInfo *root, RelOptInfo *rel, List *clause_list,
     663                 :             :                     List **extra_clauses)
     664                 :             : {
     665                 :             :     /*
     666                 :             :      * We could skip a couple of tests here if we assume all callers checked
     667                 :             :      * rel_supports_distinctness first, but it doesn't seem worth taking any
     668                 :             :      * risk for.
     669                 :             :      */
     670         [ -  + ]:      178204 :     if (rel->reloptkind != RELOPT_BASEREL)
     671                 :           0 :         return false;
     672         [ +  + ]:      178204 :     if (rel->rtekind == RTE_RELATION)
     673                 :             :     {
     674                 :             :         /*
     675                 :             :          * Examine the indexes to see if we have a matching unique index.
     676                 :             :          * relation_has_unique_index_for automatically adds any usable
     677                 :             :          * restriction clauses for the rel, so we needn't do that here.
     678                 :             :          */
     679         [ +  + ]:      173716 :         if (relation_has_unique_index_for(root, rel, clause_list, extra_clauses))
     680                 :      105212 :             return true;
     681                 :             :     }
     682         [ +  - ]:        4488 :     else if (rel->rtekind == RTE_SUBQUERY)
     683                 :             :     {
     684                 :        4488 :         Index       relid = rel->relid;
     685                 :        4488 :         Query      *subquery = root->simple_rte_array[relid]->subquery;
     686                 :        4488 :         List       *distinct_cols = NIL;
     687                 :             :         ListCell   *l;
     688                 :             : 
     689                 :             :         /*
     690                 :             :          * Build the argument list for query_is_distinct_for: a list of
     691                 :             :          * DistinctColInfo entries, each holding an output column number that
     692                 :             :          * the query needs to be distinct over, the equality operator that the
     693                 :             :          * column needs to be distinct according to, and that operator's input
     694                 :             :          * collation.  The collation matters because the subquery's own
     695                 :             :          * DISTINCT / GROUP BY / set-op proves uniqueness under its own
     696                 :             :          * collation, which need not agree with the operator's.
     697                 :             :          *
     698                 :             :          * (XXX we are not considering restriction clauses attached to the
     699                 :             :          * subquery; is that worth doing?)
     700                 :             :          */
     701   [ +  +  +  +  :        8601 :         foreach(l, clause_list)
                   +  + ]
     702                 :             :         {
     703                 :        4113 :             RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
     704                 :             :             OpExpr     *opexpr;
     705                 :             :             Var        *var;
     706                 :             :             DistinctColInfo *dcinfo;
     707                 :             : 
     708                 :             :             /*
     709                 :             :              * The caller's mergejoinability test should have selected only
     710                 :             :              * OpExprs.  The operator might be a cross-type operator and thus
     711                 :             :              * not exactly the same operator the subquery would consider;
     712                 :             :              * that's all right since query_is_distinct_for can resolve such
     713                 :             :              * cases.
     714                 :             :              */
     715                 :        4113 :             opexpr = castNode(OpExpr, rinfo->clause);
     716                 :             : 
     717                 :             :             /* caller identified the inner side for us */
     718         [ +  + ]:        4113 :             if (rinfo->outer_is_left)
     719                 :        3762 :                 var = (Var *) get_rightop(rinfo->clause);
     720                 :             :             else
     721                 :         351 :                 var = (Var *) get_leftop(rinfo->clause);
     722                 :             : 
     723                 :             :             /*
     724                 :             :              * We may ignore any RelabelType node above the operand.  (There
     725                 :             :              * won't be more than one, since eval_const_expressions() has been
     726                 :             :              * applied already.)
     727                 :             :              */
     728   [ +  -  +  + ]:        4113 :             if (var && IsA(var, RelabelType))
     729                 :        2718 :                 var = (Var *) ((RelabelType *) var)->arg;
     730                 :             : 
     731                 :             :             /*
     732                 :             :              * If inner side isn't a Var referencing a subquery output column,
     733                 :             :              * this clause doesn't help us.
     734                 :             :              */
     735   [ +  -  +  + ]:        4113 :             if (!var || !IsA(var, Var) ||
     736   [ +  -  -  + ]:        4103 :                 var->varno != relid || var->varlevelsup != 0)
     737                 :          10 :                 continue;
     738                 :             : 
     739                 :        4103 :             dcinfo = palloc_object(DistinctColInfo);
     740                 :        4103 :             dcinfo->colno = var->varattno;
     741                 :        4103 :             dcinfo->opid = opexpr->opno;
     742                 :        4103 :             dcinfo->collid = opexpr->inputcollid;
     743                 :        4103 :             distinct_cols = lappend(distinct_cols, dcinfo);
     744                 :             :         }
     745                 :             : 
     746         [ +  + ]:        4488 :         if (query_is_distinct_for(subquery, distinct_cols))
     747                 :         654 :             return true;
     748                 :             :     }
     749                 :       72338 :     return false;
     750                 :             : }
     751                 :             : 
     752                 :             : 
     753                 :             : /*
     754                 :             :  * query_supports_distinctness - could the query possibly be proven distinct
     755                 :             :  *      on some set of output columns?
     756                 :             :  *
     757                 :             :  * This is effectively a pre-checking function for query_is_distinct_for().
     758                 :             :  * It must return true if query_is_distinct_for() could possibly return true
     759                 :             :  * with this query, but it should not expend a lot of cycles.  The idea is
     760                 :             :  * that callers can avoid doing possibly-expensive processing to compute
     761                 :             :  * query_is_distinct_for()'s argument lists if the call could not possibly
     762                 :             :  * succeed.
     763                 :             :  */
     764                 :             : bool
     765                 :       10106 : query_supports_distinctness(Query *query)
     766                 :             : {
     767                 :             :     /* SRFs break distinctness except with plain DISTINCT, see below */
     768         [ +  + ]:       10106 :     if (query->hasTargetSRFs &&
     769   [ +  +  +  - ]:         766 :         (query->distinctClause == NIL || query->hasDistinctOn))
     770                 :         766 :         return false;
     771                 :             : 
     772                 :             :     /* check for features we can prove distinctness with */
     773         [ +  + ]:        9340 :     if (query->distinctClause != NIL ||
     774         [ +  + ]:        9155 :         query->groupClause != NIL ||
     775         [ +  + ]:        8969 :         query->groupingSets != NIL ||
     776         [ +  + ]:        8929 :         query->hasAggs ||
     777         [ +  - ]:        7221 :         query->havingQual ||
     778         [ +  + ]:        7221 :         query->setOperations)
     779                 :        8625 :         return true;
     780                 :             : 
     781                 :         715 :     return false;
     782                 :             : }
     783                 :             : 
     784                 :             : /*
     785                 :             :  * query_is_distinct_for - does query never return duplicates of the
     786                 :             :  *      specified columns?
     787                 :             :  *
     788                 :             :  * query is a not-yet-planned subquery (in current usage, it's always from
     789                 :             :  * a subquery RTE, which the planner avoids scribbling on).
     790                 :             :  *
     791                 :             :  * distinct_cols is a list of DistinctColInfo, one per requested output column.
     792                 :             :  * Each entry names the subquery output column number we want distinct, the
     793                 :             :  * upper-level equality operator we'll compare values with, and that operator's
     794                 :             :  * input collation.  We are interested in whether rows consisting of just these
     795                 :             :  * columns are certain to be distinct.
     796                 :             :  *
     797                 :             :  * "Distinctness" is defined according to whether the corresponding upper-level
     798                 :             :  * equality operators would think the values are distinct.  (Note: each opid
     799                 :             :  * could be a cross-type operator, and thus not exactly the equality operator
     800                 :             :  * that the subquery would use itself.  We use equality_ops_are_compatible() to
     801                 :             :  * check compatibility.  That looks at opfamily membership for index AMs that
     802                 :             :  * have declared that they support consistent equality semantics within an
     803                 :             :  * opfamily, and so should give trustworthy answers for all operators that we
     804                 :             :  * might need to deal with here.)
     805                 :             :  *
     806                 :             :  * The collid must also agree on equality with the collation the subquery's own
     807                 :             :  * DISTINCT/GROUP BY/set-op uses to deduplicate the column, else the subquery's
     808                 :             :  * distinctness does not carry over to the caller's equality semantics.  Two
     809                 :             :  * collations agree on equality if they match or if both are deterministic (in
     810                 :             :  * which case both reduce equality to byte-equality; see CREATE COLLATION).
     811                 :             :  */
     812                 :             : bool
     813                 :        4488 : query_is_distinct_for(Query *query, List *distinct_cols)
     814                 :             : {
     815                 :             :     ListCell   *l;
     816                 :             :     DistinctColInfo *dcinfo;
     817                 :             : 
     818                 :             :     /*
     819                 :             :      * DISTINCT (including DISTINCT ON) guarantees uniqueness if all the
     820                 :             :      * columns in the DISTINCT clause appear in colnos and operator semantics
     821                 :             :      * match.  With plain DISTINCT this is true even if there are SRFs in the
     822                 :             :      * tlist, since they are all DISTINCT columns and hence get expanded
     823                 :             :      * before the Unique step.  But with DISTINCT ON, the planner may postpone
     824                 :             :      * SRFs that are not DISTINCT ON or ORDER BY columns until after the
     825                 :             :      * Unique step, which can produce duplicates of the DISTINCT ON columns;
     826                 :             :      * so we can't rely on DISTINCT ON if there are any tlist SRFs.
     827                 :             :      */
     828         [ +  + ]:        4488 :     if (query->distinctClause &&
     829   [ -  +  -  - ]:         155 :         !(query->hasTargetSRFs && query->hasDistinctOn))
     830                 :             :     {
     831   [ +  -  +  +  :         220 :         foreach(l, query->distinctClause)
                   +  + ]
     832                 :             :         {
     833                 :         170 :             SortGroupClause *sgc = (SortGroupClause *) lfirst(l);
     834                 :         170 :             TargetEntry *tle = get_sortgroupclause_tle(sgc,
     835                 :             :                                                        query->targetList);
     836                 :             : 
     837                 :         170 :             dcinfo = distinct_col_search(tle->resno, distinct_cols);
     838         [ +  + ]:         170 :             if (dcinfo == NULL ||
     839         [ +  - ]:         105 :                 !equality_ops_are_compatible(dcinfo->opid, sgc->eqop) ||
     840         [ +  + ]:         105 :                 !collations_agree_on_equality(dcinfo->collid,
     841                 :         105 :                                               exprCollation((Node *) tle->expr)))
     842                 :             :                 break;          /* exit early if no match */
     843                 :             :         }
     844         [ +  + ]:         155 :         if (l == NULL)          /* had matches for all? */
     845                 :          50 :             return true;
     846                 :             :     }
     847                 :             : 
     848                 :             :     /*
     849                 :             :      * Otherwise, a set-returning function in the query's targetlist can
     850                 :             :      * result in returning duplicate rows, despite any grouping that might
     851                 :             :      * occur before tlist evaluation.  (If all tlist SRFs are within GROUP BY
     852                 :             :      * columns, it would be safe because they'd be expanded before grouping.
     853                 :             :      * But it doesn't currently seem worth the effort to check for that.)
     854                 :             :      */
     855         [ -  + ]:        4438 :     if (query->hasTargetSRFs)
     856                 :           0 :         return false;
     857                 :             : 
     858                 :             :     /*
     859                 :             :      * Similarly, GROUP BY without GROUPING SETS guarantees uniqueness if all
     860                 :             :      * the grouped columns appear in colnos and operator semantics match.
     861                 :             :      */
     862   [ +  +  +  + ]:        4438 :     if (query->groupClause && !query->groupingSets)
     863                 :             :     {
     864   [ +  -  +  +  :         226 :         foreach(l, query->groupClause)
                   +  + ]
     865                 :             :         {
     866                 :         159 :             SortGroupClause *sgc = (SortGroupClause *) lfirst(l);
     867                 :         159 :             TargetEntry *tle = get_sortgroupclause_tle(sgc,
     868                 :             :                                                        query->targetList);
     869                 :             : 
     870                 :         159 :             dcinfo = distinct_col_search(tle->resno, distinct_cols);
     871         [ +  + ]:         159 :             if (dcinfo == NULL ||
     872         [ +  - ]:         112 :                 !equality_ops_are_compatible(dcinfo->opid, sgc->eqop) ||
     873         [ +  + ]:         112 :                 !collations_agree_on_equality(dcinfo->collid,
     874                 :         112 :                                               exprCollation((Node *) tle->expr)))
     875                 :             :                 break;          /* exit early if no match */
     876                 :             :         }
     877         [ +  + ]:         124 :         if (l == NULL)          /* had matches for all? */
     878                 :          67 :             return true;
     879                 :             :     }
     880         [ +  + ]:        4314 :     else if (query->groupingSets)
     881                 :             :     {
     882                 :             :         List       *gsets;
     883                 :             : 
     884                 :             :         /*
     885                 :             :          * If we have grouping sets with expressions, we probably don't have
     886                 :             :          * uniqueness and analysis would be hard. Punt.
     887                 :             :          */
     888         [ +  + ]:          50 :         if (query->groupClause)
     889                 :          10 :             return false;
     890                 :             : 
     891                 :             :         /*
     892                 :             :          * If we have no groupClause (therefore no grouping expressions), we
     893                 :             :          * might have one or many empty grouping sets.  If there's just one,
     894                 :             :          * or if the DISTINCT clause is used on the GROUP BY, then we're
     895                 :             :          * returning only one row and are certainly unique.  But otherwise, we
     896                 :             :          * know we're certainly not unique.
     897                 :             :          */
     898         [ +  + ]:          40 :         if (query->groupDistinct)
     899                 :           5 :             return true;
     900                 :             : 
     901                 :          35 :         gsets = expand_grouping_sets(query->groupingSets, false, -1);
     902                 :             : 
     903                 :          35 :         return (list_length(gsets) == 1);
     904                 :             :     }
     905                 :             :     else
     906                 :             :     {
     907                 :             :         /*
     908                 :             :          * If we have no GROUP BY, but do have aggregates or HAVING, then the
     909                 :             :          * result is at most one row so it's surely unique, for any operators.
     910                 :             :          */
     911   [ +  +  -  + ]:        4264 :         if (query->hasAggs || query->havingQual)
     912                 :         413 :             return true;
     913                 :             :     }
     914                 :             : 
     915                 :             :     /*
     916                 :             :      * UNION, INTERSECT, EXCEPT guarantee uniqueness of the whole output row,
     917                 :             :      * except with ALL.
     918                 :             :      */
     919         [ +  + ]:        3908 :     if (query->setOperations)
     920                 :             :     {
     921                 :        3746 :         SetOperationStmt *topop = castNode(SetOperationStmt, query->setOperations);
     922                 :             : 
     923                 :             :         Assert(topop->op != SETOP_NONE);
     924                 :             : 
     925         [ +  + ]:        3746 :         if (!topop->all)
     926                 :             :         {
     927                 :             :             ListCell   *lg;
     928                 :             : 
     929                 :             :             /* We're good if all the nonjunk output columns are in colnos */
     930                 :         147 :             lg = list_head(topop->groupClauses);
     931   [ +  -  +  +  :         256 :             foreach(l, query->targetList)
                   +  + ]
     932                 :             :             {
     933                 :         152 :                 TargetEntry *tle = (TargetEntry *) lfirst(l);
     934                 :             :                 SortGroupClause *sgc;
     935                 :             : 
     936         [ -  + ]:         152 :                 if (tle->resjunk)
     937                 :           0 :                     continue;   /* ignore resjunk columns */
     938                 :             : 
     939                 :             :                 /* non-resjunk columns should have grouping clauses */
     940                 :             :                 Assert(lg != NULL);
     941                 :         152 :                 sgc = (SortGroupClause *) lfirst(lg);
     942                 :         152 :                 lg = lnext(topop->groupClauses, lg);
     943                 :             : 
     944                 :         152 :                 dcinfo = distinct_col_search(tle->resno, distinct_cols);
     945         [ +  + ]:         152 :                 if (dcinfo == NULL ||
     946         [ +  - ]:         119 :                     !equality_ops_are_compatible(dcinfo->opid, sgc->eqop) ||
     947         [ +  + ]:         119 :                     !collations_agree_on_equality(dcinfo->collid,
     948                 :         119 :                                                   exprCollation((Node *) tle->expr)))
     949                 :             :                     break;      /* exit early if no match */
     950                 :             :             }
     951         [ +  + ]:         147 :             if (l == NULL)      /* had matches for all? */
     952                 :         104 :                 return true;
     953                 :             :         }
     954                 :             :     }
     955                 :             : 
     956                 :             :     /*
     957                 :             :      * XXX Are there any other cases in which we can easily see the result
     958                 :             :      * must be distinct?
     959                 :             :      *
     960                 :             :      * If you do add more smarts to this function, be sure to update
     961                 :             :      * query_supports_distinctness() to match.
     962                 :             :      */
     963                 :             : 
     964                 :        3804 :     return false;
     965                 :             : }
     966                 :             : 
     967                 :             : /*
     968                 :             :  * distinct_col_search - subroutine for query_is_distinct_for
     969                 :             :  *
     970                 :             :  * If colno matches the colno field of an entry in distinct_cols, return a
     971                 :             :  * pointer to that entry; else return NULL.  (Ordinarily distinct_cols would
     972                 :             :  * not contain duplicate colnos, but if it does, we arbitrarily select the
     973                 :             :  * first match.)
     974                 :             :  */
     975                 :             : static DistinctColInfo *
     976                 :         481 : distinct_col_search(int colno, List *distinct_cols)
     977                 :             : {
     978   [ +  -  +  +  :         789 :     foreach_ptr(DistinctColInfo, dcinfo, distinct_cols)
                   +  + ]
     979                 :             :     {
     980         [ +  + ]:         499 :         if (dcinfo->colno == colno)
     981                 :         336 :             return dcinfo;
     982                 :             :     }
     983                 :             : 
     984                 :         145 :     return NULL;
     985                 :             : }
     986                 :             : 
     987                 :             : 
     988                 :             : /*
     989                 :             :  * innerrel_is_unique
     990                 :             :  *    Check if the innerrel provably contains at most one tuple matching any
     991                 :             :  *    tuple from the outerrel, based on join clauses in the 'restrictlist'.
     992                 :             :  *
     993                 :             :  * We need an actual RelOptInfo for the innerrel, but it's sufficient to
     994                 :             :  * identify the outerrel by its Relids.  This asymmetry supports use of this
     995                 :             :  * function before joinrels have been built.  (The caller is expected to
     996                 :             :  * also supply the joinrelids, just to save recalculating that.)
     997                 :             :  *
     998                 :             :  * The proof must be made based only on clauses that will be "joinquals"
     999                 :             :  * rather than "otherquals" at execution.  For an inner join there's no
    1000                 :             :  * difference; but if the join is outer, we must ignore pushed-down quals,
    1001                 :             :  * as those will become "otherquals".  Note that this means the answer might
    1002                 :             :  * vary depending on whether IS_OUTER_JOIN(jointype); since we cache the
    1003                 :             :  * answer without regard to that, callers must take care not to call this
    1004                 :             :  * with jointypes that would be classified differently by IS_OUTER_JOIN().
    1005                 :             :  *
    1006                 :             :  * The actual proof is undertaken by is_innerrel_unique_for(); this function
    1007                 :             :  * is a frontend that is mainly concerned with caching the answers.
    1008                 :             :  * In particular, the force_cache argument allows overriding the internal
    1009                 :             :  * heuristic about whether to cache negative answers; it should be "true"
    1010                 :             :  * if making an inquiry that is not part of the normal bottom-up join search
    1011                 :             :  * sequence.
    1012                 :             :  */
    1013                 :             : bool
    1014                 :      587569 : innerrel_is_unique(PlannerInfo *root,
    1015                 :             :                    Relids joinrelids,
    1016                 :             :                    Relids outerrelids,
    1017                 :             :                    RelOptInfo *innerrel,
    1018                 :             :                    JoinType jointype,
    1019                 :             :                    List *restrictlist,
    1020                 :             :                    bool force_cache)
    1021                 :             : {
    1022                 :      587569 :     return innerrel_is_unique_ext(root, joinrelids, outerrelids, innerrel,
    1023                 :             :                                   jointype, restrictlist, force_cache, NULL);
    1024                 :             : }
    1025                 :             : 
    1026                 :             : /*
    1027                 :             :  * innerrel_is_unique_ext
    1028                 :             :  *    Do the same as innerrel_is_unique(), but also set to (*extra_clauses)
    1029                 :             :  *    additional clauses from a baserestrictinfo list used to prove the
    1030                 :             :  *    uniqueness.
    1031                 :             :  *
    1032                 :             :  * A non-NULL extra_clauses indicates that we're checking for self-join and
    1033                 :             :  * correspondingly dealing with filtered clauses.
    1034                 :             :  */
    1035                 :             : static bool
    1036                 :      589425 : innerrel_is_unique_ext(PlannerInfo *root,
    1037                 :             :                        Relids joinrelids,
    1038                 :             :                        Relids outerrelids,
    1039                 :             :                        RelOptInfo *innerrel,
    1040                 :             :                        JoinType jointype,
    1041                 :             :                        List *restrictlist,
    1042                 :             :                        bool force_cache,
    1043                 :             :                        List **extra_clauses)
    1044                 :             : {
    1045                 :             :     MemoryContext old_context;
    1046                 :             :     ListCell   *lc;
    1047                 :             :     UniqueRelInfo *uniqueRelInfo;
    1048                 :      589425 :     List       *outer_exprs = NIL;
    1049                 :      589425 :     bool        self_join = (extra_clauses != NULL);
    1050                 :             : 
    1051                 :             :     /* Certainly can't prove uniqueness when there are no joinclauses */
    1052         [ +  + ]:      589425 :     if (restrictlist == NIL)
    1053                 :       84759 :         return false;
    1054                 :             : 
    1055                 :             :     /*
    1056                 :             :      * Make a quick check to eliminate cases in which we will surely be unable
    1057                 :             :      * to prove uniqueness of the innerrel.
    1058                 :             :      */
    1059         [ +  + ]:      504666 :     if (!rel_supports_distinctness(root, innerrel))
    1060                 :      262659 :         return false;
    1061                 :             : 
    1062                 :             :     /*
    1063                 :             :      * Query the cache to see if we've managed to prove that innerrel is
    1064                 :             :      * unique for any subset of this outerrel.  For non-self-join search, we
    1065                 :             :      * don't need an exact match, as extra outerrels can't make the innerrel
    1066                 :             :      * any less unique (or more formally, the restrictlist for a join to a
    1067                 :             :      * superset outerrel must be a superset of the conditions we successfully
    1068                 :             :      * used before). For self-join search, we require an exact match of
    1069                 :             :      * outerrels because we need extra clauses to be valid for our case. Also,
    1070                 :             :      * for self-join checking we've filtered the clauses list.  Thus, we can
    1071                 :             :      * match only the result cached for a self-join search for another
    1072                 :             :      * self-join check.
    1073                 :             :      */
    1074   [ +  +  +  +  :      261685 :     foreach(lc, innerrel->unique_for_rels)
                   +  + ]
    1075                 :             :     {
    1076                 :       92117 :         uniqueRelInfo = (UniqueRelInfo *) lfirst(lc);
    1077                 :             : 
    1078   [ +  -  +  +  :       92117 :         if ((!self_join && bms_is_subset(uniqueRelInfo->outerrelids, outerrelids)) ||
                   -  + ]
    1079         [ #  # ]:           0 :             (self_join && bms_equal(uniqueRelInfo->outerrelids, outerrelids) &&
    1080         [ #  # ]:           0 :              uniqueRelInfo->self_join))
    1081                 :             :         {
    1082         [ -  + ]:       72439 :             if (extra_clauses)
    1083                 :           0 :                 *extra_clauses = uniqueRelInfo->extra_clauses;
    1084                 :       72439 :             return true;        /* Success! */
    1085                 :             :         }
    1086                 :             :     }
    1087                 :             : 
    1088                 :             :     /*
    1089                 :             :      * Conversely, we may have already determined that this outerrel, or some
    1090                 :             :      * superset thereof, cannot prove this innerrel to be unique.
    1091                 :             :      */
    1092   [ +  +  +  +  :      169934 :     foreach(lc, innerrel->non_unique_for_rels)
                   +  + ]
    1093                 :             :     {
    1094                 :         668 :         Relids      unique_for_rels = (Relids) lfirst(lc);
    1095                 :             : 
    1096         [ +  + ]:         668 :         if (bms_is_subset(outerrelids, unique_for_rels))
    1097                 :         302 :             return false;
    1098                 :             :     }
    1099                 :             : 
    1100                 :             :     /* No cached information, so try to make the proof. */
    1101   [ +  +  +  + ]:      169266 :     if (is_innerrel_unique_for(root, joinrelids, outerrelids, innerrel,
    1102                 :             :                                jointype, restrictlist,
    1103                 :             :                                self_join ? &outer_exprs : NULL))
    1104                 :             :     {
    1105                 :             :         /*
    1106                 :             :          * Cache the positive result for future probes, being sure to keep it
    1107                 :             :          * in the planner_cxt even if we are working in GEQO.
    1108                 :             :          *
    1109                 :             :          * Note: one might consider trying to isolate the minimal subset of
    1110                 :             :          * the outerrels that proved the innerrel unique.  But it's not worth
    1111                 :             :          * the trouble, because the planner builds up joinrels incrementally
    1112                 :             :          * and so we'll see the minimally sufficient outerrels before any
    1113                 :             :          * supersets of them anyway.
    1114                 :             :          */
    1115                 :       97197 :         old_context = MemoryContextSwitchTo(root->planner_cxt);
    1116                 :       97197 :         uniqueRelInfo = makeNode(UniqueRelInfo);
    1117                 :       97197 :         uniqueRelInfo->outerrelids = bms_copy(outerrelids);
    1118                 :       97197 :         uniqueRelInfo->self_join = self_join;
    1119                 :       97197 :         uniqueRelInfo->extra_clauses = outer_exprs;
    1120                 :       97197 :         innerrel->unique_for_rels = lappend(innerrel->unique_for_rels,
    1121                 :             :                                             uniqueRelInfo);
    1122                 :       97197 :         MemoryContextSwitchTo(old_context);
    1123                 :             : 
    1124         [ +  + ]:       97197 :         if (extra_clauses)
    1125                 :         523 :             *extra_clauses = outer_exprs;
    1126                 :       97197 :         return true;            /* Success! */
    1127                 :             :     }
    1128                 :             :     else
    1129                 :             :     {
    1130                 :             :         /*
    1131                 :             :          * None of the join conditions for outerrel proved innerrel unique, so
    1132                 :             :          * we can safely reject this outerrel or any subset of it in future
    1133                 :             :          * checks.
    1134                 :             :          *
    1135                 :             :          * However, in normal planning mode, caching this knowledge is totally
    1136                 :             :          * pointless; it won't be queried again, because we build up joinrels
    1137                 :             :          * from smaller to larger.  It's only useful when using GEQO or
    1138                 :             :          * another planner extension that attempts planning multiple times.
    1139                 :             :          *
    1140                 :             :          * Also, allow callers to override that heuristic and force caching;
    1141                 :             :          * that's useful for reduce_unique_semijoins, which calls here before
    1142                 :             :          * the normal join search starts.
    1143                 :             :          */
    1144   [ +  +  -  + ]:       72069 :         if (force_cache || root->assumeReplanning)
    1145                 :             :         {
    1146                 :        3146 :             old_context = MemoryContextSwitchTo(root->planner_cxt);
    1147                 :        3146 :             innerrel->non_unique_for_rels =
    1148                 :        3146 :                 lappend(innerrel->non_unique_for_rels,
    1149                 :        3146 :                         bms_copy(outerrelids));
    1150                 :        3146 :             MemoryContextSwitchTo(old_context);
    1151                 :             :         }
    1152                 :             : 
    1153                 :       72069 :         return false;
    1154                 :             :     }
    1155                 :             : }
    1156                 :             : 
    1157                 :             : /*
    1158                 :             :  * is_innerrel_unique_for
    1159                 :             :  *    Check if the innerrel provably contains at most one tuple matching any
    1160                 :             :  *    tuple from the outerrel, based on join clauses in the 'restrictlist'.
    1161                 :             :  */
    1162                 :             : static bool
    1163                 :      169266 : is_innerrel_unique_for(PlannerInfo *root,
    1164                 :             :                        Relids joinrelids,
    1165                 :             :                        Relids outerrelids,
    1166                 :             :                        RelOptInfo *innerrel,
    1167                 :             :                        JoinType jointype,
    1168                 :             :                        List *restrictlist,
    1169                 :             :                        List **extra_clauses)
    1170                 :             : {
    1171                 :      169266 :     List       *clause_list = NIL;
    1172                 :             :     ListCell   *lc;
    1173                 :             : 
    1174                 :             :     /*
    1175                 :             :      * Search for mergejoinable clauses that constrain the inner rel against
    1176                 :             :      * the outer rel.  If an operator is mergejoinable then it behaves like
    1177                 :             :      * equality for some btree opclass, so it's what we want.  The
    1178                 :             :      * mergejoinability test also eliminates clauses containing volatile
    1179                 :             :      * functions, which we couldn't depend on.
    1180                 :             :      */
    1181   [ +  -  +  +  :      379588 :     foreach(lc, restrictlist)
                   +  + ]
    1182                 :             :     {
    1183                 :      210322 :         RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(lc);
    1184                 :             : 
    1185                 :             :         /*
    1186                 :             :          * As noted above, if it's a pushed-down clause and we're at an outer
    1187                 :             :          * join, we can't use it.
    1188                 :             :          */
    1189         [ +  + ]:      210322 :         if (IS_OUTER_JOIN(jointype) &&
    1190   [ +  +  -  + ]:       86383 :             RINFO_IS_PUSHED_DOWN(restrictinfo, joinrelids))
    1191                 :        7592 :             continue;
    1192                 :             : 
    1193                 :             :         /* Ignore if it's not a mergejoinable clause */
    1194         [ +  + ]:      202730 :         if (!restrictinfo->can_join ||
    1195         [ +  + ]:      189724 :             restrictinfo->mergeopfamilies == NIL)
    1196                 :       13720 :             continue;           /* not mergejoinable */
    1197                 :             : 
    1198                 :             :         /*
    1199                 :             :          * Check if the clause has the form "outer op inner" or "inner op
    1200                 :             :          * outer", and if so mark which side is inner.
    1201                 :             :          */
    1202         [ +  + ]:      189010 :         if (!clause_sides_match_join(restrictinfo, outerrelids,
    1203                 :             :                                      innerrel->relids))
    1204                 :          20 :             continue;           /* no good for these input relations */
    1205                 :             : 
    1206                 :             :         /* OK, add to the list */
    1207                 :      188990 :         clause_list = lappend(clause_list, restrictinfo);
    1208                 :             :     }
    1209                 :             : 
    1210                 :             :     /* Let rel_is_distinct_for() do the hard work */
    1211                 :      169266 :     return rel_is_distinct_for(root, innerrel, clause_list, extra_clauses);
    1212                 :             : }
    1213                 :             : 
    1214                 :             : /*
    1215                 :             :  * Remove the toRemove relation after we have proven that it participates only
    1216                 :             :  * in an unneeded unique self-join with toKeep.
    1217                 :             :  *
    1218                 :             :  * The removal is done by deleting the relation's RangeTblRef from the
    1219                 :             :  * jointree and then pointing everything that referenced it at the relation we
    1220                 :             :  * are keeping.  All the conditions that were attached to the removed relation
    1221                 :             :  * thereby become conditions on the remaining one, which is what we want:
    1222                 :             :  * we've proven that the two relations select the same rows.  Note that
    1223                 :             :  * this change requires us to hoist those conditions up to someplace
    1224                 :             :  * syntactically enclosing toKeep.
    1225                 :             :  *
    1226                 :             :  * kmark and rmark are the PlanRowMarks (if any) for the kept and removed
    1227                 :             :  * relations.  We could re-locate those, but the caller already found them.
    1228                 :             :  */
    1229                 :             : static void
    1230                 :         468 : remove_self_join_rel(PlannerInfo *root,
    1231                 :             :                      RelOptInfo *toKeep, RelOptInfo *toRemove,
    1232                 :             :                      PlanRowMark *kmark, PlanRowMark *rmark)
    1233                 :             : {
    1234                 :         468 :     Node       *orphan_quals = NULL;
    1235                 :         468 :     int         nremoved = 0;
    1236                 :         468 :     Node       *hoist_quals = NULL;
    1237                 :         468 :     bool        found_relid = false;
    1238                 :             : 
    1239                 :             :     Assert(toKeep->relid > 0);
    1240                 :             :     Assert(toRemove->relid > 0);
    1241                 :             : 
    1242                 :             :     /* We verify that exactly one reference gets removed from the jointree */
    1243                 :         936 :     root->parse->jointree = (FromExpr *)
    1244                 :         468 :         remove_rel_from_jointree((Node *) root->parse->jointree,
    1245                 :         468 :                                  toRemove->relid,
    1246                 :             :                                  &orphan_quals, &nremoved);
    1247         [ -  + ]:         468 :     if (nremoved != 1)
    1248         [ #  # ]:           0 :         elog(ERROR, "failed to find relation %d in jointree", toRemove->relid);
    1249                 :             :     /* The topmost FromExpr can't have gone away, so nothing can be orphaned */
    1250                 :             :     Assert(root->parse->jointree != NULL);
    1251                 :             :     Assert(orphan_quals == NULL);
    1252                 :             : 
    1253                 :             :     /*
    1254                 :             :      * Replace all references to the removed relation.  Note that this must
    1255                 :             :      * happen after the jointree surgery, else we'd not be able to tell the
    1256                 :             :      * two relations' RangeTblRefs apart.
    1257                 :             :      */
    1258                 :         468 :     ChangeVarNodes((Node *) root->parse, toRemove->relid, toKeep->relid, 0);
    1259                 :             : 
    1260                 :             :     /*
    1261                 :             :      * processed_tlist shares some but not all of its nodes with
    1262                 :             :      * parse->targetList, so it has to be processed separately.  (That's
    1263                 :             :      * harmless: ChangeVarNodes works in-place, and the second visit to a
    1264                 :             :      * shared node finds nothing to change.)
    1265                 :             :      */
    1266                 :         468 :     ChangeVarNodes((Node *) root->processed_tlist, toRemove->relid,
    1267                 :         468 :                    toKeep->relid, 0);
    1268                 :             : 
    1269                 :             :     /* There could be references in the append_rel_list, too */
    1270         [ -  + ]:         468 :     if (root->append_rel_list != NIL)
    1271                 :           0 :         ChangeVarNodes((Node *) root->append_rel_list, toRemove->relid,
    1272                 :           0 :                        toKeep->relid, 0);
    1273                 :             : 
    1274                 :             :     /*
    1275                 :             :      * As in remove_useless_outer_joins, discard the securityQuals of the
    1276                 :             :      * removed rel, so that later passes don't visit them.  We know the kept
    1277                 :             :      * rel has the same quals.  (tablesample is already known NULL.)
    1278                 :             :      */
    1279                 :         468 :     root->simple_rte_array[toRemove->relid]->securityQuals = NIL;
    1280                 :             : 
    1281                 :             :     /* Clean up the quals that the substitution has messed with */
    1282                 :         468 :     fixup_selfjoin_jointree(root, (Node *) root->parse->jointree,
    1283                 :         468 :                             toKeep->relid,
    1284                 :             :                             &hoist_quals, &found_relid);
    1285                 :             :     /* We shouldn't have any leftover quals, and we must have found toKeep */
    1286                 :             :     Assert(hoist_quals == NULL);
    1287                 :             :     Assert(found_relid);
    1288                 :             : 
    1289                 :             :     /*
    1290                 :             :      * If the removed relation has a row mark, transfer it to the remaining
    1291                 :             :      * one.
    1292                 :             :      *
    1293                 :             :      * If both rels have row marks, just keep the one corresponding to the
    1294                 :             :      * remaining relation because we verified earlier that they have the same
    1295                 :             :      * strength.
    1296                 :             :      */
    1297         [ +  + ]:         468 :     if (rmark)
    1298                 :             :     {
    1299         [ +  - ]:          36 :         if (kmark)
    1300                 :             :         {
    1301                 :             :             Assert(kmark->markType == rmark->markType);
    1302                 :             : 
    1303                 :          36 :             root->rowMarks = list_delete_ptr(root->rowMarks, rmark);
    1304                 :             :         }
    1305                 :             :         else
    1306                 :             :         {
    1307                 :             :             /* Shouldn't have inheritance children yet. */
    1308                 :             :             Assert(rmark->rti == rmark->prti);
    1309                 :             : 
    1310                 :           0 :             rmark->rti = rmark->prti = toKeep->relid;
    1311                 :             :         }
    1312                 :             :     }
    1313                 :         468 : }
    1314                 :             : 
    1315                 :             : /*
    1316                 :             :  * remove_rel_from_jointree
    1317                 :             :  *      Delete the RangeTblRef for the given relation from the query's
    1318                 :             :  *      jointree.
    1319                 :             :  *
    1320                 :             :  * This is used for self-join elimination, where the removed relation's
    1321                 :             :  * qual conditions must all be preserved (they will be transposed onto the
    1322                 :             :  * remaining relation afterwards).  Hence, if dropping the RangeTblRef leaves
    1323                 :             :  * a JoinExpr or FromExpr with nothing under it, we can't simply drop that
    1324                 :             :  * node; we hand its quals back to the caller in *orphan_quals, to be merged
    1325                 :             :  * into the nearest enclosing node that still has some content.  That's a
    1326                 :             :  * valid transformation only for inner joins, but a jointree node can't become
    1327                 :             :  * empty at an outer join here: remove_self_joins_one_group() insists that the
    1328                 :             :  * two relations be on the same side of every outer join, so the relation we
    1329                 :             :  * are keeping would have to be in the emptied subtree too.
    1330                 :             :  *
    1331                 :             :  * *nremoved is incremented by the number of RangeTblRefs removed (there
    1332                 :             :  * should be exactly one, but the caller checks that).
    1333                 :             :  */
    1334                 :             : static Node *
    1335                 :        2285 : remove_rel_from_jointree(Node *jtnode, int relid,
    1336                 :             :                          Node **orphan_quals, int *nremoved)
    1337                 :             : {
    1338         [ -  + ]:        2285 :     if (jtnode == NULL)
    1339                 :           0 :         return NULL;
    1340         [ +  + ]:        2285 :     if (IsA(jtnode, RangeTblRef))
    1341                 :             :     {
    1342                 :        1189 :         RangeTblRef *rtr = (RangeTblRef *) jtnode;
    1343                 :             : 
    1344         [ +  + ]:        1189 :         if (rtr->rtindex == relid)
    1345                 :             :         {
    1346                 :         468 :             (*nremoved)++;
    1347                 :         468 :             return NULL;
    1348                 :             :         }
    1349                 :             :     }
    1350         [ +  + ]:        1096 :     else if (IsA(jtnode, FromExpr))
    1351                 :             :     {
    1352                 :         570 :         FromExpr   *f = (FromExpr *) jtnode;
    1353                 :         570 :         List       *newfromlist = NIL;
    1354                 :         570 :         Node       *sub_orphans = NULL;
    1355                 :             :         ListCell   *l;
    1356                 :             : 
    1357   [ +  -  +  +  :        1335 :         foreach(l, f->fromlist)
                   +  + ]
    1358                 :             :         {
    1359                 :             :             Node       *newchild;
    1360                 :             : 
    1361                 :         765 :             newchild = remove_rel_from_jointree((Node *) lfirst(l), relid,
    1362                 :             :                                                 &sub_orphans, nremoved);
    1363         [ +  + ]:         765 :             if (newchild != NULL)
    1364                 :         578 :                 newfromlist = lappend(newfromlist, newchild);
    1365                 :             :         }
    1366                 :         570 :         f->fromlist = newfromlist;
    1367                 :         570 :         f->quals = merge_quals(sub_orphans, f->quals);
    1368         [ +  + ]:         570 :         if (newfromlist == NIL)
    1369                 :             :         {
    1370                 :             :             /* Nothing left here, so pass our quals up to the parent */
    1371                 :          32 :             *orphan_quals = merge_quals(f->quals, *orphan_quals);
    1372                 :          32 :             return NULL;
    1373                 :             :         }
    1374                 :             :     }
    1375         [ +  - ]:         526 :     else if (IsA(jtnode, JoinExpr))
    1376                 :             :     {
    1377                 :         526 :         JoinExpr   *j = (JoinExpr *) jtnode;
    1378                 :         526 :         Node       *sub_orphans = NULL;
    1379                 :             : 
    1380                 :         526 :         j->larg = remove_rel_from_jointree(j->larg, relid,
    1381                 :             :                                            &sub_orphans, nremoved);
    1382                 :         526 :         j->rarg = remove_rel_from_jointree(j->rarg, relid,
    1383                 :             :                                            &sub_orphans, nremoved);
    1384   [ +  +  +  + ]:         526 :         if (j->larg == NULL || j->rarg == NULL)
    1385                 :             :         {
    1386         [ +  + ]:         313 :             Node       *surviving = (j->larg != NULL) ? j->larg : j->rarg;
    1387                 :         313 :             Node       *quals = merge_quals(sub_orphans, j->quals);
    1388                 :             : 
    1389                 :             :             /* As explained above, this can only happen for an inner join */
    1390                 :             :             Assert(j->jointype == JOIN_INNER);
    1391                 :             :             /* We can't have removed both children */
    1392                 :             :             Assert(surviving != NULL);
    1393                 :             : 
    1394                 :             :             /*
    1395                 :             :              * Replace the join by a FromExpr, so that the surviving side's
    1396                 :             :              * rows are still filtered by the join's conditions.
    1397                 :             :              */
    1398                 :         313 :             return (Node *) makeFromExpr(list_make1(surviving), quals);
    1399                 :             :         }
    1400                 :             :         /* A subtree that survives never hands any quals back to us */
    1401                 :             :         Assert(sub_orphans == NULL);
    1402                 :             :     }
    1403                 :             :     else
    1404         [ #  # ]:           0 :         elog(ERROR, "unrecognized jointree node type: %d",
    1405                 :             :              (int) nodeTag(jtnode));
    1406                 :             : 
    1407                 :        1472 :     return jtnode;
    1408                 :             : }
    1409                 :             : 
    1410                 :             : /*
    1411                 :             :  * merge_quals
    1412                 :             :  *      Combine two jointree qual conditions.
    1413                 :             :  *
    1414                 :             :  * quals1 should be the quals from the lower of the two jointree levels,
    1415                 :             :  * so that those quals get applied first.
    1416                 :             :  *
    1417                 :             :  * Jointree quals have been through preprocess_expression() by now, so each
    1418                 :             :  * one is either NULL or an implicitly-ANDed List.
    1419                 :             :  */
    1420                 :             : static Node *
    1421                 :        2029 : merge_quals(Node *quals1, Node *quals2)
    1422                 :             : {
    1423         [ +  + ]:        2029 :     if (quals1 == NULL)
    1424                 :        1959 :         return quals2;
    1425         [ +  + ]:          70 :     if (quals2 == NULL)
    1426                 :          40 :         return quals1;
    1427                 :          30 :     return (Node *) list_concat(castNode(List, quals1),
    1428                 :             :                                 castNode(List, quals2));
    1429                 :             : }
    1430                 :             : 
    1431                 :             : /*
    1432                 :             :  * fixup_selfjoin_jointree
    1433                 :             :  *      Clean up the query's jointree quals after self-join elimination has
    1434                 :             :  *      merged one relation into another.  (relid is the kept relation.)
    1435                 :             :  *
    1436                 :             :  * See fixup_selfjoin_quals() for what needs fixing locally to each qual list.
    1437                 :             :  * In addition, we need to check quals to see if they refer to relid, and if
    1438                 :             :  * so make sure they get hoisted to someplace syntactically above relid.
    1439                 :             :  * Do that using a "hoist_quals" in/out parameter similar to "orphan_quals"
    1440                 :             :  * in remove_rel_from_jointree.  (We can't readily merge these concerns into
    1441                 :             :  * a single pass, since remove_rel_from_jointree must run before we relabel
    1442                 :             :  * the removed rel's Vars.)  In addition, *found_relid is set true if
    1443                 :             :  * the subtree rooted at jtnode is found to contain relid's RangeTblRef,
    1444                 :             :  * so that we can tell when to stop hoisting quals.
    1445                 :             :  * If a qual gets hoisted up, we apply fixup_selfjoin_quals() to it only
    1446                 :             :  * after it reaches its final level.  This rule improves the odds of
    1447                 :             :  * detecting duplicate quals.
    1448                 :             :  */
    1449                 :             : static void
    1450                 :        1785 : fixup_selfjoin_jointree(PlannerInfo *root, Node *jtnode, int relid,
    1451                 :             :                         Node **hoist_quals, bool *found_relid)
    1452                 :             : {
    1453         [ -  + ]:        1785 :     if (jtnode == NULL)
    1454                 :           0 :         return;
    1455         [ +  + ]:        1785 :     if (IsA(jtnode, RangeTblRef))
    1456                 :             :     {
    1457                 :         721 :         RangeTblRef *rtr = (RangeTblRef *) jtnode;
    1458                 :             : 
    1459         [ +  + ]:         721 :         if (rtr->rtindex == relid)
    1460                 :             :         {
    1461                 :             :             Assert(!*found_relid);
    1462                 :         468 :             *found_relid = true;
    1463                 :             :         }
    1464                 :             :     }
    1465         [ +  + ]:        1064 :     else if (IsA(jtnode, FromExpr))
    1466                 :             :     {
    1467                 :         851 :         FromExpr   *f = (FromExpr *) jtnode;
    1468                 :         851 :         Node       *sub_hoist_quals = NULL;
    1469                 :         851 :         bool        sub_found_relid = false;
    1470                 :             :         ListCell   *l;
    1471                 :             : 
    1472   [ +  -  +  +  :        1742 :         foreach(l, f->fromlist)
                   +  + ]
    1473                 :         891 :             fixup_selfjoin_jointree(root, (Node *) lfirst(l), relid,
    1474                 :             :                                     &sub_hoist_quals, &sub_found_relid);
    1475         [ +  + ]:         851 :         if (sub_found_relid)
    1476                 :             :         {
    1477                 :             :             /* This FromExpr covers relid, so OK to stop hoisting quals here */
    1478                 :         816 :             f->quals = merge_quals(sub_hoist_quals, f->quals);
    1479                 :             :             Assert(!*found_relid);
    1480                 :         816 :             *found_relid = true;
    1481                 :             :         }
    1482                 :             :         else
    1483                 :             :         {
    1484                 :             :             /* We might need to hoist some of our own quals too */
    1485                 :          35 :             List       *hoistable = NIL;
    1486                 :          35 :             List       *keepable = NIL;
    1487                 :             : 
    1488   [ +  +  +  +  :         100 :             foreach_ptr(Node, qual, castNode(List, f->quals))
                   +  + ]
    1489                 :             :             {
    1490         [ +  + ]:          30 :                 if (bms_is_member(relid, pull_varnos(root, qual)))
    1491                 :          10 :                     hoistable = lappend(hoistable, qual);
    1492                 :             :                 else
    1493                 :          20 :                     keepable = lappend(keepable, qual);
    1494                 :             :             }
    1495                 :          35 :             f->quals = (Node *) keepable;
    1496                 :          35 :             sub_hoist_quals = merge_quals(sub_hoist_quals, (Node *) hoistable);
    1497                 :          35 :             *hoist_quals = merge_quals(sub_hoist_quals, *hoist_quals);
    1498                 :             :         }
    1499                 :         851 :         f->quals = (Node *) fixup_selfjoin_quals(root,
    1500                 :         851 :                                                  castNode(List, f->quals),
    1501                 :             :                                                  relid);
    1502                 :             :     }
    1503         [ +  - ]:         213 :     else if (IsA(jtnode, JoinExpr))
    1504                 :             :     {
    1505                 :         213 :         JoinExpr   *j = (JoinExpr *) jtnode;
    1506                 :         213 :         Node       *sub_hoist_quals = NULL;
    1507                 :         213 :         bool        sub_found_relid = false;
    1508                 :             : 
    1509                 :         213 :         fixup_selfjoin_jointree(root, j->larg, relid,
    1510                 :             :                                 &sub_hoist_quals, &sub_found_relid);
    1511                 :         213 :         fixup_selfjoin_jointree(root, j->rarg, relid,
    1512                 :             :                                 &sub_hoist_quals, &sub_found_relid);
    1513         [ +  + ]:         213 :         if (sub_found_relid)
    1514                 :             :         {
    1515                 :             :             /* This JoinExpr covers relid, so OK to stop hoisting quals here */
    1516                 :         198 :             j->quals = merge_quals(sub_hoist_quals, j->quals);
    1517                 :             :             Assert(!*found_relid);
    1518                 :         198 :             *found_relid = true;
    1519                 :             :         }
    1520                 :             :         else
    1521                 :             :         {
    1522                 :             :             /* We might need to hoist some of our own quals too */
    1523                 :          15 :             List       *hoistable = NIL;
    1524                 :          15 :             List       *keepable = NIL;
    1525                 :             : 
    1526   [ +  -  +  +  :          45 :             foreach_ptr(Node, qual, castNode(List, j->quals))
                   +  + ]
    1527                 :             :             {
    1528         [ +  + ]:          15 :                 if (bms_is_member(relid, pull_varnos(root, qual)))
    1529                 :           5 :                     hoistable = lappend(hoistable, qual);
    1530                 :             :                 else
    1531                 :          10 :                     keepable = lappend(keepable, qual);
    1532                 :             :             }
    1533                 :          15 :             j->quals = (Node *) keepable;
    1534                 :          15 :             sub_hoist_quals = merge_quals(sub_hoist_quals, (Node *) hoistable);
    1535                 :             :             /* We should never need to hoist quals above an outer join */
    1536                 :             :             Assert(sub_hoist_quals == NULL || j->jointype == JOIN_INNER);
    1537                 :          15 :             *hoist_quals = merge_quals(sub_hoist_quals, *hoist_quals);
    1538                 :             :         }
    1539                 :         213 :         j->quals = (Node *) fixup_selfjoin_quals(root,
    1540                 :         213 :                                                  castNode(List, j->quals),
    1541                 :             :                                                  relid);
    1542                 :             :     }
    1543                 :             :     else
    1544         [ #  # ]:           0 :         elog(ERROR, "unrecognized jointree node type: %d",
    1545                 :             :              (int) nodeTag(jtnode));
    1546                 :             : }
    1547                 :             : 
    1548                 :             : /*
    1549                 :             :  * fixup_selfjoin_quals
    1550                 :             :  *      Clean up one qual list after self-join elimination.
    1551                 :             :  *
    1552                 :             :  * Two things need fixing here.  First, a join clause such as "t1.a = t2.a"
    1553                 :             :  * has turned into "t1.a = t1.a".  For a strict mergejoinable operator that
    1554                 :             :  * means "t1.a IS NOT NULL", and we should make the substitution, for two
    1555                 :             :  * reasons:
    1556                 :             :  * 1. It will typically result in better selectivity estimates.
    1557                 :             :  * 2. EquivalenceClass processing is likely to make the substitution
    1558                 :             :  *    if we don't.  While not directly harmful, we'd then fail to
    1559                 :             :  *    recognize it as a duplicate of a user-written "t1.a IS NOT NULL"
    1560                 :             :  *    clause, again leading to bad selectivity estimates.
    1561                 :             :  * Second, conditions that were written against the two relations separately
    1562                 :             :  * may now be identical, and we don't want to apply the same condition twice
    1563                 :             :  * (much less double-count its selectivity).
    1564                 :             :  *
    1565                 :             :  * We only touch the top-level conjuncts of the list.  There, turning a NULL
    1566                 :             :  * result into FALSE makes no difference, whereas below a NOT it would,
    1567                 :             :  * invalidating the IS NOT NULL substitution.  EquivalenceClass processing
    1568                 :             :  * will not be applied to sub-clauses, and cleaning up duplicates in them
    1569                 :             :  * seems like more trouble than it's worth.  Also, we only consider clauses
    1570                 :             :  * that mention the relation we merged into, so that we don't change the
    1571                 :             :  * treatment of anything we didn't touch.
    1572                 :             :  *
    1573                 :             :  * Since this is not a correctness issue but just an optimization opportunity,
    1574                 :             :  * we likewise don't worry about recognizing duplicates that appear in
    1575                 :             :  * different qual lists.
    1576                 :             :  */
    1577                 :             : static List *
    1578                 :        1064 : fixup_selfjoin_quals(PlannerInfo *root, List *quals, int relid)
    1579                 :             : {
    1580                 :        1064 :     List       *result = NIL;
    1581                 :             :     ListCell   *l;
    1582                 :             : 
    1583   [ +  +  +  +  :        2151 :     foreach(l, quals)
                   +  + ]
    1584                 :             :     {
    1585                 :        1087 :         Node       *qual = (Node *) lfirst(l);
    1586                 :             : 
    1587         [ +  + ]:        1087 :         if (bms_is_member(relid, pull_varnos(root, qual)))
    1588                 :             :         {
    1589                 :        1017 :             qual = replace_selfjoin_qual(qual);
    1590                 :             :             /* Drop it if the substitution has made it a duplicate */
    1591         [ +  + ]:        1017 :             if (list_member(result, qual))
    1592                 :          77 :                 continue;
    1593                 :             :         }
    1594                 :        1010 :         result = lappend(result, qual);
    1595                 :             :     }
    1596                 :             : 
    1597                 :        1064 :     return result;
    1598                 :             : }
    1599                 :             : 
    1600                 :             : /*
    1601                 :             :  * replace_selfjoin_qual
    1602                 :             :  *      Replace one "X = X" qual by "X IS NOT NULL", if it is one.
    1603                 :             :  */
    1604                 :             : static Node *
    1605                 :        1017 : replace_selfjoin_qual(Node *qual)
    1606                 :             : {
    1607                 :             :     OpExpr     *opexpr;
    1608                 :             :     Node       *leftop;
    1609                 :             :     Node       *rightop;
    1610                 :             :     NullTest   *ntest;
    1611                 :             : 
    1612                 :             :     /* See if it looks like "X op X" */
    1613         [ +  + ]:        1017 :     if (!is_opclause(qual))
    1614                 :         105 :         return qual;
    1615                 :         912 :     opexpr = (OpExpr *) qual;
    1616         [ -  + ]:         912 :     if (list_length(opexpr->args) != 2)
    1617                 :           0 :         return qual;
    1618                 :         912 :     leftop = get_leftop((Expr *) opexpr);
    1619                 :         912 :     rightop = get_rightop((Expr *) opexpr);
    1620         [ +  + ]:         912 :     if (!equal(leftop, rightop))
    1621                 :         379 :         return qual;
    1622                 :             : 
    1623                 :             :     /*
    1624                 :             :      * The operator must be strict and behave like btree equality, else we
    1625                 :             :      * can't conclude that it yields true for any non-null input.  And the
    1626                 :             :      * input had better not be volatile, else the two evaluations might not
    1627                 :             :      * agree.  If either condition doesn't hold, the clause is not a candidate
    1628                 :             :      * to be an equivalence, so we needn't worry about it getting replaced by
    1629                 :             :      * equivclass.c.
    1630                 :             :      */
    1631                 :         533 :     set_opfuncid(opexpr);
    1632         [ -  + ]:         533 :     if (!func_strict(opexpr->opfuncid))
    1633                 :           0 :         return qual;
    1634         [ +  + ]:         533 :     if (!op_mergejoinable(opexpr->opno, exprType(leftop)))
    1635                 :           5 :         return qual;
    1636         [ -  + ]:         528 :     if (contain_volatile_functions(leftop))
    1637                 :           0 :         return qual;
    1638                 :             : 
    1639                 :             :     /* OK, replace it */
    1640                 :         528 :     ntest = makeNode(NullTest);
    1641                 :         528 :     ntest->arg = (Expr *) leftop;
    1642                 :         528 :     ntest->nulltesttype = IS_NOT_NULL;
    1643                 :         528 :     ntest->argisrow = false; /* correct even if composite arg */
    1644                 :         528 :     ntest->location = -1;
    1645                 :         528 :     return (Node *) ntest;
    1646                 :             : }
    1647                 :             : 
    1648                 :             : /*
    1649                 :             :  * split_selfjoin_quals
    1650                 :             :  *      Processes 'joinquals' by building two lists: one containing the quals
    1651                 :             :  *      where the columns/exprs are on either side of the join match and
    1652                 :             :  *      another one containing the remaining quals.
    1653                 :             :  *
    1654                 :             :  * 'joinquals' must only contain quals for a RTE_RELATION being joined to
    1655                 :             :  * itself.
    1656                 :             :  */
    1657                 :             : static void
    1658                 :        1856 : split_selfjoin_quals(PlannerInfo *root, List *joinquals, List **selfjoinquals,
    1659                 :             :                      List **otherjoinquals, int from, int to)
    1660                 :             : {
    1661                 :        1856 :     List       *sjoinquals = NIL;
    1662                 :        1856 :     List       *ojoinquals = NIL;
    1663                 :             : 
    1664   [ +  -  +  +  :        5768 :     foreach_node(RestrictInfo, rinfo, joinquals)
                   +  + ]
    1665                 :             :     {
    1666                 :             :         OpExpr     *expr;
    1667                 :             :         Node       *leftexpr;
    1668                 :             :         Node       *rightexpr;
    1669                 :             : 
    1670                 :             :         /*
    1671                 :             :          * Since the given joinquals all came from
    1672                 :             :          * generate_join_implied_equalities, they ought to look like equality
    1673                 :             :          * operators on single-relation expressions.  But let's check that.
    1674                 :             :          * Anything that doesn't look like that can be dumped into ojoinquals.
    1675                 :             :          */
    1676   [ +  -  +  - ]:        4112 :         if (!rinfo->mergeopfamilies ||
    1677         [ +  - ]:        4112 :             bms_num_members(rinfo->clause_relids) != 2 ||
    1678         [ -  + ]:        4112 :             bms_membership(rinfo->left_relids) != BMS_SINGLETON ||
    1679                 :        2056 :             bms_membership(rinfo->right_relids) != BMS_SINGLETON)
    1680                 :             :         {
    1681                 :           0 :             ojoinquals = lappend(ojoinquals, rinfo);
    1682                 :           0 :             continue;
    1683                 :             :         }
    1684                 :             : 
    1685                 :        2056 :         expr = (OpExpr *) rinfo->clause;
    1686                 :             : 
    1687   [ +  -  -  + ]:        2056 :         if (!IsA(expr, OpExpr) || list_length(expr->args) != 2)
    1688                 :             :         {
    1689                 :           0 :             ojoinquals = lappend(ojoinquals, rinfo);
    1690                 :           0 :             continue;
    1691                 :             :         }
    1692                 :             : 
    1693                 :        2056 :         leftexpr = get_leftop(rinfo->clause);
    1694                 :        2056 :         rightexpr = copyObject(get_rightop(rinfo->clause));
    1695                 :             : 
    1696   [ +  -  +  + ]:        2056 :         if (leftexpr && IsA(leftexpr, RelabelType))
    1697                 :          20 :             leftexpr = (Node *) ((RelabelType *) leftexpr)->arg;
    1698   [ +  -  +  + ]:        2056 :         if (rightexpr && IsA(rightexpr, RelabelType))
    1699                 :          15 :             rightexpr = (Node *) ((RelabelType *) rightexpr)->arg;
    1700                 :             : 
    1701                 :             :         /*
    1702                 :             :          * Quite an expensive operation, narrowing the use case. For example,
    1703                 :             :          * when we have cast of the same var to different (but compatible)
    1704                 :             :          * types.
    1705                 :             :          */
    1706                 :        2056 :         ChangeVarNodes(rightexpr,
    1707                 :        2056 :                        bms_singleton_member(rinfo->right_relids),
    1708                 :        2056 :                        bms_singleton_member(rinfo->left_relids), 0);
    1709                 :             : 
    1710         [ +  + ]:        2056 :         if (equal(leftexpr, rightexpr))
    1711                 :        1466 :             sjoinquals = lappend(sjoinquals, rinfo);
    1712                 :             :         else
    1713                 :         590 :             ojoinquals = lappend(ojoinquals, rinfo);
    1714                 :             :     }
    1715                 :             : 
    1716                 :        1856 :     *selfjoinquals = sjoinquals;
    1717                 :        1856 :     *otherjoinquals = ojoinquals;
    1718                 :        1856 : }
    1719                 :             : 
    1720                 :             : /*
    1721                 :             :  * Check that each base restriction used to prove uniqueness of relid has
    1722                 :             :  * a matching restriction in outer->baserestrictinfo, after replacing
    1723                 :             :  * relid with outer->relid.
    1724                 :             :  *
    1725                 :             :  * Require equal() clauses, including the operator and input collation.
    1726                 :             :  * Formerly this tried to match commuted forms of clauses, but that added
    1727                 :             :  * a great deal of extra complication without much extra value.
    1728                 :             :  */
    1729                 :             : static bool
    1730                 :         523 : match_unique_clauses(PlannerInfo *root, RelOptInfo *outer, List *uclauses,
    1731                 :             :                      Index relid)
    1732                 :             : {
    1733                 :             :     Assert(outer->relid > 0 && relid > 0);
    1734                 :             : 
    1735   [ +  +  +  +  :        1061 :     foreach_node(RestrictInfo, rinfo, uclauses)
                   +  + ]
    1736                 :             :     {
    1737                 :             :         Expr       *clause;
    1738                 :         125 :         bool        matched = false;
    1739                 :             : 
    1740                 :             :         /* Convert the clause from uclauses to use outer's Vars */
    1741                 :         125 :         clause = (Expr *) copyObject(rinfo->clause);
    1742                 :         125 :         ChangeVarNodes((Node *) clause, relid, outer->relid, 0);
    1743                 :             : 
    1744                 :             :         /* Look for a matching restriction on the outer relation */
    1745   [ +  +  +  +  :         330 :         foreach_node(RestrictInfo, orinfo, outer->baserestrictinfo)
                   +  + ]
    1746                 :             :         {
    1747         [ +  + ]:         150 :             if (equal(clause, orinfo->clause))
    1748                 :             :             {
    1749                 :          70 :                 matched = true;
    1750                 :          70 :                 break;
    1751                 :             :             }
    1752                 :             :         }
    1753                 :             : 
    1754         [ +  + ]:         125 :         if (!matched)
    1755                 :          55 :             return false;
    1756                 :             :     }
    1757                 :             : 
    1758                 :         468 :     return true;
    1759                 :             : }
    1760                 :             : 
    1761                 :             : /*
    1762                 :             :  * Find and remove unique self-joins in a group of base relations that have
    1763                 :             :  * the same Oid.
    1764                 :             :  *
    1765                 :             :  * Return true if we removed any joins.
    1766                 :             :  *
    1767                 :             :  * After a removal, we continue searching for more removals, even though the
    1768                 :             :  * tests will be using derived data that is now partially stale.  That is safe
    1769                 :             :  * because we are trying to prove that a candidate pair of relations must
    1770                 :             :  * match the same row, and the stale data can only omit quals, never invent
    1771                 :             :  * them.  The removed relation's quals are moved onto the kept relation in
    1772                 :             :  * the jointree but not into its baserestrictinfo, and no other derived data
    1773                 :             :  * changes.  A proof made from a subset of the applicable quals remains valid
    1774                 :             :  * when the rest are added, since extra quals can only remove rows from the
    1775                 :             :  * join.  So a pass may miss a removal that a later pass will find, but it
    1776                 :             :  * cannot make one that isn't justified.
    1777                 :             :  */
    1778                 :             : static bool
    1779                 :        8820 : remove_self_joins_one_group(PlannerInfo *root, Relids relids)
    1780                 :             : {
    1781                 :        8820 :     bool        removed = false;
    1782                 :             :     int         k;              /* Index of kept relation */
    1783                 :        8820 :     int         r = -1;         /* Index of removed relation */
    1784                 :             : 
    1785         [ +  + ]:       27652 :     while ((r = bms_next_member(relids, r)) > 0)
    1786                 :             :     {
    1787                 :       18832 :         RelOptInfo *rrel = root->simple_rel_array[r];
    1788                 :             : 
    1789                 :             :         /* k iterates over the relids after r */
    1790                 :       18832 :         k = r;
    1791         [ +  + ]:       29814 :         while ((k = bms_next_member(relids, k)) > 0)
    1792                 :             :         {
    1793                 :       11450 :             Relids      joinrelids = NULL;
    1794                 :       11450 :             RelOptInfo *krel = root->simple_rel_array[k];
    1795                 :             :             List       *restrictlist;
    1796                 :             :             List       *selfjoinquals;
    1797                 :             :             List       *otherjoinquals;
    1798                 :             :             ListCell   *lc;
    1799                 :       11450 :             bool        jinfo_check = true;
    1800                 :       11450 :             PlanRowMark *kmark = NULL;
    1801                 :       11450 :             PlanRowMark *rmark = NULL;
    1802                 :       11450 :             List       *uclauses = NIL;
    1803                 :             : 
    1804                 :             :             /* A sanity check: the relations have the same Oid. */
    1805                 :             :             Assert(root->simple_rte_array[k]->relid ==
    1806                 :             :                    root->simple_rte_array[r]->relid);
    1807                 :             : 
    1808                 :             :             /*
    1809                 :             :              * It is impossible to eliminate the join of two relations if they
    1810                 :             :              * are not on the same side of every outer join.  Otherwise, the
    1811                 :             :              * planner can't find any variants of the correct query plan.
    1812                 :             :              */
    1813   [ +  +  +  +  :       14093 :             foreach(lc, root->join_info_list)
                   +  + ]
    1814                 :             :             {
    1815                 :        9044 :                 SpecialJoinInfo *info = (SpecialJoinInfo *) lfirst(lc);
    1816                 :             : 
    1817         [ +  + ]:       18088 :                 if ((bms_is_member(k, info->syn_lefthand) ^
    1818         [ +  + ]:       12760 :                      bms_is_member(r, info->syn_lefthand)) ||
    1819                 :        3716 :                     (bms_is_member(k, info->syn_righthand) ^
    1820                 :        3716 :                      bms_is_member(r, info->syn_righthand)))
    1821                 :             :                 {
    1822                 :        6401 :                     jinfo_check = false;
    1823                 :        6401 :                     break;
    1824                 :             :                 }
    1825                 :             :             }
    1826         [ +  + ]:       11450 :             if (!jinfo_check)
    1827                 :       10982 :                 continue;
    1828                 :             : 
    1829                 :             :             /*
    1830                 :             :              * Check Row Marks equivalence. We can't remove the join if the
    1831                 :             :              * relations have row marks of different strength (e.g., one is
    1832                 :             :              * locked FOR UPDATE, and another just has ROW_MARK_REFERENCE for
    1833                 :             :              * EvalPlanQual rechecking).
    1834                 :             :              */
    1835   [ +  +  +  -  :        5150 :             foreach(lc, root->rowMarks)
                   +  + ]
    1836                 :             :             {
    1837                 :         187 :                 PlanRowMark *rowMark = (PlanRowMark *) lfirst(lc);
    1838                 :             : 
    1839         [ +  + ]:         187 :                 if (rowMark->rti == r)
    1840                 :             :                 {
    1841                 :             :                     Assert(rmark == NULL);
    1842                 :          86 :                     rmark = rowMark;
    1843                 :             :                 }
    1844         [ +  + ]:         101 :                 else if (rowMark->rti == k)
    1845                 :             :                 {
    1846                 :             :                     Assert(kmark == NULL);
    1847                 :          86 :                     kmark = rowMark;
    1848                 :             :                 }
    1849                 :             : 
    1850   [ +  +  +  - ]:         187 :                 if (kmark && rmark)
    1851                 :          86 :                     break;
    1852                 :             :             }
    1853   [ +  +  +  -  :        5049 :             if (kmark && rmark && kmark->markType != rmark->markType)
                   +  + ]
    1854                 :          23 :                 continue;
    1855                 :             : 
    1856                 :             :             /*
    1857                 :             :              * We only deal with base rels here, so their relids bitset
    1858                 :             :              * contains only one member -- their relid.
    1859                 :             :              */
    1860                 :        5026 :             joinrelids = bms_add_member(joinrelids, r);
    1861                 :        5026 :             joinrelids = bms_add_member(joinrelids, k);
    1862                 :             : 
    1863                 :             :             /*
    1864                 :             :              * PHVs should not impose any constraints on removing self-joins.
    1865                 :             :              */
    1866                 :             : 
    1867                 :             :             /*
    1868                 :             :              * At this stage, joininfo lists of inner and outer can contain
    1869                 :             :              * only clauses required for a superior outer join that can't
    1870                 :             :              * influence this optimization. So, we can avoid to call the
    1871                 :             :              * build_joinrel_restrictlist() routine.
    1872                 :             :              */
    1873                 :        5026 :             restrictlist = generate_join_implied_equalities(root, joinrelids,
    1874                 :             :                                                             rrel->relids,
    1875                 :             :                                                             krel, NULL);
    1876         [ +  + ]:        5026 :             if (restrictlist == NIL)
    1877                 :        3170 :                 continue;
    1878                 :             : 
    1879                 :             :             /*
    1880                 :             :              * Process restrictlist to separate the self-join quals from the
    1881                 :             :              * other quals. e.g., "x = x" goes to selfjoinquals and "a = b" to
    1882                 :             :              * otherjoinquals.
    1883                 :             :              */
    1884                 :        1856 :             split_selfjoin_quals(root, restrictlist, &selfjoinquals,
    1885                 :        1856 :                                  &otherjoinquals, rrel->relid, krel->relid);
    1886                 :             : 
    1887                 :             :             Assert(list_length(restrictlist) ==
    1888                 :             :                    (list_length(selfjoinquals) + list_length(otherjoinquals)));
    1889                 :             : 
    1890                 :             :             /*
    1891                 :             :              * To enable SJE for the only degenerate case without any self
    1892                 :             :              * join clauses at all, add baserestrictinfo to this list. The
    1893                 :             :              * degenerate case works only if both sides have the same clause.
    1894                 :             :              * So doesn't matter which side to add.
    1895                 :             :              */
    1896                 :        1856 :             selfjoinquals = list_concat(selfjoinquals, krel->baserestrictinfo);
    1897                 :             : 
    1898                 :             :             /*
    1899                 :             :              * Determine if the rrel can duplicate outer rows. We must bypass
    1900                 :             :              * the unique rel cache here since we're possibly using a subset
    1901                 :             :              * of join quals. We can use 'force_cache' == true when all join
    1902                 :             :              * quals are self-join quals.  Otherwise, we could end up putting
    1903                 :             :              * false negatives in the cache.
    1904                 :             :              */
    1905         [ +  + ]:        1856 :             if (!innerrel_is_unique_ext(root, joinrelids, rrel->relids,
    1906                 :             :                                         krel, JOIN_INNER, selfjoinquals,
    1907                 :        1856 :                                         list_length(otherjoinquals) == 0,
    1908                 :             :                                         &uclauses))
    1909                 :        1333 :                 continue;
    1910                 :             : 
    1911                 :             :             /*
    1912                 :             :              * 'uclauses' is the copy of outer->baserestrictinfo that are
    1913                 :             :              * associated with an index.  We proved by matching selfjoinquals
    1914                 :             :              * to a unique index that the outer relation has at most one
    1915                 :             :              * matching row for each inner row.  Sometimes that is not enough.
    1916                 :             :              * e.g. "WHERE s1.b = s2.b AND s1.a = 1 AND s2.a = 2" when the
    1917                 :             :              * unique index is (a,b).  Having non-empty uclauses, we must
    1918                 :             :              * validate that the inner baserestrictinfo contains the same
    1919                 :             :              * expressions, or we won't match the same row on each side of the
    1920                 :             :              * join.
    1921                 :             :              */
    1922         [ +  + ]:         523 :             if (!match_unique_clauses(root, rrel, uclauses, krel->relid))
    1923                 :          55 :                 continue;
    1924                 :             : 
    1925                 :             :             /* OK, remove rrel from the query */
    1926                 :         468 :             remove_self_join_rel(root, krel, rrel, kmark, rmark);
    1927                 :         468 :             removed = true;
    1928                 :             : 
    1929                 :             :             /*
    1930                 :             :              * Since relation r is now gone, we mustn't keep looking for
    1931                 :             :              * matches to it.  But we can keep scanning later relids members
    1932                 :             :              * for additional join pairs.
    1933                 :             :              */
    1934                 :         468 :             break;
    1935                 :             :         }
    1936                 :             :     }
    1937                 :             : 
    1938                 :        8820 :     return removed;
    1939                 :             : }
    1940                 :             : 
    1941                 :             : /*
    1942                 :             :  * Gather indexes of base relations from the joinlist and try to eliminate
    1943                 :             :  * self-joins.
    1944                 :             :  *
    1945                 :             :  * Return true if we removed any joins.
    1946                 :             :  */
    1947                 :             : static bool
    1948                 :       81080 : remove_self_joins_recurse(PlannerInfo *root, List *joinlist)
    1949                 :             : {
    1950                 :       81080 :     bool        removed = false;
    1951                 :             :     ListCell   *jl;
    1952                 :       81080 :     Relids      relids = NULL;
    1953                 :             :     SelfJoinCandidate *candidates;
    1954                 :             :     int         i;
    1955                 :             :     int         j;
    1956                 :             :     int         numRels;
    1957                 :             : 
    1958                 :             :     /* Collect indexes of possibly-mergeable relations from the joinlist */
    1959   [ +  -  +  +  :      271875 :     foreach(jl, joinlist)
                   +  + ]
    1960                 :             :     {
    1961                 :      190795 :         Node       *jlnode = (Node *) lfirst(jl);
    1962                 :             : 
    1963         [ +  + ]:      190795 :         if (IsA(jlnode, RangeTblRef))
    1964                 :             :         {
    1965                 :      187816 :             int         varno = ((RangeTblRef *) jlnode)->rtindex;
    1966                 :      187816 :             RangeTblEntry *rte = root->simple_rte_array[varno];
    1967                 :             : 
    1968                 :             :             /*
    1969                 :             :              * To be considered for self-join removal, the RTE must:
    1970                 :             :              *
    1971                 :             :              * 1. Be an ordinary relation.  (Someday we might support SJE on
    1972                 :             :              * partitioned tables, but not yet.)
    1973                 :             :              *
    1974                 :             :              * 2. Not have inh set, ie it has no inheritance children (or the
    1975                 :             :              * user wrote ONLY to ignore them).  Under traditional inheritance
    1976                 :             :              * a unique index on a parent table does not establish uniqueness
    1977                 :             :              * across its children.  This rule also keeps us from trying to
    1978                 :             :              * merge an inheritance scan with an ONLY scan, which would be
    1979                 :             :              * wrong.  (preprocess_relation_rtes already cleared the inh flag
    1980                 :             :              * for tables known not to have inheritance children.)
    1981                 :             :              *
    1982                 :             :              * 3. Not have a TABLESAMPLE clause.  Removing a relation with a
    1983                 :             :              * TABLESAMPLE clause would change the semantics of the query,
    1984                 :             :              * even if we merged it with another RTE with an identical
    1985                 :             :              * TABLESAMPLE clause.  (Two such RTEs should represent
    1986                 :             :              * independent samplings of the base table.)
    1987                 :             :              *
    1988                 :             :              * 4. Not be the query's result relation or MERGE target.  Merging
    1989                 :             :              * would cause misbehavior during EPQ.
    1990                 :             :              */
    1991         [ +  + ]:      187816 :             if (rte->rtekind == RTE_RELATION &&
    1992         [ +  + ]:      166198 :                 rte->relkind == RELKIND_RELATION &&
    1993         [ +  + ]:      161671 :                 !rte->inh &&
    1994         [ +  + ]:      161145 :                 rte->tablesample == NULL &&
    1995         [ +  + ]:      161113 :                 varno != root->parse->resultRelation &&
    1996         [ +  - ]:      159791 :                 varno != root->parse->mergeTargetRelation)
    1997                 :             :             {
    1998                 :             :                 Assert(!bms_is_member(varno, relids));
    1999                 :      159791 :                 relids = bms_add_member(relids, varno);
    2000                 :             :             }
    2001                 :             :         }
    2002         [ +  - ]:        2979 :         else if (IsA(jlnode, List))
    2003                 :             :         {
    2004                 :             :             /* Recursively perform SJE within the sub-joinlist */
    2005                 :        2979 :             removed |= remove_self_joins_recurse(root, (List *) jlnode);
    2006                 :             :         }
    2007                 :             :         else
    2008         [ #  # ]:           0 :             elog(ERROR, "unrecognized joinlist node type: %d",
    2009                 :             :                  (int) nodeTag(jlnode));
    2010                 :             :     }
    2011                 :             : 
    2012                 :       81080 :     numRels = bms_num_members(relids);
    2013                 :             : 
    2014                 :             :     /* No work if not at least two relations at this level */
    2015         [ +  + ]:       81080 :     if (numRels < 2)
    2016                 :       22600 :         return removed;         /* ... but don't fail to report sub-removals */
    2017                 :             : 
    2018                 :             :     /*
    2019                 :             :      * In order to find relations with the same reloid/useroid we first build
    2020                 :             :      * an array of candidates and then sort it by those oids.
    2021                 :             :      */
    2022                 :       58480 :     candidates = palloc_array(SelfJoinCandidate, numRels);
    2023                 :       58480 :     i = -1;
    2024                 :       58480 :     j = 0;
    2025         [ +  + ]:      202386 :     while ((i = bms_next_member(relids, i)) >= 0)
    2026                 :             :     {
    2027                 :      143906 :         RangeTblEntry *rte = root->simple_rte_array[i];
    2028                 :             : 
    2029                 :      143906 :         candidates[j].relid = i;
    2030                 :      143906 :         candidates[j].reloid = rte->relid;
    2031         [ +  - ]:      143906 :         if (rte->perminfoindex != 0)
    2032                 :             :         {
    2033                 :             :             RTEPermissionInfo *perminfo;
    2034                 :             : 
    2035                 :      143906 :             perminfo = getRTEPermissionInfo(root->parse->rteperminfos, rte);
    2036                 :      143906 :             candidates[j].useroid = perminfo->checkAsUser;
    2037                 :             :         }
    2038                 :             :         else
    2039                 :           0 :             candidates[j].useroid = InvalidOid;
    2040                 :      143906 :         j++;
    2041                 :             :     }
    2042                 :             : 
    2043                 :       58480 :     qsort(candidates, numRels, sizeof(SelfJoinCandidate),
    2044                 :             :           self_join_candidates_cmp);
    2045                 :             : 
    2046                 :             :     /*
    2047                 :             :      * Iteratively form a group of relation indexes with the same oids and
    2048                 :             :      * launch the routine that detects self-joins in this group.
    2049                 :             :      *
    2050                 :             :      * We remove considered relations from relids as we scan, so that that set
    2051                 :             :      * should be empty at the end.
    2052                 :             :      */
    2053                 :       58480 :     i = 0;
    2054         [ +  + ]:      202386 :     for (j = 1; j <= numRels; j++)
    2055                 :             :     {
    2056         [ +  + ]:      143906 :         if (j == numRels ||
    2057         [ +  + ]:       85426 :             candidates[j].reloid != candidates[i].reloid ||
    2058         [ +  + ]:       10032 :             candidates[j].useroid != candidates[i].useroid)
    2059                 :             :         {
    2060         [ +  + ]:      133894 :             if (j - i >= 2)
    2061                 :             :             {
    2062                 :             :                 /* Create a group of relation indexes with the same oids */
    2063                 :        8820 :                 Relids      group = NULL;
    2064                 :             : 
    2065         [ +  + ]:       27652 :                 while (i < j)
    2066                 :             :                 {
    2067                 :       18832 :                     group = bms_add_member(group, candidates[i].relid);
    2068                 :       18832 :                     i++;
    2069                 :             :                 }
    2070                 :        8820 :                 relids = bms_del_members(relids, group);
    2071                 :             : 
    2072                 :             :                 /* Try to remove self-joins from the group */
    2073                 :        8820 :                 removed |= remove_self_joins_one_group(root, group);
    2074                 :        8820 :                 bms_free(group);
    2075                 :             :             }
    2076                 :             :             else
    2077                 :             :             {
    2078                 :             :                 /* Nothing to do with this group, just drop it from the set */
    2079         [ +  + ]:      250148 :                 while (i < j)
    2080                 :             :                 {
    2081                 :      125074 :                     relids = bms_del_member(relids, candidates[i].relid);
    2082                 :      125074 :                     i++;
    2083                 :             :                 }
    2084                 :             :             }
    2085                 :             :         }
    2086                 :             :     }
    2087                 :             : 
    2088                 :             :     Assert(bms_is_empty(relids));
    2089                 :             : 
    2090                 :       58480 :     return removed;
    2091                 :             : }
    2092                 :             : 
    2093                 :             : /*
    2094                 :             :  * Compare self-join candidates by their reloid and then useroid.
    2095                 :             :  */
    2096                 :             : static int
    2097                 :      104703 : self_join_candidates_cmp(const void *a, const void *b)
    2098                 :             : {
    2099                 :      104703 :     const SelfJoinCandidate *ca = (const SelfJoinCandidate *) a;
    2100                 :      104703 :     const SelfJoinCandidate *cb = (const SelfJoinCandidate *) b;
    2101                 :             : 
    2102         [ +  + ]:      104703 :     if (ca->reloid != cb->reloid)
    2103         [ +  + ]:       94626 :         return (ca->reloid < cb->reloid ? -1 : 1);
    2104         [ +  + ]:       10077 :     else if (ca->useroid != cb->useroid)
    2105         [ +  - ]:          20 :         return (ca->useroid < cb->useroid ? -1 : 1);
    2106                 :             :     else
    2107                 :       10057 :         return 0;
    2108                 :             : }
    2109                 :             : 
    2110                 :             : /*
    2111                 :             :  * Find and remove useless self joins.
    2112                 :             :  *
    2113                 :             :  * Search for joins where a relation is joined to itself. If the join clause
    2114                 :             :  * for each tuple from one side of the join is proven to match the same
    2115                 :             :  * physical row (or nothing) on the other side, that self-join can be
    2116                 :             :  * eliminated from the query.  Suitable join clauses are assumed to be in the
    2117                 :             :  * form of X = X, and can be replaced with NOT NULL clauses.
    2118                 :             :  *
    2119                 :             :  * For the sake of simplicity, we don't apply this optimization to special
    2120                 :             :  * joins. Here is a list of what we could do in some particular cases:
    2121                 :             :  * 'a a1 semi join a a2': is reduced to inner by reduce_unique_semijoins,
    2122                 :             :  * and then removed normally.
    2123                 :             :  * 'a a1 anti join a a2': could simplify to a scan with 'outer quals AND
    2124                 :             :  * (IS NULL on join columns OR NOT inner quals)'.
    2125                 :             :  * 'a a1 left join a a2': could simplify to a scan like inner but without
    2126                 :             :  * NOT NULL conditions on join columns.
    2127                 :             :  * 'a a1 left join (a a2 join b)': can't simplify this, because join to b
    2128                 :             :  * can both remove rows and introduce duplicates.
    2129                 :             :  *
    2130                 :             :  * To search for removable joins, we order all the relations on their Oid,
    2131                 :             :  * go over each set with the same Oid, and consider each pair of relations
    2132                 :             :  * in this set.
    2133                 :             :  *
    2134                 :             :  * To remove the join, we delete one of the participating relations from the
    2135                 :             :  * query's jointree and rewrite all references to it to point to the remaining
    2136                 :             :  * relation.  We also have to modify their row marks.
    2137                 :             :  *
    2138                 :             :  * 'joinlist' is the top-level joinlist of the query; we use it to identify
    2139                 :             :  * groups of relations that could be joined to each other.
    2140                 :             :  *
    2141                 :             :  * We return true if we removed any self-joins.  If so, the caller must
    2142                 :             :  * recompute everything that was derived from the jointree, and should then
    2143                 :             :  * try join simplifications again since we might have exposed opportunities
    2144                 :             :  * for additional simplifications.
    2145                 :             :  */
    2146                 :             : bool
    2147                 :      246940 : remove_useless_self_joins(PlannerInfo *root, List *joinlist)
    2148                 :             : {
    2149                 :             :     /* Skip if SJE is disabled, or if the joinlist has less than 2 members. */
    2150   [ +  -  +  -  :      493880 :     if (!enable_self_join_elimination || joinlist == NIL ||
                   +  + ]
    2151         [ +  + ]:      416519 :         (list_length(joinlist) == 1 && !IsA(linitial(joinlist), List)))
    2152                 :      168839 :         return false;
    2153                 :             : 
    2154                 :             :     /* Try to merge pairs of self-joined relations. */
    2155                 :       78101 :     return remove_self_joins_recurse(root, joinlist);
    2156                 :             : }
        

Generated by: LCOV version 2.0-1