diff options
Diffstat (limited to 'src/backend/optimizer/path/orindxpath.c')
-rw-r--r-- | src/backend/optimizer/path/orindxpath.c | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/src/backend/optimizer/path/orindxpath.c b/src/backend/optimizer/path/orindxpath.c new file mode 100644 index 00000000000..e040675e6ec --- /dev/null +++ b/src/backend/optimizer/path/orindxpath.c @@ -0,0 +1,271 @@ +/*------------------------------------------------------------------------- + * + * orindxpath.c-- + * Routines to find index paths that match a set of 'or' clauses + * + * Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.1.1.1 1996/07/09 06:21:36 scrappy Exp $ + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "nodes/pg_list.h" +#include "nodes/relation.h" +#include "nodes/primnodes.h" + +#include "nodes/makefuncs.h" +#include "nodes/nodeFuncs.h" + +#include "optimizer/internal.h" +#include "optimizer/clauses.h" +#include "optimizer/clauseinfo.h" +#include "optimizer/paths.h" +#include "optimizer/cost.h" +#include "optimizer/plancat.h" +#include "optimizer/xfunc.h" + +#include "parser/parsetree.h" + + +static void best_or_subclause_indices(Query *root, Rel *rel, List *subclauses, + List *indices, List *examined_indexids, Cost subcost, List *selectivities, + List **indexids, Cost *cost, List **selecs); +static void best_or_subclause_index(Query *root, Rel *rel, Expr *subclause, + List *indices, int *indexid, Cost *cost, Cost *selec); + + +/* + * create-or-index-paths-- + * Creates index paths for indices that match 'or' clauses. + * + * 'rel' is the relation entry for which the paths are to be defined on + * 'clauses' is the list of available restriction clause nodes + * + * Returns a list of these index path nodes. + * + */ +List * +create_or_index_paths(Query *root, + Rel *rel, List *clauses) +{ + List *t_list = NIL; + + if (clauses != NIL) { + CInfo *clausenode = (CInfo *) (lfirst (clauses)); + + /* Check to see if this clause is an 'or' clause, and, if so, + * whether or not each of the subclauses within the 'or' clause has + * been matched by an index (the 'Index field was set in + * (match_or) if no index matches a given subclause, one of the + * lists of index nodes returned by (get_index) will be 'nil'). + */ + if (valid_or_clause(clausenode) && + clausenode->indexids) { + List *temp = NIL; + List *index_list = NIL; + bool index_flag = true; + + index_list = clausenode->indexids; + foreach(temp,index_list) { + if (!temp) + index_flag = false; + } + if (index_flag) { /* used to be a lisp every function */ + IndexPath *pathnode = makeNode(IndexPath); + List *indexids; + Cost cost; + List *selecs; + + best_or_subclause_indices(root, + rel, + clausenode->clause->args, + clausenode->indexids, + NIL, + (Cost)0, + NIL, + &indexids, + &cost, + &selecs); + + pathnode->path.pathtype = T_IndexScan; + pathnode->path.parent = rel; + pathnode->indexqual = + lcons(clausenode,NIL); + pathnode->indexid = indexids; + pathnode->path.path_cost = cost; + + /* copy clauseinfo list into path for expensive + function processing -- JMH, 7/7/92 */ + pathnode->path.locclauseinfo = + set_difference(clauses, + copyObject((Node*) + rel->clauseinfo)); + +#if 0 /* fix xfunc */ + /* add in cost for expensive functions! -- JMH, 7/7/92 */ + if (XfuncMode != XFUNC_OFF) { + ((Path*)pathnode)->path_cost += + xfunc_get_path_cost((Path)pathnode); + } +#endif + clausenode->selectivity = (Cost)floatVal(selecs); + t_list = + lcons(pathnode, + create_or_index_paths(root, rel,lnext(clauses))); + } else { + t_list = create_or_index_paths(root, rel,lnext(clauses)); + } + } + } + + return(t_list); +} + +/* + * best-or-subclause-indices-- + * Determines the best index to be used in conjunction with each subclause + * of an 'or' clause and the cost of scanning a relation using these + * indices. The cost is the sum of the individual index costs. + * + * 'rel' is the node of the relation on which the index is defined + * 'subclauses' are the subclauses of the 'or' clause + * 'indices' are those index nodes that matched subclauses of the 'or' + * clause + * 'examined-indexids' is a list of those index ids to be used with + * subclauses that have already been examined + * 'subcost' is the cost of using the indices in 'examined-indexids' + * 'selectivities' is a list of the selectivities of subclauses that + * have already been examined + * + * Returns a list of the indexids, cost, and selectivities of each + * subclause, e.g., ((i1 i2 i3) cost (s1 s2 s3)), where 'i' is an OID, + * 'cost' is a flonum, and 's' is a flonum. + */ +static void +best_or_subclause_indices(Query *root, + Rel *rel, + List *subclauses, + List *indices, + List *examined_indexids, + Cost subcost, + List *selectivities, + List **indexids, /* return value */ + Cost *cost, /* return value */ + List **selecs) /* return value */ +{ + if (subclauses==NIL) { + *indexids = nreverse(examined_indexids); + *cost = subcost; + *selecs = nreverse(selectivities); + } else { + int best_indexid; + Cost best_cost; + Cost best_selec; + + best_or_subclause_index(root, rel, lfirst(subclauses), lfirst(indices), + &best_indexid, &best_cost, &best_selec); + + best_or_subclause_indices(root, + rel, + lnext(subclauses), + lnext(indices), + lconsi(best_indexid, examined_indexids), + subcost + best_cost, + lcons(makeFloat(best_selec), selectivities), + indexids, + cost, + selecs); + } + return; +} + +/* + * best-or-subclause-index-- + * Determines which is the best index to be used with a subclause of + * an 'or' clause by estimating the cost of using each index and selecting + * the least expensive. + * + * 'rel' is the node of the relation on which the index is defined + * 'subclause' is the subclause + * 'indices' is a list of index nodes that match the subclause + * + * Returns a list (index-id index-subcost index-selectivity) + * (a fixnum, a fixnum, and a flonum respectively). + * + */ +static void +best_or_subclause_index(Query *root, + Rel *rel, + Expr *subclause, + List *indices, + int *retIndexid, /* return value */ + Cost *retCost, /* return value */ + Cost *retSelec) /* return value */ +{ + if (indices != NIL) { + Datum value; + int flag = 0; + Cost subcost; + Rel *index = (Rel *)lfirst (indices); + AttrNumber attno = (get_leftop (subclause))->varattno ; + Oid opno = ((Oper*)subclause->oper)->opno; + bool constant_on_right = non_null((Expr*)get_rightop(subclause)); + float npages, selec; + int subclause_indexid; + Cost subclause_cost; + Cost subclause_selec; + + if(constant_on_right) { + value = ((Const*)get_rightop (subclause))->constvalue; + } else { + value = NameGetDatum(""); + } + if(constant_on_right) { + flag = (_SELEC_IS_CONSTANT_ ||_SELEC_CONSTANT_RIGHT_); + } else { + flag = _SELEC_CONSTANT_RIGHT_; + } + index_selectivity(lfirsti(index->relids), + index->classlist, + lconsi(opno,NIL), + getrelid(lfirsti(rel->relids), + root->rtable), + lconsi(attno,NIL), + lconsi(value,NIL), + lconsi(flag,NIL), + 1, + &npages, + &selec); + + subcost = cost_index((Oid) lfirsti(index->relids), + (int)npages, + (Cost)selec, + rel->pages, + rel->tuples, + index->pages, + index->tuples, + false); + best_or_subclause_index(root, + rel, + subclause, + lnext(indices), + &subclause_indexid, + &subclause_cost, + &subclause_selec); + + if (subclause_indexid==0 || subcost < subclause_cost) { + *retIndexid = lfirsti(index->relids); + *retCost = subcost; + *retSelec = selec; + } else { + *retIndexid = 0; + *retCost = 0.0; + *retSelec = 0.0; + } + } + return; +} |