diff options
Diffstat (limited to 'src/backend/optimizer/path/orindxpath.c')
-rw-r--r-- | src/backend/optimizer/path/orindxpath.c | 430 |
1 files changed, 228 insertions, 202 deletions
diff --git a/src/backend/optimizer/path/orindxpath.c b/src/backend/optimizer/path/orindxpath.c index e040675e6ec..96408b78905 100644 --- a/src/backend/optimizer/path/orindxpath.c +++ b/src/backend/optimizer/path/orindxpath.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * orindxpath.c-- - * Routines to find index paths that match a set of 'or' clauses + * 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 $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.2 1997/09/07 04:43:46 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -31,241 +31,267 @@ #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); +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. - * + * 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 * +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; + 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); + 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)); + } } -#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); + 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. - * + * 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 + * 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 - * + * 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 */ +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; -} + 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. - * + * 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 */ +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 (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 (subclause_indexid==0 || subcost < subclause_cost) { - *retIndexid = lfirsti(index->relids); - *retCost = subcost; - *retSelec = selec; - } else { - *retIndexid = 0; - *retCost = 0.0; - *retSelec = 0.0; - } - } - return; + 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; } |