diff options
Diffstat (limited to 'src/backend/optimizer/plan')
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 133 | ||||
-rw-r--r-- | src/backend/optimizer/plan/initsplan.c | 26 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planmain.c | 3 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 5 |
4 files changed, 67 insertions, 100 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); } diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index c62fd5ecd7d..3b3c761bca6 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.61 2001/05/14 20:25:00 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.62 2001/05/20 20:28:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -73,8 +73,8 @@ build_base_rel_tlists(Query *root, List *tlist) /* * add_vars_to_targetlist * For each variable appearing in the list, add it to the relation's - * targetlist if not already present. Rel nodes will also be created - * if not already present. + * targetlist if not already present. Corresponding base rel nodes + * will be created if not already present. */ static void add_vars_to_targetlist(Query *root, List *vars) @@ -84,7 +84,7 @@ add_vars_to_targetlist(Query *root, List *vars) foreach(temp, vars) { Var *var = (Var *) lfirst(temp); - RelOptInfo *rel = get_base_rel(root, var->varno); + RelOptInfo *rel = build_base_rel(root, var->varno); add_var_to_tlist(rel, var); } @@ -120,8 +120,8 @@ add_missing_rels_to_query(Query *root, Node *jtnode) { int varno = ((RangeTblRef *) jtnode)->rtindex; - /* This call to get_base_rel does the primary work... */ - RelOptInfo *rel = get_base_rel(root, varno); + /* This call to build_base_rel does the primary work... */ + RelOptInfo *rel = build_base_rel(root, varno); result = makeList1(rel); } @@ -299,7 +299,7 @@ mark_baserels_for_outer_join(Query *root, Relids rels, Relids outerrels) foreach(relid, rels) { int relno = lfirsti(relid); - RelOptInfo *rel = get_base_rel(root, relno); + RelOptInfo *rel = build_base_rel(root, relno); /* * Since we do this bottom-up, any outer-rels previously marked @@ -422,7 +422,7 @@ distribute_qual_to_rels(Query *root, Node *clause, can_be_equijoin = true; foreach(relid, relids) { - RelOptInfo *rel = get_base_rel(root, lfirsti(relid)); + RelOptInfo *rel = build_base_rel(root, lfirsti(relid)); if (rel->outerjoinset && !is_subseti(rel->outerjoinset, relids)) @@ -454,12 +454,11 @@ distribute_qual_to_rels(Query *root, Node *clause, if (length(relids) == 1) { - /* * There is only one relation participating in 'clause', so * 'clause' is a restriction clause for that relation. */ - RelOptInfo *rel = get_base_rel(root, lfirsti(relids)); + RelOptInfo *rel = build_base_rel(root, lfirsti(relids)); rel->baserestrictinfo = lappend(rel->baserestrictinfo, restrictinfo); @@ -564,7 +563,7 @@ add_join_info_to_rels(Query *root, RestrictInfo *restrictinfo, * Find or make the joininfo node for this combination of rels, * and add the restrictinfo node to it. */ - joininfo = find_joininfo_node(get_base_rel(root, cur_relid), + joininfo = find_joininfo_node(build_base_rel(root, cur_relid), unjoined_relids); joininfo->jinfo_restrictinfo = lappend(joininfo->jinfo_restrictinfo, restrictinfo); @@ -609,8 +608,11 @@ process_implied_equality(Query *root, Node *item1, Node *item2, * If both vars belong to same rel, we need to look at that rel's * baserestrictinfo list. If different rels, each will have a * joininfo node for the other, and we can scan either list. + * + * All baserel entries should already exist at this point, so use + * find_base_rel not build_base_rel. */ - rel1 = get_base_rel(root, irel1); + rel1 = find_base_rel(root, irel1); if (irel1 == irel2) restrictlist = rel1->baserestrictinfo; else diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c index b2b362e84a5..2f52e694d13 100644 --- a/src/backend/optimizer/plan/planmain.c +++ b/src/backend/optimizer/plan/planmain.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.64 2001/03/22 03:59:37 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.65 2001/05/20 20:28:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -194,6 +194,7 @@ subplanner(Query *root, * construction. */ root->base_rel_list = NIL; + root->other_rel_list = NIL; root->join_rel_list = NIL; root->equi_key_list = NIL; diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 0aba4808c16..fbed3d6d092 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.106 2001/05/07 00:43:21 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.107 2001/05/20 20:28:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -206,7 +206,8 @@ subquery_planner(Query *parse, double tuple_fraction) * grouping_planner. */ if (parse->resultRelation && - (lst = expand_inherted_rtentry(parse, parse->resultRelation)) != NIL) + (lst = expand_inherted_rtentry(parse, parse->resultRelation, false)) + != NIL) plan = inheritance_planner(parse, lst); else plan = grouping_planner(parse, tuple_fraction); |