]> granicus.if.org Git - postgresql/commitdiff
Merge restrictlist_selectivity into clauselist_selectivity by
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 4 Jan 2004 03:51:52 +0000 (03:51 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 4 Jan 2004 03:51:52 +0000 (03:51 +0000)
teaching the latter to accept either RestrictInfo nodes or bare
clause expressions; and cache the selectivity result in the RestrictInfo
node when possible.  This extends the caching behavior of approx_selectivity
to many more contexts, and should reduce duplicate selectivity
calculations.

12 files changed:
src/backend/nodes/copyfuncs.c
src/backend/nodes/outfuncs.c
src/backend/optimizer/path/clausesel.c
src/backend/optimizer/path/costsize.c
src/backend/optimizer/path/indxpath.c
src/backend/optimizer/plan/initsplan.c
src/backend/optimizer/prep/prepunion.c
src/backend/optimizer/util/clauses.c
src/backend/optimizer/util/restrictinfo.c
src/include/nodes/relation.h
src/include/optimizer/clauses.h
src/include/optimizer/cost.h

index 7cc052182d501ea83d277d83d5937b20b664e6e2..29f55e0abb8a78cd5534dbbdefbf8f2b9da36dee 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.271 2004/01/04 00:07:32 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.272 2004/01/04 03:51:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1170,6 +1170,7 @@ _copyRestrictInfo(RestrictInfo *from)
        COPY_NODE_FIELD(clause);
        COPY_SCALAR_FIELD(ispusheddown);
        COPY_SCALAR_FIELD(canjoin);
+       COPY_BITMAPSET_FIELD(clause_relids);
        COPY_BITMAPSET_FIELD(left_relids);
        COPY_BITMAPSET_FIELD(right_relids);
        COPY_NODE_FIELD(orclause);
index e697196a28767be4251a11b512dd6ffe9b2baa74..3b8613fd19c2f5a1faced674cdf4ea4b14c993d2 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.224 2004/01/04 00:07:32 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.225 2004/01/04 03:51:52 tgl Exp $
  *
  * NOTES
  *       Every node type that can appear in stored rules' parsetrees *must*
@@ -1075,6 +1075,7 @@ _outRestrictInfo(StringInfo str, RestrictInfo *node)
        WRITE_NODE_FIELD(clause);
        WRITE_BOOL_FIELD(ispusheddown);
        WRITE_BOOL_FIELD(canjoin);
+       WRITE_BITMAPSET_FIELD(clause_relids);
        WRITE_BITMAPSET_FIELD(left_relids);
        WRITE_BITMAPSET_FIELD(right_relids);
        WRITE_NODE_FIELD(orclause);
index 7e5456d85b5e4273242e89ee533ba7ac0ca94490..a330ce894bb2d54c1ff070a21df3328d8d3f00cf 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.62 2003/12/29 21:44:49 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.63 2004/01/04 03:51:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -54,33 +54,13 @@ static void addRangeClause(RangeQueryClause **rqlist, Node *clause,
  *             ROUTINES TO COMPUTE SELECTIVITIES
  ****************************************************************************/
 
-/*
- * restrictlist_selectivity -
- *       Compute the selectivity of an implicitly-ANDed list of RestrictInfo
- *       clauses.
- *
- * This is the same as clauselist_selectivity except for the representation
- * of the clause list.
- */
-Selectivity
-restrictlist_selectivity(Query *root,
-                                                List *restrictinfo_list,
-                                                int varRelid,
-                                                JoinType jointype)
-{
-       List       *clauselist = get_actual_clauses(restrictinfo_list);
-       Selectivity result;
-
-       result = clauselist_selectivity(root, clauselist, varRelid, jointype);
-       freeList(clauselist);
-       return result;
-}
-
 /*
  * clauselist_selectivity -
  *       Compute the selectivity of an implicitly-ANDed list of boolean
  *       expression clauses.  The list can be empty, in which case 1.0
- *       must be returned.
+ *       must be returned.  List elements may be either RestrictInfos
+ *       or bare expression clauses --- the former is preferred since
+ *       it allows caching of results.
  *
  * See clause_selectivity() for the meaning of the additional parameters.
  *
@@ -133,64 +113,80 @@ clauselist_selectivity(Query *root,
        foreach(clist, clauses)
        {
                Node       *clause = (Node *) lfirst(clist);
+               RestrictInfo *rinfo;
                Selectivity s2;
 
+               /* Always compute the selectivity using clause_selectivity */
+               s2 = clause_selectivity(root, clause, varRelid, jointype);
+
+               /*
+                * Check for being passed a RestrictInfo.
+                */
+               if (IsA(clause, RestrictInfo))
+               {
+                       rinfo = (RestrictInfo *) clause;
+                       clause = (Node *) rinfo->clause;
+               }
+               else
+                       rinfo = NULL;
+
                /*
                 * See if it looks like a restriction clause with a pseudoconstant
                 * on one side.  (Anything more complicated than that might not
-                * behave in the simple way we are expecting.)
-                *
-                * NB: for consistency of results, this fragment of code had better
-                * match what clause_selectivity() would do in the cases it
-                * handles.
+                * behave in the simple way we are expecting.)  Most of the tests
+                * here can be done more efficiently with rinfo than without.
                 */
-               if (is_opclause(clause) &&
-                       (varRelid != 0 || NumRelids(clause) == 1))
+               if (is_opclause(clause) && length(((OpExpr *) clause)->args) == 2)
                {
                        OpExpr     *expr = (OpExpr *) clause;
+                       bool            varonleft = true;
+                       bool            ok;
 
-                       if (length(expr->args) == 2)
+                       if (rinfo)
                        {
-                               bool            varonleft = true;
+                               ok = (bms_membership(rinfo->clause_relids) == BMS_SINGLETON) &&
+                                       (is_pseudo_constant_clause_relids(lsecond(expr->args),
+                                                                                                         rinfo->right_relids) ||
+                                        (varonleft = false,
+                                         is_pseudo_constant_clause_relids(lfirst(expr->args),
+                                                                                                          rinfo->left_relids)));
+                       }
+                       else
+                       {
+                               ok = (NumRelids(clause) == 1) &&
+                                       (is_pseudo_constant_clause(lsecond(expr->args)) ||
+                                        (varonleft = false,
+                                         is_pseudo_constant_clause(lfirst(expr->args))));
+                       }
 
-                               if (is_pseudo_constant_clause(lsecond(expr->args)) ||
-                                       (varonleft = false,
-                                        is_pseudo_constant_clause(lfirst(expr->args))))
+                       if (ok)
+                       {
+                               /*
+                                * If it's not a "<" or ">" operator, just merge the
+                                * selectivity in generically.  But if it's the
+                                * right oprrest, add the clause to rqlist for later
+                                * processing.
+                                */
+                               switch (get_oprrest(expr->opno))
                                {
-                                       Oid                     opno = expr->opno;
-                                       RegProcedure oprrest = get_oprrest(opno);
-
-                                       s2 = restriction_selectivity(root, opno,
-                                                                                                expr->args, varRelid);
-
-                                       /*
-                                        * If we reach here, we have computed the same result
-                                        * that clause_selectivity would, so we can just use
-                                        * s2 if it's the wrong oprrest.  But if it's the
-                                        * right oprrest, add the clause to rqlist for later
-                                        * processing.
-                                        */
-                                       switch (oprrest)
-                                       {
-                                               case F_SCALARLTSEL:
-                                                       addRangeClause(&rqlist, clause,
-                                                                                  varonleft, true, s2);
-                                                       break;
-                                               case F_SCALARGTSEL:
-                                                       addRangeClause(&rqlist, clause,
-                                                                                  varonleft, false, s2);
-                                                       break;
-                                               default:
-                                                       /* Just merge the selectivity in generically */
-                                                       s1 = s1 * s2;
-                                                       break;
-                                       }
-                                       continue;       /* drop to loop bottom */
+                                       case F_SCALARLTSEL:
+                                               addRangeClause(&rqlist, clause,
+                                                                          varonleft, true, s2);
+                                               break;
+                                       case F_SCALARGTSEL:
+                                               addRangeClause(&rqlist, clause,
+                                                                          varonleft, false, s2);
+                                               break;
+                                       default:
+                                               /* Just merge the selectivity in generically */
+                                               s1 = s1 * s2;
+                                               break;
                                }
+                               continue;               /* drop to loop bottom */
                        }
                }
+
                /* Not the right form, so treat it generically. */
-               s2 = clause_selectivity(root, clause, varRelid, jointype);
                s1 = s1 * s2;
        }
 
@@ -352,11 +348,39 @@ addRangeClause(RangeQueryClause **rqlist, Node *clause,
        *rqlist = rqelem;
 }
 
+/*
+ * bms_is_subset_singleton
+ *
+ * Same result as bms_is_subset(s, bms_make_singleton(x)),
+ * but a little faster and doesn't leak memory.
+ *
+ * Is this of use anywhere else?  If so move to bitmapset.c ...
+ */
+static bool
+bms_is_subset_singleton(const Bitmapset *s, int x)
+{
+       switch (bms_membership(s))
+       {
+               case BMS_EMPTY_SET:
+                       return true;
+               case BMS_SINGLETON:
+                       return bms_is_member(x, s);
+               case BMS_MULTIPLE:
+                       return false;
+       }
+       /* can't get here... */
+       return false;
+}
+
 
 /*
  * clause_selectivity -
  *       Compute the selectivity of a general boolean expression clause.
  *
+ * The clause can be either a RestrictInfo or a plain expression.  If it's
+ * a RestrictInfo, we try to cache the selectivity for possible re-use,
+ * so passing RestrictInfos is preferred.
+ *
  * varRelid is either 0 or a rangetable index.
  *
  * When varRelid is not 0, only variables belonging to that relation are
@@ -379,9 +403,37 @@ clause_selectivity(Query *root,
                                   JoinType jointype)
 {
        Selectivity s1 = 1.0;           /* default for any unhandled clause type */
+       RestrictInfo *rinfo = NULL;
+       bool            cacheable = false;
 
-       if (clause == NULL)
+       if (clause == NULL)                     /* can this still happen? */
                return s1;
+
+       if (IsA(clause, RestrictInfo))
+       {
+               rinfo = (RestrictInfo *) clause;
+
+               /*
+                * If possible, cache the result of the selectivity calculation for
+                * the clause.  We can cache if varRelid is zero or the clause
+                * contains only vars of that relid --- otherwise varRelid will affect
+                * the result, so mustn't cache.  We ignore the possibility that
+                * jointype will affect the result, which should be okay because outer
+                * join clauses will always be examined with the same jointype value.
+                */
+               if (varRelid == 0 ||
+                       bms_is_subset_singleton(rinfo->clause_relids, varRelid))
+               {
+                       /* Cacheable --- do we already have the result? */
+                       if (rinfo->this_selec >= 0)
+                               return rinfo->this_selec;
+                       cacheable = true;
+               }
+
+               /* Proceed with examination of contained clause */
+               clause = (Node *) rinfo->clause;
+       }
+
        if (IsA(clause, Var))
        {
                Var                *var = (Var *) clause;
@@ -448,9 +500,10 @@ clause_selectivity(Query *root,
        else if (or_clause(clause))
        {
                /*
-                * Selectivities for an 'or' clause are computed as s1+s2 - s1*s2
-                * to account for the probable overlap of selected tuple sets. XXX
-                * is this too conservative?
+                * Selectivities for an OR clause are computed as s1+s2 - s1*s2
+                * to account for the probable overlap of selected tuple sets.
+                *
+                * XXX is this too conservative?
                 */
                List       *arg;
 
@@ -483,9 +536,13 @@ clause_selectivity(Query *root,
                {
                        /*
                         * Otherwise, it's a join if there's more than one relation
-                        * used.
+                        * used.  We can optimize this calculation if an rinfo was passed.
                         */
-                       is_join_clause = (NumRelids(clause) > 1);
+                       if (rinfo)
+                               is_join_clause = (bms_membership(rinfo->clause_relids) ==
+                                                                 BMS_MULTIPLE);
+                       else
+                               is_join_clause = (NumRelids(clause) > 1);
                }
 
                if (is_join_clause)
@@ -559,6 +616,10 @@ clause_selectivity(Query *root,
                                                                jointype);
        }
 
+       /* Cache the result if possible */
+       if (cacheable)
+               rinfo->this_selec = s1;
+
 #ifdef SELECTIVITY_DEBUG
        elog(DEBUG4, "clause_selectivity: s1 %f", s1);
 #endif   /* SELECTIVITY_DEBUG */
index cb0b657acb5e52dc02316e6618510c88f2faf26e..94202cda4b02cca8104e8a3e85cd71fc5caa8bf3 100644 (file)
@@ -49,7 +49,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.118 2003/12/18 03:46:45 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.119 2004/01/04 03:51:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1625,15 +1625,12 @@ cost_qual_eval_walker(Node *node, QualCost *total)
  *             The input can be either an implicitly-ANDed list of boolean
  *             expressions, or a list of RestrictInfo nodes (typically the latter).
  *
- * The "quick" part comes from caching the selectivity estimates so we can
- * avoid recomputing them later.  (Since the same clauses are typically
- * examined over and over in different possible join trees, this makes a
- * big difference.)
- *
- * The "dirty" part comes from the fact that the selectivities of multiple
- * clauses are estimated independently and multiplied together.  Now
+ * This is quick-and-dirty because we bypass clauselist_selectivity, and
+ * simply multiply the independent clause selectivities together.  Now
  * clauselist_selectivity often can't do any better than that anyhow, but
- * for some situations (such as range constraints) it is smarter.
+ * for some situations (such as range constraints) it is smarter.  However,
+ * we can't effectively cache the results of clauselist_selectivity, whereas
+ * the individual clause selectivities can be and are cached.
  *
  * Since we are only using the results to estimate how many potential
  * output tuples are generated and passed through qpqual checking, it
@@ -1648,33 +1645,9 @@ approx_selectivity(Query *root, List *quals, JoinType jointype)
        foreach(l, quals)
        {
                Node       *qual = (Node *) lfirst(l);
-               Selectivity selec;
 
-               /*
-                * RestrictInfo nodes contain a this_selec field reserved for this
-                * routine's use, so that it's not necessary to evaluate the qual
-                * clause's selectivity more than once.  If the clause's
-                * selectivity hasn't been computed yet, the field will contain
-                * -1.
-                */
-               if (qual && IsA(qual, RestrictInfo))
-               {
-                       RestrictInfo *restrictinfo = (RestrictInfo *) qual;
-
-                       if (restrictinfo->this_selec < 0)
-                               restrictinfo->this_selec =
-                                       clause_selectivity(root,
-                                                                          (Node *) restrictinfo->clause,
-                                                                          0,
-                                                                          jointype);
-                       selec = restrictinfo->this_selec;
-               }
-               else
-               {
-                       /* If it's a bare expression, must always do it the hard way */
-                       selec = clause_selectivity(root, qual, 0, jointype);
-               }
-               total *= selec;
+               /* Note that clause_selectivity will be able to cache its result */
+               total *= clause_selectivity(root, qual, 0, jointype);
        }
        return total;
 }
@@ -1702,10 +1675,10 @@ set_baserel_size_estimates(Query *root, RelOptInfo *rel)
        Assert(rel->relid > 0);
 
        temp = rel->tuples *
-               restrictlist_selectivity(root,
-                                                                rel->baserestrictinfo,
-                                                                rel->relid,
-                                                                JOIN_INNER);
+               clauselist_selectivity(root,
+                                                          rel->baserestrictinfo,
+                                                          0,
+                                                          JOIN_INNER);
 
        /*
         * Force estimate to be at least one row, to make explain output look
@@ -1765,10 +1738,10 @@ set_joinrel_size_estimates(Query *root, RelOptInfo *rel,
         * not double-counting them because they were not considered in
         * estimating the sizes of the component rels.
         */
-       selec = restrictlist_selectivity(root,
-                                                                        restrictlist,
-                                                                        0,
-                                                                        jointype);
+       selec = clauselist_selectivity(root,
+                                                                  restrictlist,
+                                                                  0,
+                                                                  jointype);
 
        /*
         * Basically, we multiply size of Cartesian product by selectivity.
@@ -1875,10 +1848,10 @@ set_function_size_estimates(Query *root, RelOptInfo *rel)
 
        /* Now estimate number of output rows */
        temp = rel->tuples *
-               restrictlist_selectivity(root,
-                                                                rel->baserestrictinfo,
-                                                                rel->relid,
-                                                                JOIN_INNER);
+               clauselist_selectivity(root,
+                                                          rel->baserestrictinfo,
+                                                          0,
+                                                          JOIN_INNER);
 
        /*
         * Force estimate to be at least one row, to make explain output look
index 353fcc6130f4c39426b0b7ef9e4be6502e18fb70..0fa02d4f74f8074e87824d5d5557dabb36eee609 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.152 2004/01/04 00:07:32 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.153 2004/01/04 03:51:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1449,7 +1449,7 @@ make_innerjoin_index_path(Query *root,
         * the full set of clauses that must be considered to compute the
         * correct selectivity.  (Without the union operation, we might have
         * some restriction clauses appearing twice, which'd mislead
-        * restrictlist_selectivity into double-counting their selectivity.
+        * clauselist_selectivity into double-counting their selectivity.
         * However, since RestrictInfo nodes aren't copied when linking them
         * into different lists, it should be sufficient to use pointer
         * comparison to remove duplicates.)
@@ -1459,10 +1459,10 @@ make_innerjoin_index_path(Query *root,
         */
        allclauses = set_ptrUnion(rel->baserestrictinfo, allclauses);
        pathnode->rows = rel->tuples *
-               restrictlist_selectivity(root,
-                                                                allclauses,
-                                                                rel->relid,
-                                                                JOIN_INNER);
+               clauselist_selectivity(root,
+                                                          allclauses,
+                                                          rel->relid,          /* do not use 0! */
+                                                          JOIN_INNER);
        /* Like costsize.c, force estimate to be at least one row */
        if (pathnode->rows < 1.0)
                pathnode->rows = 1.0;
index e170058c93590747732abab6950ce9f67753e758..bcfdb25403ce9e079b870c9204002f246641675e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.95 2004/01/04 00:07:32 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.96 2004/01/04 03:51:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -375,15 +375,15 @@ distribute_qual_to_rels(Query *root, Node *clause,
                                                Relids qualscope)
 {
        Relids          relids;
-       List       *vars;
        bool            can_be_equijoin;
        RestrictInfo *restrictinfo;
        RelOptInfo *rel;
+       List       *vars;
 
        /*
-        * Retrieve all relids and vars contained within the clause.
+        * Retrieve all relids mentioned within the clause.
         */
-       clause_get_relids_vars(clause, &relids, &vars);
+       relids = pull_varnos(clause);
 
        /*
         * Cross-check: clause should contain no relids not within its scope.
@@ -571,7 +571,9 @@ distribute_qual_to_rels(Query *root, Node *clause,
                         * that scan those relations (else they won't be available at
                         * the join node!).
                         */
+                       vars = pull_var_clause(clause, false);
                        add_vars_to_targetlist(root, vars, relids);
+                       freeList(vars);
                        break;
                default:
 
index 6866e95e4b37bfb759a933a508cb0d516e1ce011..d52f2a73417ab92fad3324a59dd6c47e77d14602 100644 (file)
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.106 2004/01/04 00:07:32 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.107 2004/01/04 03:51:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -885,9 +885,10 @@ adjust_inherited_attrs_mutator(Node *node,
                newinfo->orclause = (Expr *)
                        adjust_inherited_attrs_mutator((Node *) oldinfo->orclause, context);
 
-               /*
-                * Adjust left/right relid sets too.
-                */
+               /* adjust relid sets too */
+               newinfo->clause_relids = adjust_relid_set(oldinfo->clause_relids,
+                                                                                                 context->old_rt_index,
+                                                                                                 context->new_rt_index);
                newinfo->left_relids = adjust_relid_set(oldinfo->left_relids,
                                                                                                context->old_rt_index,
                                                                                                context->new_rt_index);
index 35efa6bc63074fa14758c90b2c402cf24d288853..3831231470356bb624859c340ceec37bdb9e9d8f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.158 2003/12/30 23:53:15 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.159 2004/01/04 03:51:52 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -928,51 +928,6 @@ has_distinct_on_clause(Query *query)
  *                                                                                                                                                      *
  *****************************************************************************/
 
-/*
- * clause_get_relids_vars
- *       Retrieves distinct relids and vars appearing within a clause.
- *
- * '*relids' is set to the set of all distinct "varno"s appearing
- *             in Vars within the clause.
- * '*vars' is set to a list of all distinct Vars appearing within the clause.
- *             Var nodes are considered distinct if they have different varno
- *             or varattno values.  If there are several occurrences of the same
- *             varno/varattno, you get a randomly chosen one...
- *
- * Note that upper-level vars are ignored, since they normally will
- * become Params with respect to this query level.
- */
-void
-clause_get_relids_vars(Node *clause, Relids *relids, List **vars)
-{
-       List       *clvars = pull_var_clause(clause, false);
-       Relids          varnos = NULL;
-       List       *var_list = NIL;
-       List       *i;
-
-       foreach(i, clvars)
-       {
-               Var                *var = (Var *) lfirst(i);
-               List       *vi;
-
-               varnos = bms_add_member(varnos, var->varno);
-               foreach(vi, var_list)
-               {
-                       Var                *in_list = (Var *) lfirst(vi);
-
-                       if (in_list->varno == var->varno &&
-                               in_list->varattno == var->varattno)
-                               break;
-               }
-               if (vi == NIL)
-                       var_list = lcons(var, var_list);
-       }
-       freeList(clvars);
-
-       *relids = varnos;
-       *vars = var_list;
-}
-
 /*
  * NumRelids
  *             (formerly clause_relids)
index a7c9ec85f72b7a4e2069dbde5031d30a06a62720..c72e2306aca7849279758a2e61c466beab0c2b7d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.22 2004/01/04 00:07:32 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.23 2004/01/04 03:51:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -47,12 +47,16 @@ make_restrictinfo(Expr *clause, bool ispusheddown)
 
        /*
         * If it's a binary opclause, set up left/right relids info.
+        * In any case set up the total clause relids info.
         */
        if (is_opclause(clause) && length(((OpExpr *) clause)->args) == 2)
        {
                restrictinfo->left_relids = pull_varnos(get_leftop(clause));
                restrictinfo->right_relids = pull_varnos(get_rightop(clause));
 
+               restrictinfo->clause_relids = bms_union(restrictinfo->left_relids,
+                                                                                               restrictinfo->right_relids);
+
                /*
                 * Does it look like a normal join clause, i.e., a binary operator
                 * relating expressions that come from distinct relations? If so
@@ -67,9 +71,11 @@ make_restrictinfo(Expr *clause, bool ispusheddown)
        }
        else
        {
-               /* Not a binary opclause, so mark both relid sets as empty */
+               /* Not a binary opclause, so mark left/right relid sets as empty */
                restrictinfo->left_relids = NULL;
                restrictinfo->right_relids = NULL;
+               /* and get the total relid set the hard way */
+               restrictinfo->clause_relids = pull_varnos((Node *) clause);
        }
 
        /*
@@ -328,9 +334,13 @@ join_clause_is_redundant(Query *root,
                bool            redundant = false;
                List       *refitem;
 
+               /* do the cheap test first: is it a "var = const" clause? */
+               if (bms_is_empty(rinfo->left_relids) ||
+                       bms_is_empty(rinfo->right_relids))
+                       return false;           /* var = const, so not redundant */
+
                cache_mergeclause_pathkeys(root, rinfo);
 
-               /* do the cheap tests first */
                foreach(refitem, reference_list)
                {
                        RestrictInfo *refrinfo = (RestrictInfo *) lfirst(refitem);
@@ -347,13 +357,7 @@ join_clause_is_redundant(Query *root,
                }
 
                if (redundant)
-               {
-                       /* It looks redundant, but check for "var = const" case */
-                       if (!bms_is_empty(rinfo->left_relids) &&
-                               !bms_is_empty(rinfo->right_relids))
-                               return true;    /* var = var, so redundant */
-                       /* else var = const, not redundant */
-               }
+                       return true;            /* var = var, so redundant */
        }
 
        /* otherwise, not redundant */
index af8527257374fa2fe7b624bd622f079574e51d4d..010adcc8592a0e5a35636f54dd5b5848033201cf 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.89 2004/01/04 00:07:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.90 2004/01/04 03:51:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -613,6 +613,9 @@ typedef struct RestrictInfo
         */
        bool            canjoin;
 
+       /* The set of relids (varnos) referenced in the clause: */
+       Relids          clause_relids;
+
        /* These fields are set for any binary opclause: */
        Relids          left_relids;    /* relids in left side of clause */
        Relids          right_relids;   /* relids in right side of clause */
@@ -620,7 +623,7 @@ typedef struct RestrictInfo
        /* This field is NULL unless clause is an OR clause: */
        Expr       *orclause;           /* modified clause with RestrictInfos */
 
-       /* cache space for costs (currently only used for join clauses) */
+       /* cache space for cost and selectivity */
        QualCost        eval_cost;              /* eval cost of clause; -1 if not yet set */
        Selectivity this_selec;         /* selectivity; -1 if not yet set */
 
index 3e089256a51fb5d2c910b7c1c3e63e937b53514a..c948a9039fbf0569befe21ad18861c9b836ef994 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/clauses.h,v 1.70 2003/12/30 23:53:15 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/clauses.h,v 1.71 2004/01/04 03:51:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -59,7 +59,6 @@ extern List *pull_constant_clauses(List *quals, List **constantQual);
 
 extern bool has_distinct_on_clause(Query *query);
 
-extern void clause_get_relids_vars(Node *clause, Relids *relids, List **vars);
 extern int     NumRelids(Node *clause);
 extern void CommuteClause(OpExpr *clause);
 
index 316d63b97a24a84de33ee3e11cfe0efa509eb352..15540a66643f5810bd4fe4d8307f93add707d1a2 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.58 2003/11/29 22:41:07 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.59 2004/01/04 03:51:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -88,10 +88,6 @@ extern void set_function_size_estimates(Query *root, RelOptInfo *rel);
  * prototypes for clausesel.c
  *       routines to compute clause selectivities
  */
-extern Selectivity restrictlist_selectivity(Query *root,
-                                                List *restrictinfo_list,
-                                                int varRelid,
-                                                JoinType jointype);
 extern Selectivity clauselist_selectivity(Query *root,
                                           List *clauses,
                                           int varRelid,