LCOV - code coverage report
Current view: top level - src/backend/optimizer/plan - analyzejoins.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 94.8 % 600 569
Test Date: 2026-09-12 04:15:38 Functions: 100.0 % 26 26
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 83.8 % 586 491

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

Generated by: LCOV version 2.0-1