diff options
Diffstat (limited to 'src/backend/optimizer/path/orindxpath.c')
-rw-r--r-- | src/backend/optimizer/path/orindxpath.c | 241 |
1 files changed, 0 insertions, 241 deletions
diff --git a/src/backend/optimizer/path/orindxpath.c b/src/backend/optimizer/path/orindxpath.c deleted file mode 100644 index f0c1a44196d..00000000000 --- a/src/backend/optimizer/path/orindxpath.c +++ /dev/null @@ -1,241 +0,0 @@ -/*------------------------------------------------------------------------- - * - * orindxpath.c - * Routines to find index paths that match a set of 'or' clauses - * - * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.47 2002/06/20 20:29:30 momjian Exp $ - * - *------------------------------------------------------------------------- - */ - -#include "postgres.h" - -#include "optimizer/cost.h" -#include "optimizer/pathnode.h" -#include "optimizer/paths.h" -#include "optimizer/restrictinfo.h" - - -static void best_or_subclause_indices(Query *root, RelOptInfo *rel, - List *subclauses, List *indices, - IndexPath *pathnode); -static void best_or_subclause_index(Query *root, RelOptInfo *rel, - Expr *subclause, List *indices, - IndexOptInfo **retIndexInfo, - List **retIndexQual, - Cost *retStartupCost, - Cost *retTotalCost); - - -/* - * create_or_index_paths - * Creates index paths for indices that match 'or' clauses. - * create_index_paths() must already have been called. - * - * 'rel' is the relation entry for which the paths are to be created - * - * Returns nothing, but adds paths to rel->pathlist via add_path(). - */ -void -create_or_index_paths(Query *root, RelOptInfo *rel) -{ - List *rlist; - - foreach(rlist, rel->baserestrictinfo) - { - RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(rlist); - - /* - * 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 information used was saved - * by create_index_paths(). - */ - if (restriction_is_or_clause(restrictinfo) && - restrictinfo->subclauseindices) - { - bool all_indexable = true; - List *temp; - - foreach(temp, restrictinfo->subclauseindices) - { - if (lfirst(temp) == NIL) - { - all_indexable = false; - break; - } - } - if (all_indexable) - { - /* - * OK, build an IndexPath for this OR clause, using the - * best available index for each subclause. - */ - IndexPath *pathnode = makeNode(IndexPath); - - pathnode->path.pathtype = T_IndexScan; - pathnode->path.parent = rel; - - /* - * This is an IndexScan, but the overall result will - * consist of tuples extracted in multiple passes (one for - * each subclause of the OR), so the result cannot be - * claimed to have any particular ordering. - */ - pathnode->path.pathkeys = NIL; - - /* We don't actually care what order the index scans in. */ - pathnode->indexscandir = NoMovementScanDirection; - - /* This isn't a nestloop innerjoin, so: */ - pathnode->joinrelids = NIL; /* no join clauses here */ - pathnode->alljoinquals = false; - pathnode->rows = rel->rows; - - best_or_subclause_indices(root, - rel, - restrictinfo->clause->args, - restrictinfo->subclauseindices, - pathnode); - - add_path(rel, (Path *) pathnode); - } - } - } -} - -/* - * 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, since - * the executor will perform a scan for each subclause of the 'or'. - * Returns a list of IndexOptInfo nodes, one per scan. - * - * This routine also creates the indexqual list that will be needed by - * the executor. The indexqual list has one entry for each scan of the base - * rel, which is a sublist of indexqual conditions to apply in that scan. - * The implicit semantics are AND across each sublist of quals, and OR across - * the toplevel list (note that the executor takes care not to return any - * single tuple more than once). - * - * 'rel' is the node of the relation on which the indexes are defined - * 'subclauses' are the subclauses of the 'or' clause - * 'indices' is a list of sublists of the IndexOptInfo nodes that matched - * each subclause of the 'or' clause - * 'pathnode' is the IndexPath node being built. - * - * Results are returned by setting these fields of the passed pathnode: - * 'indexinfo' gets a list of the index IndexOptInfo nodes, one per scan - * 'indexqual' gets the constructed indexquals for the path (a list - * of sublists of clauses, one sublist per scan of the base rel) - * 'startup_cost' and 'total_cost' get the complete path costs. - * - * 'startup_cost' is the startup cost for the first index scan only; - * startup costs for later scans will be paid later on, so they just - * get reflected in total_cost. - * - * NOTE: we choose each scan on the basis of its total cost, ignoring startup - * cost. This is reasonable as long as all index types have zero or small - * startup cost, but we might have to work harder if any index types with - * nontrivial startup cost are ever invented. - */ -static void -best_or_subclause_indices(Query *root, - RelOptInfo *rel, - List *subclauses, - List *indices, - IndexPath *pathnode) -{ - List *slist; - - pathnode->indexinfo = NIL; - pathnode->indexqual = NIL; - pathnode->path.startup_cost = 0; - pathnode->path.total_cost = 0; - - foreach(slist, subclauses) - { - Expr *subclause = lfirst(slist); - IndexOptInfo *best_indexinfo; - List *best_indexqual; - Cost best_startup_cost; - Cost best_total_cost; - - best_or_subclause_index(root, rel, subclause, lfirst(indices), - &best_indexinfo, &best_indexqual, - &best_startup_cost, &best_total_cost); - - Assert(best_indexinfo != NULL); - - pathnode->indexinfo = lappend(pathnode->indexinfo, best_indexinfo); - pathnode->indexqual = lappend(pathnode->indexqual, best_indexqual); - if (slist == subclauses) /* first scan? */ - pathnode->path.startup_cost = best_startup_cost; - pathnode->path.total_cost += best_total_cost; - - indices = lnext(indices); - } -} - -/* - * 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 (considering total cost only, for now). - * - * 'rel' is the node of the relation on which the index is defined - * 'subclause' is the OR subclause being considered - * 'indices' is a list of IndexOptInfo nodes that match the subclause - * '*retIndexInfo' gets the IndexOptInfo of the best index - * '*retIndexQual' gets a list of the indexqual conditions for the best index - * '*retStartupCost' gets the startup cost of a scan with that index - * '*retTotalCost' gets the total cost of a scan with that index - */ -static void -best_or_subclause_index(Query *root, - RelOptInfo *rel, - Expr *subclause, - List *indices, - IndexOptInfo **retIndexInfo, /* return value */ - List **retIndexQual, /* return value */ - Cost *retStartupCost, /* return value */ - Cost *retTotalCost) /* return value */ -{ - bool first_time = true; - List *ilist; - - /* if we don't match anything, return zeros */ - *retIndexInfo = NULL; - *retIndexQual = NIL; - *retStartupCost = 0; - *retTotalCost = 0; - - foreach(ilist, indices) - { - IndexOptInfo *index = (IndexOptInfo *) lfirst(ilist); - List *indexqual; - Path subclause_path; - - Assert(IsA(index, IndexOptInfo)); - - /* Convert this 'or' subclause to an indexqual list */ - indexqual = extract_or_indexqual_conditions(rel, index, subclause); - - cost_index(&subclause_path, root, rel, index, indexqual, false); - - if (first_time || subclause_path.total_cost < *retTotalCost) - { - *retIndexInfo = index; - *retIndexQual = indexqual; - *retStartupCost = subclause_path.startup_cost; - *retTotalCost = subclause_path.total_cost; - first_time = false; - } - } -} |