diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2001-05-20 20:28:20 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2001-05-20 20:28:20 +0000 |
commit | be03eb25f34c9c95c400504ef76c8abe0081d09f (patch) | |
tree | ca3b081710826485bdaaad375b80e82f5a7fd611 /src/backend/optimizer/plan/createplan.c | |
parent | 5d53389cfe5ecacadda12f3a777a642605278e49 (diff) | |
download | postgresql-be03eb25f34c9c95c400504ef76c8abe0081d09f.tar.gz postgresql-be03eb25f34c9c95c400504ef76c8abe0081d09f.zip |
Modify optimizer data structures so that IndexOptInfo lists built for
create_index_paths are not immediately discarded, but are available for
subsequent planner work. This allows avoiding redundant syscache lookups
in several places. Change interface to operator selectivity estimation
procedures to allow faster and more flexible estimation.
Initdb forced due to change of pg_proc entries for selectivity functions!
Diffstat (limited to 'src/backend/optimizer/plan/createplan.c')
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 133 |
1 files changed, 48 insertions, 85 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 2d264c46881..81e7fec0427 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.105 2001/05/07 00:43:20 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.106 2001/05/20 20:28:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -18,7 +18,6 @@ #include <sys/types.h> -#include "catalog/pg_index.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "optimizer/clauses.h" @@ -27,6 +26,7 @@ #include "optimizer/planmain.h" #include "optimizer/restrictinfo.h" #include "optimizer/tlist.h" +#include "optimizer/var.h" #include "parser/parse_expr.h" #include "utils/lsyscache.h" #include "utils/syscache.h" @@ -56,11 +56,11 @@ static HashJoin *create_hashjoin_plan(HashPath *best_path, List *tlist, Plan *outer_plan, List *outer_tlist, Plan *inner_plan, List *inner_tlist); static List *fix_indxqual_references(List *indexquals, IndexPath *index_path); -static List *fix_indxqual_sublist(List *indexqual, int baserelid, Oid relam, - Form_pg_index index); +static List *fix_indxqual_sublist(List *indexqual, int baserelid, + IndexOptInfo *index); static Node *fix_indxqual_operand(Node *node, int baserelid, - Form_pg_index index, - Oid *opclass); + IndexOptInfo *index, + Oid *opclass); static List *switch_outer(List *clauses); static void copy_path_costsize(Plan *dest, Path *src); static void copy_plan_costsize(Plan *dest, Plan *src); @@ -365,7 +365,7 @@ create_seqscan_plan(Path *best_path, List *tlist, List *scan_clauses) * The indexqual of the path contains a sublist of implicitly-ANDed qual * conditions for each scan of the index(es); if there is more than one * scan then the retrieved tuple sets are ORed together. The indexqual - * and indexid lists must have the same length, ie, the number of scans + * and indexinfo lists must have the same length, ie, the number of scans * that will occur. Note it is possible for a qual condition sublist * to be empty --- then no index restrictions will be applied during that * scan. @@ -380,9 +380,10 @@ create_indexscan_plan(Query *root, Index baserelid; List *qpqual; List *fixed_indxqual; - List *ixid; + List *indexids; + List *ixinfo; IndexScan *scan_plan; - bool lossy = false; + bool lossy; /* there should be exactly one base rel involved... */ Assert(length(best_path->path.parent->relids) == 1); @@ -390,25 +391,18 @@ create_indexscan_plan(Query *root, baserelid = lfirsti(best_path->path.parent->relids); - /* check to see if any of the indices are lossy */ - foreach(ixid, best_path->indexid) + /* + * Build list of index OIDs, and check to see if any of the indices + * are lossy. + */ + indexids = NIL; + lossy = false; + foreach(ixinfo, best_path->indexinfo) { - HeapTuple indexTuple; - Form_pg_index index; - - indexTuple = SearchSysCache(INDEXRELID, - ObjectIdGetDatum(lfirsti(ixid)), - 0, 0, 0); - if (!HeapTupleIsValid(indexTuple)) - elog(ERROR, "create_plan: index %u not found", lfirsti(ixid)); - index = (Form_pg_index) GETSTRUCT(indexTuple); - if (index->indislossy) - { - lossy = true; - ReleaseSysCache(indexTuple); - break; - } - ReleaseSysCache(indexTuple); + IndexOptInfo *index = (IndexOptInfo *) lfirst(ixinfo); + + indexids = lappendi(indexids, index->indexoid); + lossy |= index->lossy; } /* @@ -471,7 +465,7 @@ create_indexscan_plan(Query *root, scan_plan = make_indexscan(tlist, qpqual, baserelid, - best_path->indexid, + indexids, fixed_indxqual, indxqual, best_path->indexscandir); @@ -895,45 +889,19 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path) { List *fixed_quals = NIL; int baserelid = lfirsti(index_path->path.parent->relids); - List *indexids = index_path->indexid; + List *ixinfo = index_path->indexinfo; List *i; foreach(i, indexquals) { List *indexqual = lfirst(i); - Oid indexid = lfirsti(indexids); - HeapTuple indexTuple; - Oid relam; - Form_pg_index index; - - /* Get the relam from the index's pg_class entry */ - indexTuple = SearchSysCache(RELOID, - ObjectIdGetDatum(indexid), - 0, 0, 0); - if (!HeapTupleIsValid(indexTuple)) - elog(ERROR, "fix_indxqual_references: index %u not found in pg_class", - indexid); - relam = ((Form_pg_class) GETSTRUCT(indexTuple))->relam; - ReleaseSysCache(indexTuple); - - /* Need the index's pg_index entry for other stuff */ - indexTuple = SearchSysCache(INDEXRELID, - ObjectIdGetDatum(indexid), - 0, 0, 0); - if (!HeapTupleIsValid(indexTuple)) - elog(ERROR, "fix_indxqual_references: index %u not found in pg_index", - indexid); - index = (Form_pg_index) GETSTRUCT(indexTuple); + IndexOptInfo *index = (IndexOptInfo *) lfirst(ixinfo); fixed_quals = lappend(fixed_quals, fix_indxqual_sublist(indexqual, baserelid, - relam, index)); - - ReleaseSysCache(indexTuple); - - indexids = lnext(indexids); + ixinfo = lnext(ixinfo); } return fixed_quals; } @@ -946,8 +914,7 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path) * of the clause.) Also change the operator if necessary. */ static List * -fix_indxqual_sublist(List *indexqual, int baserelid, Oid relam, - Form_pg_index index) +fix_indxqual_sublist(List *indexqual, int baserelid, IndexOptInfo *index) { List *fixed_qual = NIL; List *i; @@ -955,27 +922,15 @@ fix_indxqual_sublist(List *indexqual, int baserelid, Oid relam, foreach(i, indexqual) { Expr *clause = (Expr *) lfirst(i); - int relid; - AttrNumber attno; - Datum constval; - int flag; Expr *newclause; + List *leftvarnos; Oid opclass, newopno; - if (!is_opclause((Node *) clause) || - length(clause->args) != 2) + if (!is_opclause((Node *) clause) || length(clause->args) != 2) elog(ERROR, "fix_indxqual_sublist: indexqual clause is not binary opclause"); /* - * Which side is the indexkey on? - * - * get_relattval sets flag&SEL_RIGHT if the indexkey is on the LEFT. - */ - get_relattval((Node *) clause, baserelid, - &relid, &attno, &constval, &flag); - - /* * Make a copy that will become the fixed clause. * * We used to try to do a shallow copy here, but that fails if there @@ -984,9 +939,15 @@ fix_indxqual_sublist(List *indexqual, int baserelid, Oid relam, */ newclause = (Expr *) copyObject((Node *) clause); - /* If the indexkey is on the right, commute the clause. */ - if ((flag & SEL_RIGHT) == 0) + /* + * Check to see if the indexkey is on the right; if so, commute + * the clause. The indexkey should be the side that refers to + * (only) the base relation. + */ + leftvarnos = pull_varnos((Node *) lfirst(newclause->args)); + if (length(leftvarnos) != 1 || lfirsti(leftvarnos) != baserelid) CommuteClause(newclause); + freeList(leftvarnos); /* * Now, determine which index attribute this is, change the @@ -1002,7 +963,7 @@ fix_indxqual_sublist(List *indexqual, int baserelid, Oid relam, * is merely binary-compatible with the index. This shouldn't * fail, since indxpath.c found it before... */ - newopno = indexable_operator(newclause, opclass, relam, true); + newopno = indexable_operator(newclause, opclass, index->relam, true); if (newopno == InvalidOid) elog(ERROR, "fix_indxqual_sublist: failed to find substitute op"); ((Oper *) newclause->oper)->opno = newopno; @@ -1013,7 +974,7 @@ fix_indxqual_sublist(List *indexqual, int baserelid, Oid relam, } static Node * -fix_indxqual_operand(Node *node, int baserelid, Form_pg_index index, +fix_indxqual_operand(Node *node, int baserelid, IndexOptInfo *index, Oid *opclass) { @@ -1033,27 +994,29 @@ fix_indxqual_operand(Node *node, int baserelid, Form_pg_index index, if (IsA(node, Var)) { /* If it's a var, find which index key position it occupies */ + Assert(index->indproc == InvalidOid); + if (((Var *) node)->varno == baserelid) { int varatt = ((Var *) node)->varattno; int pos; - for (pos = 0; pos < INDEX_MAX_KEYS; pos++) + for (pos = 0; pos < index->nkeys; pos++) { - if (index->indkey[pos] == varatt) + if (index->indexkeys[pos] == varatt) { Node *newnode = copyObject(node); ((Var *) newnode)->varattno = pos + 1; /* return the correct opclass, too */ - *opclass = index->indclass[pos]; + *opclass = index->classlist[pos]; return newnode; } } } /* - * Oops, this Var isn't the indexkey! + * Oops, this Var isn't an indexkey! */ elog(ERROR, "fix_indxqual_operand: var is not index attribute"); } @@ -1063,11 +1026,11 @@ fix_indxqual_operand(Node *node, int baserelid, Form_pg_index index, * Since we currently only support single-column functional indexes, * the returned varattno must be 1. */ + Assert(index->indproc != InvalidOid); + Assert(is_funcclause(node)); /* not a very thorough check, but easy */ - Assert(is_funcclause(node));/* not a very thorough check, but easy */ - - /* indclass[0] is the only class of a functional index */ - *opclass = index->indclass[0]; + /* classlist[0] is the only class of a functional index */ + *opclass = index->classlist[0]; return (Node *) makeVar(baserelid, 1, exprType(node), -1, 0); } |