]> granicus.if.org Git - postgresql/commitdiff
Further work on planning of indexscans. Cleaned up interfaces
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 25 Jul 1999 23:07:26 +0000 (23:07 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 25 Jul 1999 23:07:26 +0000 (23:07 +0000)
to index_selectivity so that it can be handed an indexqual clause list
rather than a bunch of assorted derivative data.

src/backend/optimizer/path/clausesel.c
src/backend/optimizer/path/indxpath.c
src/backend/optimizer/path/orindxpath.c
src/backend/optimizer/util/clauses.c
src/backend/optimizer/util/pathnode.c
src/backend/optimizer/util/plancat.c
src/backend/optimizer/util/restrictinfo.c
src/include/optimizer/clauses.h
src/include/optimizer/internal.h
src/include/optimizer/plancat.h
src/include/optimizer/restrictinfo.h

index 00d3780a352d5827cc19c65d986a4ad7cecee57b..23998a54bff3151b2fe793cdfa927f8a7133929b 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.24 1999/07/24 23:21:09 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.25 1999/07/25 23:07:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -142,8 +142,8 @@ compute_clause_selec(Query *root, Node *clause)
                                                                         BooleanEqualOperator,
                                                                         relid,
                                                                         ((Var *) clause)->varoattno,
-                                                                        "t",
-                                                                        _SELEC_CONSTANT_RIGHT_);
+                                                                        Int8GetDatum(true),
+                                                                        SEL_CONSTANT | SEL_RIGHT);
        }
        else if (IsA(clause, Param))
        {
@@ -215,14 +215,6 @@ compute_clause_selec(Query *root, Node *clause)
                         */
                        Oid                     opno = ((Oper *) ((Expr *) clause)->oper)->opno;
                        RegProcedure oprrest = get_oprrest(opno);
-                       Oid                     relid;
-                       int                     relidx;
-                       AttrNumber      attno;
-                       Datum           constval;
-                       int                     flag;
-
-                       get_relattval(clause, &relidx, &attno, &constval, &flag);
-                       relid = getrelid(relidx, root->rtable);
 
                        /*
                         * if the oprrest procedure is missing for whatever reason, use a
@@ -230,22 +222,33 @@ compute_clause_selec(Query *root, Node *clause)
                         */
                        if (!oprrest)
                                s1 = (Cost) 0.5;
-                       else if (attno == InvalidAttrNumber)
+                       else
                        {
-                               /*
-                                * attno can be Invalid if the clause had a function in it,
-                                * i.e.   WHERE myFunc(f) = 10
-                                */
-                               /* this should be FIXED somehow to use function selectivity */
-                               s1 = (Cost) (0.5);
+                               int                     relidx;
+                               AttrNumber      attno;
+                               Datum           constval;
+                               int                     flag;
+
+                               get_relattval(clause, 0, &relidx, &attno, &constval, &flag);
+                               if (relidx <= 0 || attno <= 0)
+                               {
+                                       /*
+                                        * attno can be Invalid if the clause had a function in it,
+                                        * i.e.   WHERE myFunc(f) = 10
+                                        *
+                                        * XXX should be FIXED to use function selectivity
+                                        */
+                                       s1 = (Cost) (0.5);
+                               }
+                               else
+                                       s1 = (Cost) restriction_selectivity(oprrest,
+                                                                                                               opno,
+                                                                                                               getrelid(relidx,
+                                                                                                                                root->rtable),
+                                                                                                               attno,
+                                                                                                               constval,
+                                                                                                               flag);
                        }
-                       else
-                               s1 = (Cost) restriction_selectivity(oprrest,
-                                                                                                       opno,
-                                                                                                       relid,
-                                                                                                       attno,
-                                                                                                       (char *) constval,
-                                                                                                       flag);
                }
                else
                {
@@ -256,14 +259,6 @@ compute_clause_selec(Query *root, Node *clause)
                         */
                        Oid                     opno = ((Oper *) ((Expr *) clause)->oper)->opno;
                        RegProcedure oprjoin = get_oprjoin(opno);
-                       int                     relid1,
-                                               relid2;
-                       AttrNumber      attno1,
-                                               attno2;
-
-                       get_rels_atts(clause, &relid1, &attno1, &relid2, &attno2);
-                       relid1 = getrelid(relid1, root->rtable);
-                       relid2 = getrelid(relid2, root->rtable);
 
                        /*
                         * if the oprjoin procedure is missing for whatever reason, use a
@@ -272,12 +267,25 @@ compute_clause_selec(Query *root, Node *clause)
                        if (!oprjoin)
                                s1 = (Cost) (0.5);
                        else
-                               s1 = (Cost) join_selectivity(oprjoin,
-                                                                                        opno,
-                                                                                        relid1,
-                                                                                        attno1,
-                                                                                        relid2,
-                                                                                        attno2);
+                       {
+                               int                     relid1,
+                                                       relid2;
+                               AttrNumber      attno1,
+                                                       attno2;
+
+                               get_rels_atts(clause, &relid1, &attno1, &relid2, &attno2);
+                               if (relid1 > 0 && relid2 > 0 && attno1 > 0 && attno2 > 0)
+                                       s1 = (Cost) join_selectivity(oprjoin,
+                                                                                                opno,
+                                                                                                getrelid(relid1,
+                                                                                                                 root->rtable),
+                                                                                                attno1,
+                                                                                                getrelid(relid2,
+                                                                                                                 root->rtable),
+                                                                                                attno2);
+                               else                    /* XXX more code for function selectivity? */
+                                       s1 = (Cost) (0.5);
+                       }
                }
        }
 
index 62996ee7d4c0aa6fc8a15c708157bb4bbf53803c..2f1002c78f5b5e1eb31045e386f877b110869b84 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.64 1999/07/25 17:53:27 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.65 1999/07/25 23:07:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1216,25 +1216,20 @@ index_innerjoin(Query *root, RelOptInfo *rel, RelOptInfo *index,
        {
                List       *clausegroup = lfirst(i);
                IndexPath  *pathnode = makeNode(IndexPath);
-               Cost            temp_selec;
-               float           temp_pages;
-               List       *attnos,
-                                  *values,
-                                  *flags;
-
-               get_joinvars(lfirsti(rel->relids), clausegroup,
-                                        &attnos, &values, &flags);
-               index_selectivity(lfirsti(index->relids),
-                                                 index->classlist,
-                                                 get_opnos(clausegroup),
-                                                 getrelid(lfirsti(rel->relids),
-                                                                  root->rtable),
-                                                 attnos,
-                                                 values,
-                                                 flags,
-                                                 length(clausegroup),
-                                                 &temp_pages,
-                                                 &temp_selec);
+               List       *indexquals;
+               float           npages;
+               float           selec;
+
+               indexquals = get_actual_clauses(clausegroup);
+
+               index_selectivity(root,
+                                                 lfirsti(rel->relids),
+                                                 lfirsti(index->relids),
+                                                 indexquals,
+                                                 &npages,
+                                                 &selec);
+
+               /* XXX this code ought to be merged with create_index_path */
 
                pathnode->path.pathtype = T_IndexScan;
                pathnode->path.parent = rel;
@@ -1249,14 +1244,14 @@ index_innerjoin(Query *root, RelOptInfo *rel, RelOptInfo *index,
                 */
                pathnode->indexid = index->relids;
                pathnode->indexkeys = index->indexkeys;
-               pathnode->indexqual = lcons(get_actual_clauses(clausegroup), NIL);
+               pathnode->indexqual = lcons(indexquals, NIL);
 
                /* joinid saves the rels needed on the outer side of the join */
                pathnode->path.joinid = lfirst(outerrelids_list);
 
                pathnode->path.path_cost = cost_index((Oid) lfirsti(index->relids),
-                                                                                         (int) temp_pages,
-                                                                                         temp_selec,
+                                                                                         (int) npages,
+                                                                                         selec,
                                                                                          rel->pages,
                                                                                          rel->tuples,
                                                                                          index->pages,
index 4a511372a53d8deb989a4c44a64fd3c528cdc97b..39fa69cdef818940258d555bd42a8aa528306b43 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.29 1999/07/24 23:21:10 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.30 1999/07/25 23:07:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -121,11 +121,14 @@ create_or_index_paths(Query *root,
                                pathnode->indexqual = NIL;
                                foreach(orclause, clausenode->clause->args)
                                {
-                                       List    *sublist;
-                                       if (and_clause(lfirst(orclause)))
-                                               sublist = ((Expr *) lfirst(orclause))->args;
+                                       Expr   *subclause = (Expr *) lfirst(orclause);
+                                       List   *sublist;
+
+                                       if (and_clause((Node *) subclause))
+                                               sublist = subclause->args;
                                        else
-                                               sublist = lcons(lfirst(orclause), NIL);
+                                               sublist = lcons(subclause, NIL);
+                                       /* expansion call... */
                                        pathnode->indexqual = lappend(pathnode->indexqual,
                                                                                                  sublist);
                                }
@@ -224,18 +227,8 @@ best_or_subclause_index(Query *root,
                                                Cost *retCost,  /* return value */
                                                Cost *retSelec) /* return value */
 {
-       Oid                     relid = getrelid(lfirsti(rel->relids),
-                                                                root->rtable);
-       Oid                     opno = ((Oper *) subclause->oper)->opno;
-       AttrNumber      attno = (get_leftop(subclause))->varattno;
-       bool            constant_on_right = non_null((Expr *) get_rightop(subclause));
-       Datum           value;
-       int                     flag;
-       List       *opnos,
-                          *attnos,
-                          *values,
-                          *flags;
        bool            first_run = true;
+       List       *indexquals;
        List       *ilist;
 
        /* if we don't match anything, return zeros */
@@ -243,37 +236,25 @@ best_or_subclause_index(Query *root,
        *retCost = (Cost) 0.0;
        *retSelec = (Cost) 0.0;
 
-       if (constant_on_right)          /* XXX looks pretty bogus ... tgl */
-               value = ((Const *) get_rightop(subclause))->constvalue;
-       else
-               value = NameGetDatum("");
-       if (constant_on_right)
-               flag = (_SELEC_IS_CONSTANT_ || _SELEC_CONSTANT_RIGHT_);
+       /* convert 'or' subclause to an indexqual list */
+       if (and_clause((Node *) subclause))
+               indexquals = subclause->args;
        else
-               flag = _SELEC_CONSTANT_RIGHT_;
-
-       /* prebuild lists since we will pass same list to each index */
-       opnos = lconsi(opno, NIL);
-       attnos = lconsi(attno, NIL);
-       values = lconsi(value, NIL);
-       flags = lconsi(flag, NIL);
+               indexquals = lcons(subclause, NIL);
+       /* expansion call... */
 
        foreach(ilist, indices)
        {
                RelOptInfo *index = (RelOptInfo *) lfirst(ilist);
                Oid                     indexid = (Oid) lfirsti(index->relids);
                Cost            subcost;
-               float           npages,
-                                       selec;
-
-               index_selectivity(indexid,
-                                                 index->classlist,
-                                                 opnos,
-                                                 relid,
-                                                 attnos,
-                                                 values,
-                                                 flags,
-                                                 1,
+               float           npages;
+               float           selec;
+
+               index_selectivity(root,
+                                                 lfirsti(rel->relids),
+                                                 indexid,
+                                                 indexquals,
                                                  &npages,
                                                  &selec);
 
index 5c9e4175adebff97139e9bf13eeb5393cb3af56a..442ebad1e7b5582a323ffaa2116826a0d29957ba 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.41 1999/07/24 23:21:13 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.42 1999/07/25 23:07:25 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -29,6 +29,7 @@
 
 
 static bool fix_opid_walker(Node *node, void *context);
+static int is_single_func(Node *node);
 
 
 Expr *
@@ -533,36 +534,36 @@ fix_opids(List *clauses)
 
 /*
  * get_relattval
- *             For a non-join clause, returns a list consisting of the
- *                             relid,
- *                             attno,
- *                             value of the CONST node (if any), and a
- *                             flag indicating whether the value appears on the left or right
- *                                             of the operator and whether the value varied.
- *
- * OLD OBSOLETE COMMENT FOLLOWS:
- *             If 'clause' is not of the format (op var node) or (op node var),
- *             or if the var refers to a nested attribute, then -1's are returned for
- *             everything but the value  a blank string "" (pointer to \0) is
- *             returned for the value if it is unknown or null.
- * END OF OLD OBSOLETE COMMENT.
- * NEW COMMENT:
- * when defining rules one of the attributes of the operator can
- * be a Param node (which is supposed to be treated as a constant).
- * However as there is no value specified for a parameter until run time
- * this routine used to return "" as value, which caused 'compute_selec'
- * to bomb (because it was expecting a lisp integer and got back a lisp
- * string). Now the code returns a plain old good "lispInteger(0)".
+ *             Extract information from a restriction or join clause for
+ *             selectivity estimation.  The inputs are an expression
+ *             and a relation number (which can be 0 if we don't care which
+ *             relation is used; that'd normally be the case for restriction
+ *             clauses, where the caller already knows that only one relation
+ *             is referenced in the clause).  The routine checks that the
+ *             expression is of the form (var op something) or (something op var)
+ *             where the var is an attribute of the specified relation, or
+ *             a function of a var of the specified relation.  If so, it
+ *             returns the following info:
+ *                     the found relation number (same as targetrelid unless that is 0)
+ *                     the found var number (or InvalidAttrNumber if a function)
+ *                     if the "something" is a constant, the value of the constant
+ *                     flags indicating whether a constant was found, and on which side.
+ *             Default values are returned if the expression is too complicated,
+ *             specifically -1 for the relid and attno, 0 for the constant value.
+ *             Note that InvalidAttrNumber is *not* -1, but 0.
  */
 void
 get_relattval(Node *clause,
+                         int targetrelid,
                          int *relid,
                          AttrNumber *attno,
                          Datum *constval,
                          int *flag)
 {
        Var                *left,
-                          *right;
+                          *right,
+                          *other;
+       int                     funcvarno;
 
        /* Careful; the passed clause might not be a binary operator at all */
 
@@ -575,71 +576,96 @@ get_relattval(Node *clause,
        if (!right)
                goto default_results;
 
-       if (IsA(left, Var) &&IsA(right, Const))
+       /* First look for the var or func */
+
+       if (IsA(left, Var) &&
+               (targetrelid == 0 || targetrelid == left->varno))
        {
                *relid = left->varno;
                *attno = left->varattno;
-               *constval = ((Const *) right)->constvalue;
-               *flag = (_SELEC_CONSTANT_RIGHT_ | _SELEC_IS_CONSTANT_);
+               *flag = SEL_RIGHT;
        }
-       else if (IsA(left, Var) &&IsA(right, Param))
+       else if (IsA(right, Var) &&
+                        (targetrelid == 0 || targetrelid == right->varno))
        {
-               *relid = left->varno;
-               *attno = left->varattno;
-               *constval = 0;
-               *flag = (_SELEC_NOT_CONSTANT_);
+               *relid = right->varno;
+               *attno = right->varattno;
+               *flag = 0;
        }
-       else if (is_funcclause((Node *) left) && IsA(right, Const))
+       else if ((funcvarno = is_single_func((Node *) left)) != 0 &&
+                        (targetrelid == 0 || targetrelid == funcvarno))
        {
-               List       *vars = pull_var_clause((Node *) left);
-
-               *relid = ((Var *) lfirst(vars))->varno;
+               *relid = funcvarno;
                *attno = InvalidAttrNumber;
-               *constval = ((Const *) right)->constvalue;
-               *flag = (_SELEC_CONSTANT_RIGHT_ | _SELEC_IS_CONSTANT_);
+               *flag = SEL_RIGHT;
        }
-       else if (IsA(right, Var) &&IsA(left, Const))
+       else if ((funcvarno = is_single_func((Node *) right)) != 0 &&
+                        (targetrelid == 0 || targetrelid == funcvarno))
        {
-               *relid = right->varno;
-               *attno = right->varattno;
-               *constval = ((Const *) left)->constvalue;
-               *flag = (_SELEC_IS_CONSTANT_);
+               *relid = funcvarno;
+               *attno = InvalidAttrNumber;
+               *flag = 0;
        }
-       else if (IsA(right, Var) &&IsA(left, Param))
+       else
        {
-               *relid = right->varno;
-               *attno = right->varattno;
+               /* Duh, it's too complicated for me... */
+default_results:
+               *relid = -1;
+               *attno = -1;
                *constval = 0;
-               *flag = (_SELEC_NOT_CONSTANT_);
+               *flag = 0;
+               return;
        }
-       else if (is_funcclause((Node *) right) && IsA(left, Const))
-       {
-               List       *vars = pull_var_clause((Node *) right);
 
-               *relid = ((Var *) lfirst(vars))->varno;
-               *attno = InvalidAttrNumber;
-               *constval = ((Const *) left)->constvalue;
-               *flag = (_SELEC_IS_CONSTANT_);
+       /* OK, we identified the var or func; now look at the other side */
+
+       other = (*flag == 0) ? left : right;
+
+       if (IsA(other, Const))
+       {
+               *constval = ((Const *) other)->constvalue;
+               *flag |= SEL_CONSTANT;
        }
        else
        {
-               /* Duh, it's too complicated for me... */
-default_results:
-               *relid = _SELEC_VALUE_UNKNOWN_;
-               *attno = _SELEC_VALUE_UNKNOWN_;
                *constval = 0;
-               *flag = (_SELEC_NOT_CONSTANT_);
        }
 }
 
 /*
- * get_relsatts
+ * is_single_func
+ *   If the given expression is a function of a single relation,
+ *   return the relation number; else return 0
+ */
+static int is_single_func(Node *node)
+{
+       if (is_funcclause(node))
+       {
+               List       *vars = pull_var_clause(node);
+
+               if (vars != NIL)
+               {
+                       int             funcvarno = ((Var *) lfirst(vars))->varno;
+                       /* need to check that all args of func are same relation */
+                       while ((vars = lnext(vars)) != NIL)
+                       {
+                               if (((Var *) lfirst(vars))->varno != funcvarno)
+                                       return 0;
+                       }
+                       return funcvarno;
+               }
+       }
+       return 0;
+}
+
+/*
+ * get_rels_atts
  *
- * Returns a list
+ * Returns the info
  *                             ( relid1 attno1 relid2 attno2 )
  *             for a joinclause.
  *
- * If the clause is not of the form (op var var) or if any of the vars
+ * If the clause is not of the form (var op var) or if any of the vars
  * refer to nested attributes, then -1's are returned.
  *
  */
@@ -650,6 +676,12 @@ get_rels_atts(Node *clause,
                          int *relid2,
                          AttrNumber *attno2)
 {
+       /* set default values */
+       *relid1 = -1;
+       *attno1 = -1;
+       *relid2 = -1;
+       *attno2 = -1;
+
        if (is_opclause(clause))
        {
                Var                *left = get_leftop((Expr *) clause);
@@ -657,47 +689,31 @@ get_rels_atts(Node *clause,
 
                if (left && right)
                {
-                       bool            var_left = IsA(left, Var);
-                       bool            var_right = IsA(right, Var);
-                       bool            varexpr_left = (bool) ((IsA(left, Func) ||IsA(left, Oper)) &&
-                                                                         contain_var_clause((Node *) left));
-                       bool            varexpr_right = (bool) ((IsA(right, Func) ||IsA(right, Oper)) &&
-                                                                        contain_var_clause((Node *) right));
-
-                       if (var_left && var_right)
-                       {
+                       int                     funcvarno;
 
-                               *relid1 = left->varno;
-                               *attno1 = left->varoattno;
-                               *relid2 = right->varno;
-                               *attno2 = right->varoattno;
-                               return;
-                       }
-                       if (var_left && varexpr_right)
+                       if (IsA(left, Var))
                        {
-
                                *relid1 = left->varno;
-                               *attno1 = left->varoattno;
-                               *relid2 = _SELEC_VALUE_UNKNOWN_;
-                               *attno2 = _SELEC_VALUE_UNKNOWN_;
-                               return;
+                               *attno1 = left->varattno;
                        }
-                       if (varexpr_left && var_right)
+                       else if ((funcvarno = is_single_func((Node *) left)) != 0)
                        {
+                               *relid1 = funcvarno;
+                               *attno1 = InvalidAttrNumber;
+                       }
 
-                               *relid1 = _SELEC_VALUE_UNKNOWN_;
-                               *attno1 = _SELEC_VALUE_UNKNOWN_;
+                       if (IsA(right, Var))
+                       {
                                *relid2 = right->varno;
-                               *attno2 = right->varoattno;
-                               return;
+                               *attno2 = right->varattno;
+                       }
+                       else if ((funcvarno = is_single_func((Node *) right)) != 0)
+                       {
+                               *relid2 = funcvarno;
+                               *attno2 = InvalidAttrNumber;
                        }
                }
        }
-
-       *relid1 = _SELEC_VALUE_UNKNOWN_;
-       *attno1 = _SELEC_VALUE_UNKNOWN_;
-       *relid2 = _SELEC_VALUE_UNKNOWN_;
-       *attno2 = _SELEC_VALUE_UNKNOWN_;
 }
 
 /*--------------------
index 52689d96a4d5184c59627208db77d35910ed7faa..658ee57baaa667e78eb9daa296d942696863634f 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.47 1999/07/24 23:21:14 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.48 1999/07/25 23:07:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -334,7 +334,12 @@ create_index_path(Query *root,
        pathnode->path.pathorder = makeNode(PathOrder);
        pathnode->path.pathorder->ordtype = SORTOP_ORDER;
        pathnode->path.pathorder->ord.sortop = index->ordering;
+       pathnode->path.pathkeys = NIL;
 
+       /* Note that we are making a pathnode for a single-scan indexscan;
+        * therefore, both indexid and indexqual should be single-element
+        * lists (unless indexqual is empty).
+        */
        pathnode->indexid = index->relids;
        pathnode->indexkeys = index->indexkeys;
        pathnode->indexqual = NIL;
@@ -344,7 +349,7 @@ create_index_path(Query *root,
         * JMH, 7/7/92
         */
        pathnode->path.loc_restrictinfo = set_difference((List *) copyObject((Node *) rel->restrictinfo),
-                                                                                  (List *) restriction_clauses);
+                                                                                                        restriction_clauses);
 
        /*
         * The index must have an ordering for the path to have (ordering)
@@ -385,49 +390,28 @@ create_index_path(Query *root,
                                                                                          index->pages,
                                                                                          index->tuples,
                                                                                          false);
-#ifdef NOT_USED
-               /* add in expensive functions cost!  -- JMH, 7/7/92 */
-               if (XfuncMode != XFUNC_OFF)
-               {
-                       pathnode->path_cost = (pathnode->path_cost +
-                                                                xfunc_get_path_cost((Path *) pathnode));
-               }
-#endif
        }
        else
        {
-
                /*
                 * Compute scan cost for the case when 'index' is used with a
                 * restriction clause.
                 */
-               List       *attnos;
-               List       *values;
-               List       *flags;
+               List       *indexquals;
                float           npages;
                float           selec;
                Cost            clausesel;
 
-               get_relattvals(restriction_clauses,
-                                          &attnos,
-                                          &values,
-                                          &flags);
-               index_selectivity(lfirsti(index->relids),
-                                                 index->classlist,
-                                                 get_opnos(restriction_clauses),
-                                                 getrelid(lfirsti(rel->relids),
-                                                                  root->rtable),
-                                                 attnos,
-                                                 values,
-                                                 flags,
-                                                 length(restriction_clauses),
+               indexquals = get_actual_clauses(restriction_clauses);
+
+               index_selectivity(root,
+                                                 lfirsti(rel->relids),
+                                                 lfirsti(index->relids),
+                                                 indexquals,
                                                  &npages,
                                                  &selec);
-               /* each clause gets an equal selectivity */
-               clausesel = pow(selec, 1.0 / (double) length(restriction_clauses));
 
-               pathnode->indexqual = lcons(get_actual_clauses(restriction_clauses),
-                                                                       NIL);
+               pathnode->indexqual = lcons(indexquals, NIL);
                pathnode->path.path_cost = cost_index(lfirsti(index->relids),
                                                                                          (int) npages,
                                                                                          selec,
@@ -437,21 +421,24 @@ create_index_path(Query *root,
                                                                                          index->tuples,
                                                                                          false);
 
-#ifdef NOT_USED
-               /* add in expensive functions cost!  -- JMH, 7/7/92 */
-               if (XfuncMode != XFUNC_OFF)
-                       pathnode->path_cost += xfunc_get_path_cost((Path *) pathnode);
-#endif
-
                /*
                 * Set selectivities of clauses used with index to the selectivity
                 * of this index, subdividing the selectivity equally over each of
                 * the clauses.
+                * XXX Can this divide the selectivities in a better way?
+                * XXX In fact, why the heck are we doing this at all?  We already
+                * set the cost for the indexpath.
                 */
-
-               /* XXX Can this divide the selectivities in a better way? */
+               clausesel = pow(selec, 1.0 / (double) length(restriction_clauses));
                set_clause_selectivities(restriction_clauses, clausesel);
        }
+
+#ifdef NOT_USED
+       /* add in expensive functions cost!  -- JMH, 7/7/92 */
+       if (XfuncMode != XFUNC_OFF)
+               pathnode->path_cost += xfunc_get_path_cost((Path *) pathnode);
+#endif
+
        return pathnode;
 }
 
index deb1d021165a9495a31ed374a75a54e0a5a041a8..a428e027f611dceb9f8d0e8f2043bf630b6523e5 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.35 1999/07/17 20:17:18 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.36 1999/07/25 23:07:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "catalog/catname.h"
 #include "catalog/pg_amop.h"
 #include "catalog/pg_inherits.h"
+#include "optimizer/clauses.h"
 #include "optimizer/internal.h"
 #include "optimizer/plancat.h"
 #include "parser/parsetree.h"
 #include "utils/syscache.h"
 
 
-static void IndexSelectivity(Oid indexrelid, Oid indrelid, int32 nIndexKeys,
-                                Oid *AccessMethodOperatorClasses, Oid *operatorObjectIds,
-          int32 *varAttributeNumbers, char **constValues, int32 *constFlags,
-                                float *idxPages, float *idxSelec);
+static void IndexSelectivity(Oid indexrelid, Oid baserelid, int nIndexKeys,
+                                                        Oid *operatorObjectIds,
+                                                        AttrNumber *varAttributeNumbers,
+                                                        Datum *constValues,
+                                                        int *constFlags,
+                                                        float *idxPages,
+                                                        float *idxSelec);
 
 
 /*
@@ -212,85 +216,75 @@ index_info(Query *root, bool first, int relid, IdxInfoRetval *info)
 
 /*
  * index_selectivity
+ *       Estimate the selectivity of an index scan with the given index quals.
  *
- *       Call util/plancat.c:IndexSelectivity with the indicated arguments.
- *
- * 'indid' is the index OID
- * 'classes' is a list of index key classes
- * 'opnos' is a list of index key operator OIDs
- * 'relid' is the OID of the relation indexed
- * 'attnos' is a list of the relation attnos which the index keys over
- * 'values' is a list of the values of the clause's constants
- * 'flags' is a list of fixnums which describe the constants
- * 'nkeys' is the number of index keys
- *
- * Returns two floats: index pages and index selectivity in 'idxPages' and
- *             'idxSelec'.
+ *       NOTE: an indexscan plan node can actually represent several passes,
+ *       but here we consider the cost of just one pass.
  *
+ * 'root' is the query root
+ * 'relid' is the RT index of the relation being scanned
+ * 'indexid' is the OID of the index to be used
+ * 'indexquals' is the list of qual condition exprs (implicit AND semantics)
+ * '*idxPages' receives an estimate of the number of index pages touched
+ * '*idxSelec' receives an estimate of selectivity of the scan
  */
 void
-index_selectivity(Oid indid,
-                                 Oid *classes,
-                                 List *opnos,
-                                 Oid relid,
-                                 List *attnos,
-                                 List *values,
-                                 List *flags,
-                                 int32 nkeys,
+index_selectivity(Query *root,
+                                 int relid,
+                                 Oid indexid,
+                                 List *indexquals,
                                  float *idxPages,
                                  float *idxSelec)
 {
+       int                     nclauses = length(indexquals);
        Oid                *opno_array;
-       int                *attno_array,
-                          *flag_array;
-       char      **value_array;
-       int                     i = 0;
-       List       *xopno,
-                          *xattno,
-                          *value,
-                          *flag;
-
-       if (length(opnos) != nkeys || length(attnos) != nkeys ||
-               length(values) != nkeys || length(flags) != nkeys)
-       {
+       AttrNumber *attno_array;
+       Datum      *value_array;
+       int                *flag_array;
+       List       *q;
+       int                     i;
 
+       if (nclauses <= 0)
+       {
                *idxPages = 0.0;
                *idxSelec = 1.0;
                return;
        }
-
-       opno_array = (Oid *) palloc(nkeys * sizeof(Oid));
-       attno_array = (int *) palloc(nkeys * sizeof(int32));
-       value_array = (char **) palloc(nkeys * sizeof(char *));
-       flag_array = (int *) palloc(nkeys * sizeof(int32));
+       opno_array = (Oid *) palloc(nclauses * sizeof(Oid));
+       attno_array = (AttrNumber *) palloc(nclauses * sizeof(AttrNumber));
+       value_array = (Datum *) palloc(nclauses * sizeof(Datum));
+       flag_array = (int *) palloc(nclauses * sizeof(int));
 
        i = 0;
-       foreach(xopno, opnos)
-               opno_array[i++] = lfirsti(xopno);
-
-       i = 0;
-       foreach(xattno, attnos)
-               attno_array[i++] = lfirsti(xattno);
+       foreach(q, indexquals)
+       {
+               Node       *expr = (Node *) lfirst(q);
+               int                     dummyrelid;
 
-       i = 0;
-       foreach(value, values)
-               value_array[i++] = (char *) lfirst(value);
+               if (is_opclause(expr))
+                       opno_array[i] = ((Oper *) ((Expr *) expr)->oper)->opno;
+               else
+                       opno_array[i] = InvalidOid;
 
-       i = 0;
-       foreach(flag, flags)
-               flag_array[i++] = lfirsti(flag);
+               get_relattval(expr, relid, &dummyrelid, &attno_array[i],
+                                         &value_array[i], &flag_array[i]);
+               i++;
+       }
 
-       IndexSelectivity(indid,
-                                        relid,
-                                        nkeys,
-                                        classes,       /* not used */
+       IndexSelectivity(indexid,
+                                        getrelid(relid, root->rtable),
+                                        nclauses,
                                         opno_array,
                                         attno_array,
                                         value_array,
                                         flag_array,
                                         idxPages,
                                         idxSelec);
-       return;
+
+       pfree(opno_array);
+       pfree(attno_array);
+       pfree(value_array);
+       pfree(flag_array);
 }
 
 /*
@@ -312,8 +306,8 @@ restriction_selectivity(Oid functionObjectId,
                                                Oid operatorObjectId,
                                                Oid relationObjectId,
                                                AttrNumber attributeNumber,
-                                               char *constValue,
-                                               int32 constFlag)
+                                               Datum constValue,
+                                               int constFlag)
 {
        float64         result;
 
@@ -456,35 +450,29 @@ VersionGetParents(Oid verrelid)
  *****************************************************************************/
 
 /*
- * IdexSelectivity
+ * IndexSelectivity
  *
- *       Retrieves the 'amopnpages' and 'amopselect' parameters for each
+ *       Calls the 'amopnpages' and 'amopselect' functions for each
  *       AM operator when a given index (specified by 'indexrelid') is used.
- *       These two parameters are returned by copying them to into an array of
- *       floats.
+ *       The total number of pages and product of the selectivities are returned.
  *
  *       Assumption: the attribute numbers and operator ObjectIds are in order
  *       WRT to each other (otherwise, you have no way of knowing which
  *       AM operator class or attribute number corresponds to which operator.
  *
+ * 'nIndexKeys' is the number of qual clauses in use
  * 'varAttributeNumbers' contains attribute numbers for variables
  * 'constValues' contains the constant values
  * 'constFlags' describes how to treat the constants in each clause
- * 'nIndexKeys' describes how many keys the index actually has
- *
- * Returns 'selectivityInfo' filled with the sum of all pages touched
- * and the product of each clause's selectivity.
- *
  */
 static void
 IndexSelectivity(Oid indexrelid,
-                                Oid indrelid,
-                                int32 nIndexKeys,
-                                Oid *AccessMethodOperatorClasses,              /* XXX not used? */
+                                Oid baserelid,
+                                int nIndexKeys,
                                 Oid *operatorObjectIds,
-                                int32 *varAttributeNumbers,
-                                char **constValues,
-                                int32 *constFlags,
+                                AttrNumber *varAttributeNumbers,
+                                Datum *constValues,
+                                int *constFlags,
                                 float *idxPages,
                                 float *idxSelec)
 {
@@ -493,6 +481,7 @@ IndexSelectivity(Oid indexrelid,
        HeapTuple       indexTuple,
                                amopTuple,
                                indRel;
+       Form_pg_class indexrelation;
        Form_pg_index index;
        Form_pg_amop amop;
        Oid                     indclass;
@@ -510,7 +499,8 @@ IndexSelectivity(Oid indexrelid,
        if (!HeapTupleIsValid(indRel))
                elog(ERROR, "IndexSelectivity: index %u not found",
                         indexrelid);
-       relam = ((Form_pg_class) GETSTRUCT(indRel))->relam;
+       indexrelation = (Form_pg_class) GETSTRUCT(indRel);
+       relam = indexrelation->relam;
 
        indexTuple = SearchSysCacheTuple(INDEXRELID,
                                                                         ObjectIdGetDatum(indexrelid),
@@ -530,9 +520,8 @@ IndexSelectivity(Oid indexrelid,
 
        npages = 0.0;
        select = 1.0;
-       for (n = 0; n < nIndexKeys; ++n)
+       for (n = 0; n < nIndexKeys; n++)
        {
-
                /*
                 * Find the AM class for this key.
                 *
@@ -567,49 +556,43 @@ IndexSelectivity(Oid indexrelid,
 
                amopTuple = SearchSysCacheTuple(AMOPOPID,
                                                                                ObjectIdGetDatum(indclass),
-                                                                 ObjectIdGetDatum(operatorObjectIds[n]),
+                                                                               ObjectIdGetDatum(operatorObjectIds[n]),
                                                                                ObjectIdGetDatum(relam),
                                                                                0);
                if (!HeapTupleIsValid(amopTuple))
-                       elog(ERROR, "IndexSelectivity: no amop %u %u",
-                                indclass, operatorObjectIds[n]);
+                       elog(ERROR, "IndexSelectivity: no amop %u %u %u",
+                                indclass, operatorObjectIds[n], relam);
                amop = (Form_pg_amop) GETSTRUCT(amopTuple);
 
                if (!nphack)
                {
                        amopnpages = (float64) fmgr(amop->amopnpages,
                                                                                (char *) operatorObjectIds[n],
-                                                                               (char *) indrelid,
-                                                                               (char *) varAttributeNumbers[n],
+                                                                               (char *) baserelid,
+                                                                               (char *) (int) varAttributeNumbers[n],
                                                                                (char *) constValues[n],
                                                                                (char *) constFlags[n],
                                                                                (char *) nIndexKeys,
                                                                                (char *) indexrelid);
-#ifdef NOT_USED
-/*
- * So cool guys! Npages for x > 10 and x < 20 is twice as
- * npages for x > 10!  - vadim 04/09/97
- */
-                       npages += PointerIsValid(amopnpages) ? *amopnpages : 0.0;
-                       if ((i = npages) < npages)      /* ceil(npages)? */
-                               npages += 1.0;
-#endif
-                       npages += PointerIsValid(amopnpages) ? *amopnpages : 0.0;
+                       if (PointerIsValid(amopnpages))
+                               npages += *amopnpages;
                }
 
                amopselect = (float64) fmgr(amop->amopselect,
                                                                        (char *) operatorObjectIds[n],
-                                                                       (char *) indrelid,
-                                                                       (char *) varAttributeNumbers[n],
+                                                                       (char *) baserelid,
+                                                                       (char *) (int) varAttributeNumbers[n],
                                                                        (char *) constValues[n],
                                                                        (char *) constFlags[n],
                                                                        (char *) nIndexKeys,
                                                                        (char *) indexrelid);
 
-               if (nphack && varAttributeNumbers[n] == index->indkey[0])
-                       fattr_select *= PointerIsValid(amopselect) ? *amopselect : 1.0;
-
-               select *= PointerIsValid(amopselect) ? *amopselect : 1.0;
+               if (PointerIsValid(amopselect))
+               {
+                       select *= *amopselect;
+                       if (nphack && varAttributeNumbers[n] == index->indkey[0])
+                               fattr_select *= *amopselect;
+               }
        }
 
        /*
@@ -618,7 +601,7 @@ IndexSelectivity(Oid indexrelid,
         */
        if (nphack)
        {
-               npages = fattr_select * ((Form_pg_class) GETSTRUCT(indRel))->relpages;
+               npages = fattr_select * indexrelation->relpages;
                *idxPages = ceil((double) npages);
        }
        else
index 4dfdf66fcbce676d079e39992c8c8dd0d2a2fbce..a77656e974bca26ddea7d3ccdee8c8aebd9e4411 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.7 1999/07/24 23:21:14 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.8 1999/07/25 23:07:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,144 +44,14 @@ restriction_is_or_clause(RestrictInfo *restrictinfo)
 List *
 get_actual_clauses(List *restrictinfo_list)
 {
-       List       *temp = NIL;
        List       *result = NIL;
-       RestrictInfo *clause = (RestrictInfo *) NULL;
-
-       foreach(temp, restrictinfo_list)
-       {
-               clause = (RestrictInfo *) lfirst(temp);
-               result = lappend(result, clause->clause);
-       }
-       return result;
-}
-
-/*
- * XXX NOTE:
- *             The following routines must return their contents in the same order
- *             (e.g., the first clause's info should be first, and so on) or else
- *             get_index_sel() won't work.
- *
- */
-
-/*
- * get_relattvals
- *       For each member of  a list of restrictinfo nodes to be used with an
- *       index, create a vectori-long specifying:
- *                             the attnos,
- *                             the values of the clause constants, and
- *                             flags indicating the type and location of the constant within
- *                                             each clause.
- *       Each clause is of the form (op var some_type_of_constant), thus the
- *       flag indicating whether the constant is on the left or right should
- *       always be *SELEC-CONSTANT-RIGHT*.
- *
- * 'restrictinfo_list' is a list of restrictinfo nodes
- *
- * Returns a list of vectori-longs.
- *
- */
-void
-get_relattvals(List *restrictinfo_list,
-                          List **attnos,
-                          List **values,
-                          List **flags)
-{
-       List       *result1 = NIL;
-       List       *result2 = NIL;
-       List       *result3 = NIL;
-       RestrictInfo *temp = (RestrictInfo *) NULL;
-       List       *i = NIL;
-
-       foreach(i, restrictinfo_list)
-       {
-               int                     dummy;
-               AttrNumber      attno;
-               Datum           constval;
-               int                     flag;
-
-               temp = (RestrictInfo *) lfirst(i);
-               get_relattval((Node *) temp->clause, &dummy, &attno, &constval, &flag);
-               result1 = lappendi(result1, (int) attno);
-               result2 = lappendi(result2, constval);
-               result3 = lappendi(result3, flag);
-       }
-
-       *attnos = result1;
-       *values = result2;
-       *flags = result3;
-       return;
-}
-
-/*
- * get_joinvars
- *       Given a list of join restrictinfo nodes to be used with the index
- *       of an inner join relation, return three lists consisting of:
- *                             the attributes corresponding to the inner join relation
- *                             the value of the inner var clause (always "")
- *                             whether the attribute appears on the left or right side of
- *                                             the operator.
- *
- * 'relid' is the inner join relation
- * 'restrictinfo_list' is a list of qualification clauses to be used with
- *             'rel'
- *
- */
-void
-get_joinvars(Oid relid,
-                        List *restrictinfo_list,
-                        List **attnos,
-                        List **values,
-                        List **flags)
-{
-       List       *result1 = NIL;
-       List       *result2 = NIL;
-       List       *result3 = NIL;
        List       *temp;
 
        foreach(temp, restrictinfo_list)
        {
-               RestrictInfo *restrictinfo = lfirst(temp);
-               Expr       *clause = restrictinfo->clause;
+               RestrictInfo *clause = (RestrictInfo *) lfirst(temp);
 
-               if (IsA(get_leftop(clause), Var) &&
-                       (relid == (get_leftop(clause))->varno))
-               {
-                       result1 = lappendi(result1, (int4) (get_leftop(clause))->varattno);
-                       result2 = lappend(result2, "");
-                       result3 = lappendi(result3, _SELEC_CONSTANT_RIGHT_);
-               }
-               else
-               {
-                       result1 = lappendi(result1, (int4) (get_rightop(clause))->varattno);
-                       result2 = lappend(result2, "");
-                       result3 = lappendi(result3, _SELEC_CONSTANT_LEFT_);
-               }
-       }
-       *attnos = result1;
-       *values = result2;
-       *flags = result3;
-       return;
-}
-
-/*
- * get_opnos
- *       Create and return a list containing the clause operators of each member
- *       of a list of restrictinfo nodes to be used with an index.
- *
- */
-List *
-get_opnos(List *restrictinfo_list)
-{
-       RestrictInfo *temp = (RestrictInfo *) NULL;
-       List       *result = NIL;
-       List       *i = NIL;
-
-       foreach(i, restrictinfo_list)
-       {
-               temp = (RestrictInfo *) lfirst(i);
-               result = lappendi(result,
-                                                 (((Oper *) temp->clause->oper)->opno));
+               result = lappend(result, clause->clause);
        }
        return result;
 }
index e362b7c64d9eebeca2d19070e7b4f2fe01af1bff..748c0d46e9fd9818eb79aae2e35e08771b0c411b 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: clauses.h,v 1.22 1999/07/24 23:21:05 tgl Exp $
+ * $Id: clauses.h,v 1.23 1999/07/25 23:07:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -45,8 +45,9 @@ extern bool is_joinable(Node *clause);
 extern bool qual_clause_p(Node *clause);
 extern void fix_opid(Node *clause);
 extern List *fix_opids(List *clauses);
-extern void get_relattval(Node *clause, int *relid,
-                         AttrNumber *attno, Datum *constval, int *flag);
+extern void get_relattval(Node *clause, int targetrelid,
+                                                 int *relid, AttrNumber *attno,
+                                                 Datum *constval, int *flag);
 extern void get_rels_atts(Node *clause, int *relid1,
                          AttrNumber *attno1, int *relid2, AttrNumber *attno2);
 extern void CommuteClause(Node *clause);
index faa573bbe766d2e799ba18ac65737b65130abd14..5cf04f70ef34658559edb64164b1471a98de7bd3 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: internal.h,v 1.22 1999/07/15 15:21:21 momjian Exp $
+ * $Id: internal.h,v 1.23 1999/07/25 23:07:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 /* used to be -1 */
 #define _NONAME_RELATION_ID_    InvalidOid
 
-/*        Identifier for invalid relation OIDs and attribute numbers for use by
- *        selectivity functions
- */
-#define _SELEC_VALUE_UNKNOWN_  (-1)
-
-/*        Flag indicating that a clause constant is really a parameter (or other
- *             non-constant?), a non-parameter, or a constant on the right side
- *             of the clause.
- */
-#define _SELEC_NOT_CONSTANT_   0
-#define _SELEC_IS_CONSTANT_    1
-#define _SELEC_CONSTANT_LEFT_  0
-#define _SELEC_CONSTANT_RIGHT_ 2
-
 /* #define deactivate_joininfo(joininfo)               joininfo->inactive=true*/
 /*#define joininfo_inactive(joininfo)  joininfo->inactive */
 
index 90c5e3e099fe6c61c11afc50bd990584007536a2..9a12ecb1d8cb1d88a4ed27d09eccff5821d886a1 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: plancat.h,v 1.12 1999/07/15 23:03:58 momjian Exp $
+ * $Id: plancat.h,v 1.13 1999/07/25 23:07:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -46,12 +46,12 @@ extern Cost restriction_selectivity(Oid functionObjectId,
                                                Oid operatorObjectId,
                                                Oid relationObjectId,
                                                AttrNumber attributeNumber,
-                                               char *constValue,
-                                               int32 constFlag);
+                                               Datum constValue,
+                                               int constFlag);
 
-extern void index_selectivity(Oid indid, Oid *classes, List *opnos,
-                                 Oid relid, List *attnos, List *values, List *flags,
-                                 int32 nkeys, float *idxPages, float *idxSelec);
+extern void index_selectivity(Query *root, int relid, Oid indexid,
+                                                         List *indexquals,
+                                                         float *idxPages, float *idxSelec);
 
 extern Cost join_selectivity(Oid functionObjectId, Oid operatorObjectId,
                                 Oid relationObjectId1, AttrNumber attributeNumber1,
index 7412ca46fa0bf10aa2b1ff16dc49abb823e1bb88..e6b5e2d89b16508e1a20f730c8764689d4a8e3a7 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: restrictinfo.h,v 1.6 1999/07/24 23:21:05 tgl Exp $
+ * $Id: restrictinfo.h,v 1.7 1999/07/25 23:07:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 extern bool restriction_is_or_clause(RestrictInfo *restrictinfo);
 extern List *get_actual_clauses(List *restrictinfo_list);
-extern void get_relattvals(List *restrictinfo_list, List **attnos,
-                          List **values, List **flags);
-extern void get_joinvars(Oid relid, List *restrictinfo_list,
-                        List **attnos, List **values, List **flags);
-extern List *get_opnos(List *restrictinfo_list);
 
 #endif  /* RESTRICTINFO_H */