1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-21 16:02:15 +03:00

Postgres95 1.01 Distribution - Virgin Sources

This commit is contained in:
Marc G. Fournier
1996-07-09 06:22:35 +00:00
commit d31084e9d1
868 changed files with 242656 additions and 0 deletions

View File

@ -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;
}