1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-09 06:21:09 +03:00

Massive commit to run PGINDENT on all *.c and *.h files.

This commit is contained in:
Bruce Momjian
1997-09-07 05:04:48 +00:00
parent 8fecd4febf
commit 1ccd423235
687 changed files with 150775 additions and 136888 deletions

View File

@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* clauseinfo.c--
* ClauseInfo node manipulation routines.
* ClauseInfo node manipulation routines.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/clauseinfo.c,v 1.3 1996/07/31 18:47:06 scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/clauseinfo.c,v 1.4 1997/09/07 04:44:17 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,167 +20,172 @@
#include "optimizer/clauses.h"
#include "optimizer/clauseinfo.h"
/*
/*
* valid-or-clause--
*
*
* Returns t iff the clauseinfo node contains a 'normal' 'or' clause.
*
*
*/
bool
valid_or_clause(CInfo *clauseinfo)
valid_or_clause(CInfo * clauseinfo)
{
if (clauseinfo != NULL &&
!single_node((Node*)clauseinfo->clause) &&
!clauseinfo->notclause &&
or_clause((Node*)clauseinfo->clause))
return(true);
else
return(false);
if (clauseinfo != NULL &&
!single_node((Node *) clauseinfo->clause) &&
!clauseinfo->notclause &&
or_clause((Node *) clauseinfo->clause))
return (true);
else
return (false);
}
/*
/*
* get-actual-clauses--
*
*
* Returns a list containing the clauses from 'clauseinfo-list'.
*
*
*/
List *
get_actual_clauses(List *clauseinfo_list)
List *
get_actual_clauses(List * clauseinfo_list)
{
List *temp = NIL;
List *result = NIL;
CInfo *clause = (CInfo *)NULL;
List *temp = NIL;
List *result = NIL;
CInfo *clause = (CInfo *) NULL;
foreach(temp,clauseinfo_list) {
clause = (CInfo *)lfirst(temp);
result = lappend(result,clause->clause);
}
return(result);
foreach(temp, clauseinfo_list)
{
clause = (CInfo *) lfirst(temp);
result = lappend(result, clause->clause);
}
return (result);
}
/*
/*
* XXX NOTE:
* The following routines must return their contents in the same order
* (e.g., the first clause's info should be first, and so on) or else
* get_index_sel() won't work.
*
* The following routines must return their contents in the same order
* (e.g., the first clause's info should be first, and so on) or else
* get_index_sel() won't work.
*
*/
/*
/*
* get_relattvals--
* For each member of a list of clauseinfo nodes to be used with an
* index, create a vectori-long specifying:
* the attnos,
* the values of the clause constants, and
* flags indicating the type and location of the constant within
* each clause.
* Each clause is of the form (op var some_type_of_constant), thus the
* flag indicating whether the constant is on the left or right should
* always be *SELEC-CONSTANT-RIGHT*.
*
* For each member of a list of clauseinfo nodes to be used with an
* index, create a vectori-long specifying:
* the attnos,
* the values of the clause constants, and
* flags indicating the type and location of the constant within
* each clause.
* Each clause is of the form (op var some_type_of_constant), thus the
* flag indicating whether the constant is on the left or right should
* always be *SELEC-CONSTANT-RIGHT*.
*
* 'clauseinfo-list' is a list of clauseinfo nodes
*
*
* Returns a list of vectori-longs.
*
*
*/
void
get_relattvals(List *clauseinfo_list,
List **attnos,
List **values,
List **flags)
get_relattvals(List * clauseinfo_list,
List ** attnos,
List ** values,
List ** flags)
{
List *result1 = NIL;
List *result2 = NIL;
List *result3 = NIL;
CInfo *temp = (CInfo *)NULL;
List *i = NIL;
List *result1 = NIL;
List *result2 = NIL;
List *result3 = NIL;
CInfo *temp = (CInfo *) NULL;
List *i = NIL;
foreach (i,clauseinfo_list) {
int dummy;
AttrNumber attno;
Datum constval;
int flag;
foreach(i, clauseinfo_list)
{
int dummy;
AttrNumber attno;
Datum constval;
int flag;
temp = (CInfo *)lfirst(i);
get_relattval((Node*)temp->clause, &dummy, &attno, &constval, &flag);
result1 = lappendi(result1, (int)attno);
result2 = lappendi(result2, constval);
result3 = lappendi(result3, flag);
}
temp = (CInfo *) lfirst(i);
get_relattval((Node *) temp->clause, &dummy, &attno, &constval, &flag);
result1 = lappendi(result1, (int) attno);
result2 = lappendi(result2, constval);
result3 = lappendi(result3, flag);
}
*attnos = result1;
*values = result2;
*flags = result3;
return;
*attnos = result1;
*values = result2;
*flags = result3;
return;
}
/*
/*
* get_joinvars --
* Given a list of join clauseinfo nodes to be used with the index
* of an inner join relation, return three lists consisting of:
* the attributes corresponding to the inner join relation
* the value of the inner var clause (always "")
* whether the attribute appears on the left or right side of
* the operator.
*
* Given a list of join clauseinfo nodes to be used with the index
* of an inner join relation, return three lists consisting of:
* the attributes corresponding to the inner join relation
* the value of the inner var clause (always "")
* whether the attribute appears on the left or right side of
* the operator.
*
* 'relid' is the inner join relation
* 'clauseinfo-list' is a list of qualification clauses to be used with
* 'rel'
*
* 'rel'
*
*/
void
get_joinvars(Oid relid,
List *clauseinfo_list,
List **attnos,
List **values,
List **flags)
List * clauseinfo_list,
List ** attnos,
List ** values,
List ** flags)
{
List *result1 = NIL;
List *result2 = NIL;
List *result3 = NIL;
List *temp;
foreach(temp, clauseinfo_list) {
CInfo *clauseinfo = lfirst(temp);
Expr *clause = clauseinfo->clause;
List *result1 = NIL;
List *result2 = NIL;
List *result3 = NIL;
List *temp;
if( IsA (get_leftop(clause),Var) &&
(relid == (get_leftop(clause))->varno)) {
result1 = lappendi(result1, (int4)(get_leftop(clause))->varattno);
result2 = lappend(result2, "");
result3 = lappendi(result3, _SELEC_CONSTANT_RIGHT_);
} else {
result1 = lappendi(result1, (int4)(get_rightop(clause))->varattno);
result2 = lappend(result2, "");
result3 = lappendi(result3, _SELEC_CONSTANT_LEFT_);
foreach(temp, clauseinfo_list)
{
CInfo *clauseinfo = lfirst(temp);
Expr *clause = clauseinfo->clause;
if (IsA(get_leftop(clause), Var) &&
(relid == (get_leftop(clause))->varno))
{
result1 = lappendi(result1, (int4) (get_leftop(clause))->varattno);
result2 = lappend(result2, "");
result3 = lappendi(result3, _SELEC_CONSTANT_RIGHT_);
}
else
{
result1 = lappendi(result1, (int4) (get_rightop(clause))->varattno);
result2 = lappend(result2, "");
result3 = lappendi(result3, _SELEC_CONSTANT_LEFT_);
}
}
}
*attnos = result1;
*values = result2;
*flags = result3;
return;
*attnos = result1;
*values = result2;
*flags = result3;
return;
}
/*
/*
* get_opnos--
* Create and return a list containing the clause operators of each member
* of a list of clauseinfo nodes to be used with an index.
*
* Create and return a list containing the clause operators of each member
* of a list of clauseinfo nodes to be used with an index.
*
*/
List *
get_opnos(List *clauseinfo_list)
List *
get_opnos(List * clauseinfo_list)
{
CInfo *temp = (CInfo *)NULL;
List *result = NIL;
List *i = NIL;
CInfo *temp = (CInfo *) NULL;
List *result = NIL;
List *i = NIL;
foreach(i,clauseinfo_list) {
temp = (CInfo *)lfirst(i);
result =
lappendi(result,
(((Oper*)temp->clause->oper)->opno));
}
return(result);
foreach(i, clauseinfo_list)
{
temp = (CInfo *) lfirst(i);
result =
lappendi(result,
(((Oper *) temp->clause->oper)->opno));
}
return (result);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* indexnode.c--
* Routines to find all indices on a relation
* Routines to find all indices on a relation
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/indexnode.c,v 1.2 1996/10/31 10:59:37 scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/indexnode.c,v 1.3 1997/09/07 04:44:22 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,74 +21,77 @@
#include "optimizer/internal.h"
#include "optimizer/plancat.h"
#include "optimizer/pathnode.h" /* where the decls go */
#include "optimizer/pathnode.h" /* where the decls go */
static List *find_secondary_index(Query *root, Oid relid);
static List *find_secondary_index(Query * root, Oid relid);
/*
/*
* find-relation-indices--
* Returns a list of index nodes containing appropriate information for
* each (secondary) index defined on a relation.
*
* Returns a list of index nodes containing appropriate information for
* each (secondary) index defined on a relation.
*
*/
List *
find_relation_indices(Query *root, Rel *rel)
List *
find_relation_indices(Query * root, Rel * rel)
{
if (rel->indexed) {
return (find_secondary_index(root, lfirsti(rel->relids)));
} else {
return (NIL);
}
if (rel->indexed)
{
return (find_secondary_index(root, lfirsti(rel->relids)));
}
else
{
return (NIL);
}
}
/*
/*
* find-secondary-index--
* Creates a list of index path nodes containing information for each
* secondary index defined on a relation by searching through the index
* catalog.
*
* Creates a list of index path nodes containing information for each
* secondary index defined on a relation by searching through the index
* catalog.
*
* 'relid' is the OID of the relation for which indices are being located
*
*
* Returns a list of new index nodes.
*
*
*/
static List *
find_secondary_index(Query *root, Oid relid)
static List *
find_secondary_index(Query * root, Oid relid)
{
IdxInfoRetval indexinfo;
List *indexes = NIL;
bool first = TRUE;
IdxInfoRetval indexinfo;
List *indexes = NIL;
bool first = TRUE;
while (index_info(root, first, relid,&indexinfo)) {
Rel *indexnode = makeNode(Rel);
while (index_info(root, first, relid, &indexinfo))
{
Rel *indexnode = makeNode(Rel);
indexnode->relids = lconsi(indexinfo.relid,NIL);
indexnode->relam = indexinfo.relam;
indexnode->pages = indexinfo.pages;
indexnode->tuples = indexinfo.tuples;
indexnode->indexkeys = indexinfo.indexkeys;
indexnode->ordering = indexinfo.orderOprs;
indexnode->classlist = indexinfo.classlist;
indexnode->indproc= indexinfo.indproc;
indexnode->indpred = (List*)indexinfo.indpred;
indexnode->indexed= false; /* not indexed itself */
indexnode->size = 0;
indexnode->width= 0;
indexnode->targetlist= NIL;
indexnode->pathlist= NIL;
indexnode->unorderedpath= NULL;
indexnode->cheapestpath= NULL;
indexnode->pruneable= true;
indexnode->clauseinfo= NIL;
indexnode->joininfo= NIL;
indexnode->innerjoin= NIL;
indexnode->relids = lconsi(indexinfo.relid, NIL);
indexnode->relam = indexinfo.relam;
indexnode->pages = indexinfo.pages;
indexnode->tuples = indexinfo.tuples;
indexnode->indexkeys = indexinfo.indexkeys;
indexnode->ordering = indexinfo.orderOprs;
indexnode->classlist = indexinfo.classlist;
indexnode->indproc = indexinfo.indproc;
indexnode->indpred = (List *) indexinfo.indpred;
indexes = lcons(indexnode, indexes);
first = FALSE;
}
indexnode->indexed = false; /* not indexed itself */
indexnode->size = 0;
indexnode->width = 0;
indexnode->targetlist = NIL;
indexnode->pathlist = NIL;
indexnode->unorderedpath = NULL;
indexnode->cheapestpath = NULL;
indexnode->pruneable = true;
indexnode->clauseinfo = NIL;
indexnode->joininfo = NIL;
indexnode->innerjoin = NIL;
return indexes;
indexes = lcons(indexnode, indexes);
first = FALSE;
}
return indexes;
}

View File

@@ -1,24 +1,24 @@
/*-------------------------------------------------------------------------
*
* internal.c--
* Definitions required throughout the query optimizer.
* Definitions required throughout the query optimizer.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/internal.c,v 1.3 1997/08/20 14:53:37 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/internal.c,v 1.4 1997/09/07 04:44:24 momjian Exp $
*
*-------------------------------------------------------------------------
*/
/*
* ---------- SHARED MACROS
*
* Macros common to modules for creating, accessing, and modifying
* query tree and query plan components.
* Shared with the executor.
*
/*
* ---------- SHARED MACROS
*
* Macros common to modules for creating, accessing, and modifying
* query tree and query plan components.
* Shared with the executor.
*
*/
#include <sys/types.h>
@@ -31,32 +31,30 @@
#include "nodes/primnodes.h"
#include "utils/palloc.h"
#ifdef NOT_USED
#ifdef NOT_USED
/*****************************************************************************
*
*****************************************************************************/
/* the following should probably be moved elsewhere -ay */
TargetEntry *
MakeTLE(Resdom *resdom, Node *expr)
TargetEntry *
MakeTLE(Resdom * resdom, Node * expr)
{
TargetEntry *rt = makeNode(TargetEntry);
rt->resdom = resdom;
rt->expr = expr;
return rt;
TargetEntry *rt = makeNode(TargetEntry);
rt->resdom = resdom;
rt->expr = expr;
return rt;
}
Var *
get_expr(TargetEntry *tle)
Var *
get_expr(TargetEntry * tle)
{
Assert(tle!=NULL);
Assert(tle->expr!=NULL);
Assert(tle != NULL);
Assert(tle->expr != NULL);
return ((Var *)tle->expr);
return ((Var *) tle->expr);
}
#endif /* 0 */
#endif /* 0 */

View File

@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* joininfo.c--
* JoinInfo node manipulation routines
* JoinInfo node manipulation routines
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/joininfo.c,v 1.2 1996/11/10 03:01:00 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/joininfo.c,v 1.3 1997/09/07 04:44:27 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,88 +21,96 @@
#include "optimizer/clauses.h"
/*
/*
* joininfo-member--
* Determines whether a node has already been created for a join
* between a set of join relations and the relation described by
* 'joininfo-list'.
*
* Determines whether a node has already been created for a join
* between a set of join relations and the relation described by
* 'joininfo-list'.
*
* 'join-relids' is a list of relids corresponding to the join relation
* 'joininfo-list' is the list of joininfo nodes against which this is
* checked
*
* 'joininfo-list' is the list of joininfo nodes against which this is
* checked
*
* Returns the corresponding node in 'joininfo-list' if such a node
* exists.
*
*
*/
JInfo *
joininfo_member(List *join_relids, List *joininfo_list)
JInfo *
joininfo_member(List * join_relids, List * joininfo_list)
{
List *i = NIL;
List *other_rels = NIL;
List *i = NIL;
List *other_rels = NIL;
foreach(i,joininfo_list) {
other_rels = lfirst(i);
if(same(join_relids, ((JInfo*)other_rels)->otherrels))
return((JInfo*)other_rels);
}
return((JInfo*)NULL);
foreach(i, joininfo_list)
{
other_rels = lfirst(i);
if (same(join_relids, ((JInfo *) other_rels)->otherrels))
return ((JInfo *) other_rels);
}
return ((JInfo *) NULL);
}
/*
/*
* find-joininfo-node--
* Find the joininfo node within a relation entry corresponding
* to a join between 'this_rel' and the relations in 'join-relids'. A
* new node is created and added to the relation entry's joininfo
* field if the desired one can't be found.
*
* Find the joininfo node within a relation entry corresponding
* to a join between 'this_rel' and the relations in 'join-relids'. A
* new node is created and added to the relation entry's joininfo
* field if the desired one can't be found.
*
* Returns a joininfo node.
*
*
*/
JInfo *
find_joininfo_node(Rel *this_rel, List *join_relids)
JInfo *
find_joininfo_node(Rel * this_rel, List * join_relids)
{
JInfo *joininfo = joininfo_member(join_relids,
this_rel->joininfo);
if( joininfo == NULL ) {
joininfo = makeNode(JInfo);
joininfo->otherrels = join_relids;
joininfo->jinfoclauseinfo = NIL;
joininfo->mergesortable = false;
joininfo->hashjoinable = false;
joininfo->inactive = false;
this_rel->joininfo = lcons(joininfo, this_rel->joininfo);
}
return(joininfo);
JInfo *joininfo = joininfo_member(join_relids,
this_rel->joininfo);
if (joininfo == NULL)
{
joininfo = makeNode(JInfo);
joininfo->otherrels = join_relids;
joininfo->jinfoclauseinfo = NIL;
joininfo->mergesortable = false;
joininfo->hashjoinable = false;
joininfo->inactive = false;
this_rel->joininfo = lcons(joininfo, this_rel->joininfo);
}
return (joininfo);
}
/*
/*
* other-join-clause-var--
* Determines whether a var node is contained within a joinclause
* of the form(op var var).
*
* Determines whether a var node is contained within a joinclause
* of the form(op var var).
*
* Returns the other var node in the joinclause if it is, nil if not.
*
*
*/
Var *
other_join_clause_var(Var *var, Expr *clause)
Var *
other_join_clause_var(Var * var, Expr * clause)
{
Var *retval;
Var *l, *r;
Var *retval;
Var *l,
*r;
retval = (Var*) NULL;
retval = (Var *) NULL;
if( var != NULL && join_clause_p((Node*)clause)) {
l = (Var *) get_leftop(clause);
r = (Var *) get_rightop(clause);
if (var != NULL && join_clause_p((Node *) clause))
{
l = (Var *) get_leftop(clause);
r = (Var *) get_rightop(clause);
if(var_equal(var, l)) {
retval = r;
} else if(var_equal(var, r)) {
retval = l;
}
}
if (var_equal(var, l))
{
retval = r;
}
else if (var_equal(var, r))
{
retval = l;
}
}
return(retval);
return (retval);
}

View File

@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* keys.c--
* Key manipulation routines
* Key manipulation routines
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/keys.c,v 1.2 1997/08/19 21:32:03 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/keys.c,v 1.3 1997/09/07 04:44:28 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -22,173 +22,180 @@
#include "optimizer/tlist.h"
static Expr *matching2_tlvar(int var, List *tlist, bool (*test)());
static bool equal_indexkey_var(int index_key, Var *var);
static Expr *matching2_tlvar(int var, List * tlist, bool(*test) ());
static bool equal_indexkey_var(int index_key, Var * var);
/*
/*
* 1. index key
* one of:
* attnum
* (attnum arrayindex)
* one of:
* attnum
* (attnum arrayindex)
* 2. path key
* (subkey1 ... subkeyN)
* where subkeyI is a var node
* note that the 'Keys field is a list of these
* (subkey1 ... subkeyN)
* where subkeyI is a var node
* note that the 'Keys field is a list of these
* 3. join key
* (outer-subkey inner-subkey)
* where each subkey is a var node
* (outer-subkey inner-subkey)
* where each subkey is a var node
* 4. sort key
* one of:
* SortKey node
* number
* nil
* (may also refer to the 'SortKey field of a SortKey node,
* which looks exactly like an index key)
*
* one of:
* SortKey node
* number
* nil
* (may also refer to the 'SortKey field of a SortKey node,
* which looks exactly like an index key)
*
*/
/*
/*
* match-indexkey-operand--
* Returns t iff an index key 'index-key' matches the given clause
* operand.
*
* Returns t iff an index key 'index-key' matches the given clause
* operand.
*
*/
bool
match_indexkey_operand(int indexkey, Var *operand, Rel *rel)
match_indexkey_operand(int indexkey, Var * operand, Rel * rel)
{
if (IsA (operand,Var) &&
(lfirsti(rel->relids) == operand->varno) &&
equal_indexkey_var(indexkey,operand))
return(true);
else
return(false);
if (IsA(operand, Var) &&
(lfirsti(rel->relids) == operand->varno) &&
equal_indexkey_var(indexkey, operand))
return (true);
else
return (false);
}
/*
/*
* equal_indexkey_var--
* Returns t iff an index key 'index-key' matches the corresponding
* fields of var node 'var'.
*
* Returns t iff an index key 'index-key' matches the corresponding
* fields of var node 'var'.
*
*/
static bool
equal_indexkey_var(int index_key, Var *var)
static bool
equal_indexkey_var(int index_key, Var * var)
{
if (index_key == var->varattno)
return(true);
else
return(false);
if (index_key == var->varattno)
return (true);
else
return (false);
}
/*
/*
* extract-subkey--
* Returns the subkey in a join key corresponding to the outer or inner
* lelation.
*
* Returns the subkey in a join key corresponding to the outer or inner
* lelation.
*
*/
Var *
extract_subkey(JoinKey *jk, int which_subkey)
Var *
extract_subkey(JoinKey * jk, int which_subkey)
{
Var *retval;
Var *retval;
switch (which_subkey) {
case OUTER:
retval = jk->outer;
break;
case INNER:
retval = jk->inner;
break;
default: /* do nothing */
elog(DEBUG,"extract_subkey with neither INNER or OUTER");
retval = NULL;
}
return(retval);
switch (which_subkey)
{
case OUTER:
retval = jk->outer;
break;
case INNER:
retval = jk->inner;
break;
default: /* do nothing */
elog(DEBUG, "extract_subkey with neither INNER or OUTER");
retval = NULL;
}
return (retval);
}
/*
/*
* samekeys--
* Returns t iff two sets of path keys are equivalent. They are
* equivalent if the first subkey (var node) within each sublist of
* list 'keys1' is contained within the corresponding sublist of 'keys2'.
*
* XXX It isn't necessary to check that each sublist exactly contain
* the same elements because if the routine that built these
* sublists together is correct, having one element in common
* implies having all elements in common.
*
* Returns t iff two sets of path keys are equivalent. They are
* equivalent if the first subkey (var node) within each sublist of
* list 'keys1' is contained within the corresponding sublist of 'keys2'.
*
* XXX It isn't necessary to check that each sublist exactly contain
* the same elements because if the routine that built these
* sublists together is correct, having one element in common
* implies having all elements in common.
*
*/
bool
samekeys(List *keys1, List *keys2)
samekeys(List * keys1, List * keys2)
{
bool allmember = true;
List *key1, *key2;
bool allmember = true;
List *key1,
*key2;
for(key1=keys1,key2=keys2 ; key1 != NIL && key2 !=NIL ;
key1=lnext(key1), key2=lnext(key2))
if (!member(lfirst(key1), lfirst(key2)))
allmember = false;
for (key1 = keys1, key2 = keys2; key1 != NIL && key2 != NIL;
key1 = lnext(key1), key2 = lnext(key2))
if (!member(lfirst(key1), lfirst(key2)))
allmember = false;
if ( (length (keys2) >= length (keys1)) && allmember)
return(true);
else
return(false);
if ((length(keys2) >= length(keys1)) && allmember)
return (true);
else
return (false);
}
/*
/*
* collect-index-pathkeys--
* Creates a list of subkeys by retrieving var nodes corresponding to
* each index key in 'index-keys' from the relation's target list
* 'tlist'. If the key is not in the target list, the key is irrelevant
* and is thrown away. The returned subkey list is of the form:
* ((var1) (var2) ... (varn))
*
* Creates a list of subkeys by retrieving var nodes corresponding to
* each index key in 'index-keys' from the relation's target list
* 'tlist'. If the key is not in the target list, the key is irrelevant
* and is thrown away. The returned subkey list is of the form:
* ((var1) (var2) ... (varn))
*
* 'index-keys' is a list of index keys
* 'tlist' is a relation target list
*
*
* Returns the list of cons'd subkeys.
*
*
*/
/* This function is identical to matching_tlvar and tlistentry_member.
* They should be merged.
*/
static Expr *
matching2_tlvar(int var, List *tlist, bool (*test)())
static Expr *
matching2_tlvar(int var, List * tlist, bool(*test) ())
{
TargetEntry *tlentry = NULL;
TargetEntry *tlentry = NULL;
if (var) {
List *temp;
foreach (temp,tlist) {
if ((*test)(var, get_expr(lfirst(temp)))) {
tlentry = lfirst(temp);
break;
}
if (var)
{
List *temp;
foreach(temp, tlist)
{
if ((*test) (var, get_expr(lfirst(temp))))
{
tlentry = lfirst(temp);
break;
}
}
}
}
if (tlentry)
return((Expr*)get_expr(tlentry));
else
return((Expr*)NULL);
if (tlentry)
return ((Expr *) get_expr(tlentry));
else
return ((Expr *) NULL);
}
List *
collect_index_pathkeys(int *index_keys, List *tlist)
List *
collect_index_pathkeys(int *index_keys, List * tlist)
{
List *retval = NIL;
List *retval = NIL;
Assert (index_keys != NULL);
Assert(index_keys != NULL);
while(index_keys[0] != 0) {
Expr *mvar;
mvar = matching2_tlvar(index_keys[0],
tlist,
equal_indexkey_var);
if (mvar)
retval = nconc(retval,lcons(lcons(mvar,NIL),
NIL));
index_keys++;
}
return(retval);
while (index_keys[0] != 0)
{
Expr *mvar;
mvar = matching2_tlvar(index_keys[0],
tlist,
equal_indexkey_var);
if (mvar)
retval = nconc(retval, lcons(lcons(mvar, NIL),
NIL));
index_keys++;
}
return (retval);
}

View File

@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* ordering.c--
* Routines to manipulate and compare merge and path orderings
* Routines to manipulate and compare merge and path orderings
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/ordering.c,v 1.3 1997/08/19 21:32:06 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/ordering.c,v 1.4 1997/09/07 04:44:30 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,81 +18,88 @@
#include "optimizer/internal.h"
#include "optimizer/ordering.h"
static bool equal_sortops_order(Oid *ordering1, Oid *ordering2);
static bool equal_sortops_order(Oid * ordering1, Oid * ordering2);
/*
/*
* equal-path-path-ordering--
* Returns t iff two path orderings are equal.
*
* Returns t iff two path orderings are equal.
*
*/
bool
equal_path_path_ordering(PathOrder *path_ordering1,
PathOrder *path_ordering2)
equal_path_path_ordering(PathOrder * path_ordering1,
PathOrder * path_ordering2)
{
if (path_ordering1 == path_ordering2)
return true;
if (path_ordering1 == path_ordering2)
return true;
if (!path_ordering1 || !path_ordering2)
return false;
if (!path_ordering1 || !path_ordering2)
return false;
if (path_ordering1->ordtype == MERGE_ORDER &&
path_ordering2->ordtype == MERGE_ORDER) {
if (path_ordering1->ordtype == MERGE_ORDER &&
path_ordering2->ordtype == MERGE_ORDER)
{
return equal(path_ordering1->ord.merge, path_ordering2->ord.merge);
return equal(path_ordering1->ord.merge, path_ordering2->ord.merge);
} else if (path_ordering1->ordtype == SORTOP_ORDER &&
path_ordering2->ordtype == SORTOP_ORDER) {
}
else if (path_ordering1->ordtype == SORTOP_ORDER &&
path_ordering2->ordtype == SORTOP_ORDER)
{
return
(equal_sortops_order(path_ordering1->ord.sortop,
path_ordering2->ord.sortop));
} else if (path_ordering1->ordtype == MERGE_ORDER &&
path_ordering2->ordtype == SORTOP_ORDER) {
return
(equal_sortops_order(path_ordering1->ord.sortop,
path_ordering2->ord.sortop));
}
else if (path_ordering1->ordtype == MERGE_ORDER &&
path_ordering2->ordtype == SORTOP_ORDER)
{
return (path_ordering2->ord.sortop &&
(path_ordering1->ord.merge->left_operator ==
path_ordering2->ord.sortop[0]));
} else {
return (path_ordering2->ord.sortop &&
(path_ordering1->ord.merge->left_operator ==
path_ordering2->ord.sortop[0]));
}
else
{
return (path_ordering1->ord.sortop &&
(path_ordering1->ord.sortop[0] ==
path_ordering2->ord.merge->left_operator));
}
return (path_ordering1->ord.sortop &&
(path_ordering1->ord.sortop[0] ==
path_ordering2->ord.merge->left_operator));
}
}
/*
/*
* equal-path-merge-ordering--
* Returns t iff a path ordering is usable for ordering a merge join.
* Returns t iff a path ordering is usable for ordering a merge join.
*
* XXX Presently, this means that the first sortop of the path matches
* either of the merge sortops. Is there a "right" and "wrong"
* sortop to match?
*
* either of the merge sortops. Is there a "right" and "wrong"
* sortop to match?
*
*/
bool
equal_path_merge_ordering(Oid *path_ordering,
MergeOrder *merge_ordering)
equal_path_merge_ordering(Oid * path_ordering,
MergeOrder * merge_ordering)
{
if (path_ordering == NULL || merge_ordering == NULL)
return(false);
if (path_ordering == NULL || merge_ordering == NULL)
return (false);
if (path_ordering[0] == merge_ordering->left_operator ||
path_ordering[0] == merge_ordering->right_operator)
return(true);
else
return(false);
if (path_ordering[0] == merge_ordering->left_operator ||
path_ordering[0] == merge_ordering->right_operator)
return (true);
else
return (false);
}
/*
/*
* equal-merge-merge-ordering--
* Returns t iff two merge orderings are equal.
*
* Returns t iff two merge orderings are equal.
*
*/
bool
equal_merge_merge_ordering(MergeOrder *merge_ordering1,
MergeOrder *merge_ordering2)
equal_merge_merge_ordering(MergeOrder * merge_ordering1,
MergeOrder * merge_ordering2)
{
return (equal(merge_ordering1, merge_ordering2));
return (equal(merge_ordering1, merge_ordering2));
}
/*****************************************************************************
@@ -101,21 +108,22 @@ equal_merge_merge_ordering(MergeOrder *merge_ordering1,
/*
* equal_sort_ops_order -
* Returns true iff the sort operators are in the same order.
* Returns true iff the sort operators are in the same order.
*/
static bool
equal_sortops_order(Oid *ordering1, Oid *ordering2)
static bool
equal_sortops_order(Oid * ordering1, Oid * ordering2)
{
int i = 0;
int i = 0;
if (ordering1 == NULL || ordering2 == NULL)
return (ordering1==ordering2);
while (ordering1[i]!=0 && ordering2[i]!=0) {
if (ordering1[i] != ordering2[i])
break;
i++;
}
if (ordering1 == NULL || ordering2 == NULL)
return (ordering1 == ordering2);
return (ordering1[i]==0 && ordering2[i]==0);
while (ordering1[i] != 0 && ordering2[i] != 0)
{
if (ordering1[i] != ordering2[i])
break;
i++;
}
return (ordering1[i] == 0 && ordering2[i] == 0);
}

View File

@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* pathnode.c--
* Routines to manipulate pathlists and create path nodes
* Routines to manipulate pathlists and create path nodes
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.3 1997/09/05 18:10:36 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.4 1997/09/07 04:44:30 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -27,418 +27,459 @@
#include "optimizer/xfunc.h"
#include "optimizer/ordering.h"
#include "parser/parsetree.h" /* for getrelid() */
#include "parser/parsetree.h" /* for getrelid() */
static Path *better_path(Path *new_path, List *unique_paths, bool *noOther);
static Path *better_path(Path * new_path, List * unique_paths, bool * noOther);
/*****************************************************************************
* MISC. PATH UTILITIES
* MISC. PATH UTILITIES
*****************************************************************************/
/*
/*
* path-is-cheaper--
* Returns t iff 'path1' is cheaper than 'path2'.
*
* Returns t iff 'path1' is cheaper than 'path2'.
*
*/
bool
path_is_cheaper(Path *path1, Path *path2)
path_is_cheaper(Path * path1, Path * path2)
{
Cost cost1 = path1->path_cost;
Cost cost2 = path2->path_cost;
Cost cost1 = path1->path_cost;
Cost cost2 = path2->path_cost;
return((bool)(cost1 < cost2));
return ((bool) (cost1 < cost2));
}
/*
/*
* set_cheapest--
* Finds the minimum cost path from among a relation's paths.
*
* Finds the minimum cost path from among a relation's paths.
*
* 'parent-rel' is the parent relation
* 'pathlist' is a list of path nodes corresponding to 'parent-rel'
*
* Returns and sets the relation entry field with the pathnode that
*
* Returns and sets the relation entry field with the pathnode that
* is minimum.
*
*
*/
Path *
set_cheapest(Rel *parent_rel, List *pathlist)
Path *
set_cheapest(Rel * parent_rel, List * pathlist)
{
List *p;
Path *cheapest_so_far;
List *p;
Path *cheapest_so_far;
Assert(pathlist!=NIL);
Assert(IsA(parent_rel,Rel));
Assert(pathlist != NIL);
Assert(IsA(parent_rel, Rel));
cheapest_so_far = (Path*)lfirst(pathlist);
cheapest_so_far = (Path *) lfirst(pathlist);
foreach (p, lnext(pathlist)) {
Path *path = (Path*)lfirst(p);
foreach(p, lnext(pathlist))
{
Path *path = (Path *) lfirst(p);
if (path_is_cheaper(path, cheapest_so_far)) {
cheapest_so_far = path;
if (path_is_cheaper(path, cheapest_so_far))
{
cheapest_so_far = path;
}
}
}
parent_rel->cheapestpath = cheapest_so_far;
parent_rel->cheapestpath = cheapest_so_far;
return(cheapest_so_far);
return (cheapest_so_far);
}
/*
/*
* add_pathlist--
* For each path in the list 'new-paths', add to the list 'unique-paths'
* only those paths that are unique (i.e., unique ordering and ordering
* keys). Should a conflict arise, the more expensive path is thrown out,
* thereby pruning the plan space. But we don't prune if xfunc
* told us not to.
*
* For each path in the list 'new-paths', add to the list 'unique-paths'
* only those paths that are unique (i.e., unique ordering and ordering
* keys). Should a conflict arise, the more expensive path is thrown out,
* thereby pruning the plan space. But we don't prune if xfunc
* told us not to.
*
* 'parent-rel' is the relation entry to which these paths correspond.
*
*
* Returns the list of unique pathnodes.
*
*
*/
List *
add_pathlist(Rel *parent_rel, List *unique_paths, List *new_paths)
List *
add_pathlist(Rel * parent_rel, List * unique_paths, List * new_paths)
{
List *x;
Path *new_path;
Path *old_path;
bool noOther;
List *x;
Path *new_path;
Path *old_path;
bool noOther;
foreach (x, new_paths) {
new_path = (Path*)lfirst(x);
if (member(new_path, unique_paths))
continue;
old_path = better_path(new_path,unique_paths,&noOther);
foreach(x, new_paths)
{
new_path = (Path *) lfirst(x);
if (member(new_path, unique_paths))
continue;
old_path = better_path(new_path, unique_paths, &noOther);
if (noOther) {
/* Is a brand new path. */
new_path->parent = parent_rel;
unique_paths = lcons(new_path, unique_paths);
} else if (old_path==NULL) {
; /* do nothing if path is not cheaper */
} else if (old_path != NULL) { /* (IsA(old_path,Path)) { */
new_path->parent = parent_rel;
if (!parent_rel->pruneable) {
unique_paths = lcons(new_path, unique_paths);
}else
unique_paths = lcons(new_path,
LispRemove(old_path,unique_paths));
if (noOther)
{
/* Is a brand new path. */
new_path->parent = parent_rel;
unique_paths = lcons(new_path, unique_paths);
}
else if (old_path == NULL)
{
; /* do nothing if path is not cheaper */
}
else if (old_path != NULL)
{ /* (IsA(old_path,Path)) { */
new_path->parent = parent_rel;
if (!parent_rel->pruneable)
{
unique_paths = lcons(new_path, unique_paths);
}
else
unique_paths = lcons(new_path,
LispRemove(old_path, unique_paths));
}
}
}
return(unique_paths);
return (unique_paths);
}
/*
/*
* better_path--
* Determines whether 'new-path' has the same ordering and keys as some
* path in the list 'unique-paths'. If there is a redundant path,
* eliminate the more expensive path.
*
* Determines whether 'new-path' has the same ordering and keys as some
* path in the list 'unique-paths'. If there is a redundant path,
* eliminate the more expensive path.
*
* Returns:
* The old path - if 'new-path' matches some path in 'unique-paths' and is
* cheaper
* nil - if 'new-path' matches but isn't cheaper
* t - if there is no path in the list with the same ordering and keys
*
* The old path - if 'new-path' matches some path in 'unique-paths' and is
* cheaper
* nil - if 'new-path' matches but isn't cheaper
* t - if there is no path in the list with the same ordering and keys
*
*/
static Path *
better_path(Path *new_path, List *unique_paths, bool *noOther)
static Path *
better_path(Path * new_path, List * unique_paths, bool * noOther)
{
Path *old_path = (Path*)NULL;
Path *path = (Path*)NULL;
List *temp = NIL;
Path *retval = NULL;
Path *old_path = (Path *) NULL;
Path *path = (Path *) NULL;
List *temp = NIL;
Path *retval = NULL;
/* XXX - added the following two lines which weren't int
* the lisp planner, but otherwise, doesn't seem to work
* for the case where new_path is 'nil
*/
foreach (temp,unique_paths) {
path = (Path*) lfirst(temp);
/*
* XXX - added the following two lines which weren't int the lisp
* planner, but otherwise, doesn't seem to work for the case where
* new_path is 'nil
*/
foreach(temp, unique_paths)
{
path = (Path *) lfirst(temp);
if ((equal_path_path_ordering(&new_path->p_ordering,
&path->p_ordering) &&
samekeys(new_path->keys, path->keys))) {
old_path = path;
break;
if ((equal_path_path_ordering(&new_path->p_ordering,
&path->p_ordering) &&
samekeys(new_path->keys, path->keys)))
{
old_path = path;
break;
}
}
}
if (old_path==NULL) {
*noOther = true;
} else {
*noOther = false;
if (path_is_cheaper(new_path,old_path)) {
retval = old_path;
if (old_path == NULL)
{
*noOther = true;
}
}
return(retval);
else
{
*noOther = false;
if (path_is_cheaper(new_path, old_path))
{
retval = old_path;
}
}
return (retval);
}
/*****************************************************************************
* PATH NODE CREATION ROUTINES
* PATH NODE CREATION ROUTINES
*****************************************************************************/
/*
/*
* create_seqscan_path--
* Creates a path corresponding to a sequential scan, returning the
* pathnode.
*
* Creates a path corresponding to a sequential scan, returning the
* pathnode.
*
*/
Path *
create_seqscan_path(Rel *rel)
Path *
create_seqscan_path(Rel * rel)
{
int relid=0;
int relid = 0;
Path *pathnode = makeNode(Path);
Path *pathnode = makeNode(Path);
pathnode->pathtype = T_SeqScan;
pathnode->parent = rel;
pathnode->path_cost = 0.0;
pathnode->p_ordering.ordtype = SORTOP_ORDER;
pathnode->p_ordering.ord.sortop = NULL;
pathnode->keys = NIL;
/* copy clauseinfo list into path for expensive function processing
* -- JMH, 7/7/92
*/
pathnode->locclauseinfo=
(List*)copyObject((Node*)rel->clauseinfo);
pathnode->pathtype = T_SeqScan;
pathnode->parent = rel;
pathnode->path_cost = 0.0;
pathnode->p_ordering.ordtype = SORTOP_ORDER;
pathnode->p_ordering.ord.sortop = NULL;
pathnode->keys = NIL;
if (rel->relids !=NULL)
relid = lfirsti(rel->relids);
/*
* copy clauseinfo list into path for expensive function processing --
* JMH, 7/7/92
*/
pathnode->locclauseinfo =
(List *) copyObject((Node *) rel->clauseinfo);
pathnode->path_cost = cost_seqscan (relid,
rel->pages, rel->tuples);
/* add in expensive functions cost! -- JMH, 7/7/92 */
if (rel->relids != NULL)
relid = lfirsti(rel->relids);
pathnode->path_cost = cost_seqscan(relid,
rel->pages, rel->tuples);
/* add in expensive functions cost! -- JMH, 7/7/92 */
#if 0
if (XfuncMode != XFUNC_OFF) {
pathnode->path_cost +=
xfunc_get_path_cost(pathnode);
}
if (XfuncMode != XFUNC_OFF)
{
pathnode->path_cost +=
xfunc_get_path_cost(pathnode);
}
#endif
return (pathnode);
return (pathnode);
}
/*
/*
* create_index_path--
* Creates a single path node for an index scan.
*
* Creates a single path node for an index scan.
*
* 'rel' is the parent rel
* 'index' is the pathnode for the index on 'rel'
* 'restriction-clauses' is a list of restriction clause nodes.
* 'is-join-scan' is a flag indicating whether or not the index is being
* considered because of its sort order.
*
* considered because of its sort order.
*
* Returns the new path node.
*
*
*/
IndexPath *
create_index_path(Query *root,
Rel *rel,
Rel *index,
List *restriction_clauses,
bool is_join_scan)
IndexPath *
create_index_path(Query * root,
Rel * rel,
Rel * index,
List * restriction_clauses,
bool is_join_scan)
{
IndexPath *pathnode = makeNode(IndexPath);
pathnode->path.pathtype = T_IndexScan;
pathnode->path.parent = rel;
pathnode->path.p_ordering.ordtype = SORTOP_ORDER;
pathnode->path.p_ordering.ord.sortop = index->ordering;
IndexPath *pathnode = makeNode(IndexPath);
pathnode->indexid = index->relids;
pathnode->indexkeys = index->indexkeys;
pathnode->indexqual = NIL;
pathnode->path.pathtype = T_IndexScan;
pathnode->path.parent = rel;
pathnode->path.p_ordering.ordtype = SORTOP_ORDER;
pathnode->path.p_ordering.ord.sortop = index->ordering;
/* copy clauseinfo list into path for expensive function processing
* -- JMH, 7/7/92
*/
pathnode->path.locclauseinfo =
set_difference((List*) copyObject((Node*)rel->clauseinfo),
(List*) restriction_clauses);
pathnode->indexid = index->relids;
pathnode->indexkeys = index->indexkeys;
pathnode->indexqual = NIL;
/*
* The index must have an ordering for the path to have (ordering) keys,
* and vice versa.
*/
if (pathnode->path.p_ordering.ord.sortop) {
pathnode->path.keys = collect_index_pathkeys(index->indexkeys,
rel->targetlist);
/*
* Check that the keys haven't 'disappeared', since they may
* no longer be in the target list (i.e., index keys that are not
* relevant to the scan are not applied to the scan path node,
* so if no index keys were found, we can't order the path).
* copy clauseinfo list into path for expensive function processing --
* JMH, 7/7/92
*/
if (pathnode->path.keys==NULL) {
pathnode->path.p_ordering.ord.sortop = NULL;
pathnode->path.locclauseinfo =
set_difference((List *) copyObject((Node *) rel->clauseinfo),
(List *) restriction_clauses);
/*
* The index must have an ordering for the path to have (ordering)
* keys, and vice versa.
*/
if (pathnode->path.p_ordering.ord.sortop)
{
pathnode->path.keys = collect_index_pathkeys(index->indexkeys,
rel->targetlist);
/*
* Check that the keys haven't 'disappeared', since they may no
* longer be in the target list (i.e., index keys that are not
* relevant to the scan are not applied to the scan path node, so
* if no index keys were found, we can't order the path).
*/
if (pathnode->path.keys == NULL)
{
pathnode->path.p_ordering.ord.sortop = NULL;
}
}
else
{
pathnode->path.keys = NULL;
}
} else {
pathnode->path.keys = NULL;
}
if (is_join_scan || restriction_clauses==NULL) {
/*
* Indices used for joins or sorting result nodes don't
* restrict the result at all, they simply order it,
* so compute the scan cost
* accordingly -- use a selectivity of 1.0.
*/
/* is the statement above really true? what about IndexScan as the
if (is_join_scan || restriction_clauses == NULL)
{
/*
* Indices used for joins or sorting result nodes don't restrict
* the result at all, they simply order it, so compute the scan
* cost accordingly -- use a selectivity of 1.0.
*/
/* is the statement above really true? what about IndexScan as the
inner of a join? */
pathnode->path.path_cost =
cost_index (lfirsti(index->relids),
index->pages,
1.0,
rel->pages,
rel->tuples,
index->pages,
index->tuples,
false);
/* add in expensive functions cost! -- JMH, 7/7/92 */
pathnode->path.path_cost =
cost_index(lfirsti(index->relids),
index->pages,
1.0,
rel->pages,
rel->tuples,
index->pages,
index->tuples,
false);
/* add in expensive functions cost! -- JMH, 7/7/92 */
#if 0
if (XfuncMode != XFUNC_OFF) {
pathnode->path_cost =
(pathnode->path_cost +
xfunc_get_path_cost((Path*)pathnode));
}
if (XfuncMode != XFUNC_OFF)
{
pathnode->path_cost =
(pathnode->path_cost +
xfunc_get_path_cost((Path *) pathnode));
}
#endif
} else {
/*
* Compute scan cost for the case when 'index' is used with a
* restriction clause.
*/
List *attnos;
List *values;
List *flags;
float npages;
float selec;
Cost clausesel;
}
else
{
get_relattvals(restriction_clauses,
&attnos,
&values,
&flags);
index_selectivity(lfirsti(index->relids),
index->classlist,
get_opnos(restriction_clauses),
getrelid(lfirsti(rel->relids),
root->rtable),
attnos,
values,
flags,
length(restriction_clauses),
&npages,
&selec);
/* each clause gets an equal selectivity */
clausesel =
pow(selec,
1.0 / (double) length(restriction_clauses));
pathnode->indexqual = restriction_clauses;
pathnode->path.path_cost =
cost_index (lfirsti(index->relids),
(int)npages,
selec,
rel->pages,
rel->tuples,
index->pages,
index->tuples,
false);
/*
* Compute scan cost for the case when 'index' is used with a
* restriction clause.
*/
List *attnos;
List *values;
List *flags;
float npages;
float selec;
Cost clausesel;
get_relattvals(restriction_clauses,
&attnos,
&values,
&flags);
index_selectivity(lfirsti(index->relids),
index->classlist,
get_opnos(restriction_clauses),
getrelid(lfirsti(rel->relids),
root->rtable),
attnos,
values,
flags,
length(restriction_clauses),
&npages,
&selec);
/* each clause gets an equal selectivity */
clausesel =
pow(selec,
1.0 / (double) length(restriction_clauses));
pathnode->indexqual = restriction_clauses;
pathnode->path.path_cost =
cost_index(lfirsti(index->relids),
(int) npages,
selec,
rel->pages,
rel->tuples,
index->pages,
index->tuples,
false);
#if 0
/* add in expensive functions cost! -- JMH, 7/7/92 */
if (XfuncMode != XFUNC_OFF) {
pathnode->path_cost +=
xfunc_get_path_cost((Path*)pathnode);
}
/* add in expensive functions cost! -- JMH, 7/7/92 */
if (XfuncMode != XFUNC_OFF)
{
pathnode->path_cost +=
xfunc_get_path_cost((Path *) pathnode);
}
#endif
/* Set selectivities of clauses used with index to the selectivity
* of this index, subdividing the selectivity equally over each of
* the clauses.
*/
/* XXX Can this divide the selectivities in a better way? */
set_clause_selectivities(restriction_clauses, clausesel);
}
return(pathnode);
/*
* Set selectivities of clauses used with index to the selectivity
* of this index, subdividing the selectivity equally over each of
* the clauses.
*/
/* XXX Can this divide the selectivities in a better way? */
set_clause_selectivities(restriction_clauses, clausesel);
}
return (pathnode);
}
/*
/*
* create_nestloop_path--
* Creates a pathnode corresponding to a nestloop join between two
* relations.
*
* Creates a pathnode corresponding to a nestloop join between two
* relations.
*
* 'joinrel' is the join relation.
* 'outer_rel' is the outer join relation
* 'outer_path' is the outer join path.
* 'inner_path' is the inner join path.
* 'keys' are the keys of the path
*
*
* Returns the resulting path node.
*
*
*/
JoinPath *
create_nestloop_path(Rel *joinrel,
Rel *outer_rel,
Path *outer_path,
Path *inner_path,
List *keys)
JoinPath *
create_nestloop_path(Rel * joinrel,
Rel * outer_rel,
Path * outer_path,
Path * inner_path,
List * keys)
{
JoinPath *pathnode = makeNode(JoinPath);
pathnode->path.pathtype = T_NestLoop;
pathnode->path.parent = joinrel;
pathnode->outerjoinpath = outer_path;
pathnode->innerjoinpath = inner_path;
pathnode->pathclauseinfo = joinrel->clauseinfo;
pathnode->path.keys = keys;
pathnode->path.joinid = NIL;
pathnode->path.outerjoincost = (Cost)0.0;
pathnode->path.locclauseinfo = NIL;
JoinPath *pathnode = makeNode(JoinPath);
if (keys) {
pathnode->path.p_ordering.ordtype =
outer_path->p_ordering.ordtype;
if (outer_path->p_ordering.ordtype == SORTOP_ORDER) {
pathnode->path.p_ordering.ord.sortop =
outer_path->p_ordering.ord.sortop;
} else {
pathnode->path.p_ordering.ord.merge =
outer_path->p_ordering.ord.merge;
pathnode->path.pathtype = T_NestLoop;
pathnode->path.parent = joinrel;
pathnode->outerjoinpath = outer_path;
pathnode->innerjoinpath = inner_path;
pathnode->pathclauseinfo = joinrel->clauseinfo;
pathnode->path.keys = keys;
pathnode->path.joinid = NIL;
pathnode->path.outerjoincost = (Cost) 0.0;
pathnode->path.locclauseinfo = NIL;
if (keys)
{
pathnode->path.p_ordering.ordtype =
outer_path->p_ordering.ordtype;
if (outer_path->p_ordering.ordtype == SORTOP_ORDER)
{
pathnode->path.p_ordering.ord.sortop =
outer_path->p_ordering.ord.sortop;
}
else
{
pathnode->path.p_ordering.ord.merge =
outer_path->p_ordering.ord.merge;
}
}
else
{
pathnode->path.p_ordering.ordtype = SORTOP_ORDER;
pathnode->path.p_ordering.ord.sortop = NULL;
}
} else {
pathnode->path.p_ordering.ordtype = SORTOP_ORDER;
pathnode->path.p_ordering.ord.sortop = NULL;
}
pathnode->path.path_cost =
cost_nestloop(outer_path->path_cost,
inner_path->path_cost,
outer_rel->size,
inner_path->parent->size,
page_size(outer_rel->size,
outer_rel->width),
IsA(inner_path,IndexPath));
/* add in expensive function costs -- JMH 7/7/92 */
pathnode->path.path_cost =
cost_nestloop(outer_path->path_cost,
inner_path->path_cost,
outer_rel->size,
inner_path->parent->size,
page_size(outer_rel->size,
outer_rel->width),
IsA(inner_path, IndexPath));
/* add in expensive function costs -- JMH 7/7/92 */
#if 0
if (XfuncMode != XFUNC_OFF) {
pathnode->path_cost += xfunc_get_path_cost((Path*)pathnode);
}
if (XfuncMode != XFUNC_OFF)
{
pathnode->path_cost += xfunc_get_path_cost((Path *) pathnode);
}
#endif
return(pathnode);
return (pathnode);
}
/*
/*
* create_mergesort_path--
* Creates a pathnode corresponding to a mergesort join between
* two relations
*
* Creates a pathnode corresponding to a mergesort join between
* two relations
*
* 'joinrel' is the join relation
* 'outersize' is the number of tuples in the outer relation
* 'innersize' is the number of tuples in the inner relation
@@ -451,59 +492,60 @@ create_nestloop_path(Rel *joinrel,
* 'mergeclauses' are the applicable join/restriction clauses
* 'outersortkeys' are the sort varkeys for the outer relation
* 'innersortkeys' are the sort varkeys for the inner relation
*
*
*/
MergePath *
create_mergesort_path(Rel *joinrel,
int outersize,
int innersize,
int outerwidth,
int innerwidth,
Path *outer_path,
Path *inner_path,
List *keys,
MergeOrder *order,
List *mergeclauses,
List *outersortkeys,
List *innersortkeys)
MergePath *
create_mergesort_path(Rel * joinrel,
int outersize,
int innersize,
int outerwidth,
int innerwidth,
Path * outer_path,
Path * inner_path,
List * keys,
MergeOrder * order,
List * mergeclauses,
List * outersortkeys,
List * innersortkeys)
{
MergePath *pathnode = makeNode(MergePath);
MergePath *pathnode = makeNode(MergePath);
pathnode->jpath.path.pathtype = T_MergeJoin;
pathnode->jpath.path.parent = joinrel;
pathnode->jpath.outerjoinpath = outer_path;
pathnode->jpath.innerjoinpath = inner_path;
pathnode->jpath.pathclauseinfo = joinrel->clauseinfo;
pathnode->jpath.path.keys = keys;
pathnode->jpath.path.p_ordering.ordtype = MERGE_ORDER;
pathnode->jpath.path.p_ordering.ord.merge = order;
pathnode->path_mergeclauses = mergeclauses;
pathnode->jpath.path.locclauseinfo = NIL;
pathnode->outersortkeys = outersortkeys;
pathnode->innersortkeys = innersortkeys;
pathnode->jpath.path.path_cost =
cost_mergesort(outer_path->path_cost,
inner_path->path_cost,
outersortkeys,
innersortkeys,
outersize,
innersize,
outerwidth,
innerwidth);
/* add in expensive function costs -- JMH 7/7/92 */
pathnode->jpath.path.pathtype = T_MergeJoin;
pathnode->jpath.path.parent = joinrel;
pathnode->jpath.outerjoinpath = outer_path;
pathnode->jpath.innerjoinpath = inner_path;
pathnode->jpath.pathclauseinfo = joinrel->clauseinfo;
pathnode->jpath.path.keys = keys;
pathnode->jpath.path.p_ordering.ordtype = MERGE_ORDER;
pathnode->jpath.path.p_ordering.ord.merge = order;
pathnode->path_mergeclauses = mergeclauses;
pathnode->jpath.path.locclauseinfo = NIL;
pathnode->outersortkeys = outersortkeys;
pathnode->innersortkeys = innersortkeys;
pathnode->jpath.path.path_cost =
cost_mergesort(outer_path->path_cost,
inner_path->path_cost,
outersortkeys,
innersortkeys,
outersize,
innersize,
outerwidth,
innerwidth);
/* add in expensive function costs -- JMH 7/7/92 */
#if 0
if (XfuncMode != XFUNC_OFF) {
pathnode->path_cost +=
xfunc_get_path_cost((Path*)pathnode);
}
if (XfuncMode != XFUNC_OFF)
{
pathnode->path_cost +=
xfunc_get_path_cost((Path *) pathnode);
}
#endif
return(pathnode);
return (pathnode);
}
/*
* create_hashjoin_path-- XXX HASH
* Creates a pathnode corresponding to a hash join between two relations.
*
/*
* create_hashjoin_path-- XXX HASH
* Creates a pathnode corresponding to a hash join between two relations.
*
* 'joinrel' is the join relation
* 'outersize' is the number of tuples in the outer relation
* 'innersize' is the number of tuples in the inner relation
@@ -516,52 +558,53 @@ create_mergesort_path(Rel *joinrel,
* 'hashclauses' are the applicable join/restriction clauses
* 'outerkeys' are the sort varkeys for the outer relation
* 'innerkeys' are the sort varkeys for the inner relation
*
*
*/
HashPath *
create_hashjoin_path(Rel *joinrel,
int outersize,
int innersize,
int outerwidth,
int innerwidth,
Path *outer_path,
Path *inner_path,
List *keys,
Oid operator,
List *hashclauses,
List *outerkeys,
List *innerkeys)
HashPath *
create_hashjoin_path(Rel * joinrel,
int outersize,
int innersize,
int outerwidth,
int innerwidth,
Path * outer_path,
Path * inner_path,
List * keys,
Oid operator,
List * hashclauses,
List * outerkeys,
List * innerkeys)
{
HashPath *pathnode = makeNode(HashPath);
HashPath *pathnode = makeNode(HashPath);
pathnode->jpath.path.pathtype = T_HashJoin;
pathnode->jpath.path.parent = joinrel;
pathnode->jpath.outerjoinpath = outer_path;
pathnode->jpath.innerjoinpath = inner_path;
pathnode->jpath.pathclauseinfo = joinrel->clauseinfo;
pathnode->jpath.path.locclauseinfo = NIL;
pathnode->jpath.path.keys = keys;
pathnode->jpath.path.p_ordering.ordtype = SORTOP_ORDER;
pathnode->jpath.path.p_ordering.ord.sortop = NULL;
pathnode->jpath.path.outerjoincost = (Cost)0.0;
pathnode->jpath.path.joinid = (Relid)NULL;
/* pathnode->hashjoinoperator = operator; */
pathnode->path_hashclauses = hashclauses;
pathnode->outerhashkeys = outerkeys;
pathnode->innerhashkeys = innerkeys;
pathnode->jpath.path.path_cost =
cost_hashjoin(outer_path->path_cost,
inner_path->path_cost,
outerkeys,
innerkeys,
outersize,innersize,
outerwidth,innerwidth);
/* add in expensive function costs -- JMH 7/7/92 */
pathnode->jpath.path.pathtype = T_HashJoin;
pathnode->jpath.path.parent = joinrel;
pathnode->jpath.outerjoinpath = outer_path;
pathnode->jpath.innerjoinpath = inner_path;
pathnode->jpath.pathclauseinfo = joinrel->clauseinfo;
pathnode->jpath.path.locclauseinfo = NIL;
pathnode->jpath.path.keys = keys;
pathnode->jpath.path.p_ordering.ordtype = SORTOP_ORDER;
pathnode->jpath.path.p_ordering.ord.sortop = NULL;
pathnode->jpath.path.outerjoincost = (Cost) 0.0;
pathnode->jpath.path.joinid = (Relid) NULL;
/* pathnode->hashjoinoperator = operator; */
pathnode->path_hashclauses = hashclauses;
pathnode->outerhashkeys = outerkeys;
pathnode->innerhashkeys = innerkeys;
pathnode->jpath.path.path_cost =
cost_hashjoin(outer_path->path_cost,
inner_path->path_cost,
outerkeys,
innerkeys,
outersize, innersize,
outerwidth, innerwidth);
/* add in expensive function costs -- JMH 7/7/92 */
#if 0
if (XfuncMode != XFUNC_OFF) {
pathnode->path_cost +=
xfunc_get_path_cost((Path*)pathnode);
}
if (XfuncMode != XFUNC_OFF)
{
pathnode->path_cost +=
xfunc_get_path_cost((Path *) pathnode);
}
#endif
return(pathnode);
return (pathnode);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* relnode.c--
* Relation manipulation routines
* Relation manipulation routines
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.1.1.1 1996/07/09 06:21:39 scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.2 1997/09/07 04:44:32 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -16,108 +16,118 @@
#include "nodes/relation.h"
#include "optimizer/internal.h"
#include "optimizer/pathnode.h" /* where the decls go */
#include "optimizer/pathnode.h" /* where the decls go */
#include "optimizer/plancat.h"
/*
/*
* get_base_rel--
* Returns relation entry corresponding to 'relid', creating a new one if
* necessary. This is for base relations.
*
* Returns relation entry corresponding to 'relid', creating a new one if
* necessary. This is for base relations.
*
*/
Rel *get_base_rel(Query* root, int relid)
Rel *
get_base_rel(Query * root, int relid)
{
List *relids;
Rel *rel;
List *relids;
Rel *rel;
relids = lconsi(relid, NIL);
rel = rel_member(relids, root->base_relation_list_);
if (rel==NULL) {
rel = makeNode(Rel);
rel->relids = relids;
rel->indexed = false;
rel->pages = 0;
rel->tuples = 0;
rel->width = 0;
rel->targetlist = NIL;
rel->pathlist = NIL;
rel->unorderedpath = (Path *)NULL;
rel->cheapestpath = (Path *)NULL;
rel->pruneable = true;
rel->classlist = NULL;
rel->ordering = NULL;
rel->relam = InvalidOid;
rel->clauseinfo = NIL;
rel->joininfo = NIL;
rel->innerjoin = NIL;
rel->superrels = NIL;
root->base_relation_list_ = lcons(rel,
root->base_relation_list_);
/*
* ??? the old lispy C code (get_rel) do a listp(relid) here but
* that can never happen since we already established relid is not
* a list. -ay 10/94
*/
if(relid < 0) {
/*
* If the relation is a materialized relation, assume
* constants for sizes.
*/
rel->pages = _TEMP_RELATION_PAGES_;
rel->tuples = _TEMP_RELATION_TUPLES_;
} else {
bool hasindex;
int pages, tuples;
/*
* Otherwise, retrieve relation characteristics from the
* system catalogs.
*/
relation_info(root, relid, &hasindex, &pages, &tuples);
rel->indexed = hasindex;
rel->pages = pages;
rel->tuples = tuples;
}
}
return rel;
}
relids = lconsi(relid, NIL);
rel = rel_member(relids, root->base_relation_list_);
if (rel == NULL)
{
rel = makeNode(Rel);
rel->relids = relids;
rel->indexed = false;
rel->pages = 0;
rel->tuples = 0;
rel->width = 0;
rel->targetlist = NIL;
rel->pathlist = NIL;
rel->unorderedpath = (Path *) NULL;
rel->cheapestpath = (Path *) NULL;
rel->pruneable = true;
rel->classlist = NULL;
rel->ordering = NULL;
rel->relam = InvalidOid;
rel->clauseinfo = NIL;
rel->joininfo = NIL;
rel->innerjoin = NIL;
rel->superrels = NIL;
/*
* get_join_rel--
* Returns relation entry corresponding to 'relid' (a list of relids),
* creating a new one if necessary. This is for join relations.
*
*/
Rel *get_join_rel(Query *root, List *relid)
{
return rel_member(relid, root->join_relation_list_);
}
root->base_relation_list_ = lcons(rel,
root->base_relation_list_);
/*
* rel-member--
* Determines whether a relation of id 'relid' is contained within a list
* 'rels'.
*
* Returns the corresponding entry in 'rels' if it is there.
*
*/
Rel *
rel_member(List *relid, List *rels)
{
List *temp = NIL;
List *temprelid = NIL;
if (relid!=NIL && rels!=NIL) {
foreach(temp,rels) {
temprelid = ((Rel*)lfirst(temp))->relids;
if(same(temprelid, relid))
return((Rel*)(lfirst(temp)));
/*
* ??? the old lispy C code (get_rel) do a listp(relid) here but
* that can never happen since we already established relid is not
* a list. -ay 10/94
*/
if (relid < 0)
{
/*
* If the relation is a materialized relation, assume
* constants for sizes.
*/
rel->pages = _TEMP_RELATION_PAGES_;
rel->tuples = _TEMP_RELATION_TUPLES_;
}
else
{
bool hasindex;
int pages,
tuples;
/*
* Otherwise, retrieve relation characteristics from the
* system catalogs.
*/
relation_info(root, relid, &hasindex, &pages, &tuples);
rel->indexed = hasindex;
rel->pages = pages;
rel->tuples = tuples;
}
}
}
return(NULL);
return rel;
}
/*
* get_join_rel--
* Returns relation entry corresponding to 'relid' (a list of relids),
* creating a new one if necessary. This is for join relations.
*
*/
Rel *
get_join_rel(Query * root, List * relid)
{
return rel_member(relid, root->join_relation_list_);
}
/*
* rel-member--
* Determines whether a relation of id 'relid' is contained within a list
* 'rels'.
*
* Returns the corresponding entry in 'rels' if it is there.
*
*/
Rel *
rel_member(List * relid, List * rels)
{
List *temp = NIL;
List *temprelid = NIL;
if (relid != NIL && rels != NIL)
{
foreach(temp, rels)
{
temprelid = ((Rel *) lfirst(temp))->relids;
if (same(temprelid, relid))
return ((Rel *) (lfirst(temp)));
}
}
return (NULL);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* var.c--
* Var node manipulation routines
* Var node manipulation routines
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.3 1996/11/06 09:29:26 scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.4 1997/09/07 04:44:35 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -27,169 +27,193 @@
#include "parser/parsetree.h"
/*
* find_varnos
* find_varnos
*
* Descends down part of a parsetree (qual or tlist),
* Descends down part of a parsetree (qual or tlist),
*
* XXX assumes varno's are always integers, which shouldn't be true...
* (though it currently is, see primnodes.h)
* XXX assumes varno's are always integers, which shouldn't be true...
* (though it currently is, see primnodes.h)
*/
List *
pull_varnos(Node *me)
List *
pull_varnos(Node * me)
{
List *i, *result = NIL;
if (me == NULL)
return (NIL);
List *i,
*result = NIL;
switch (nodeTag(me)) {
case T_List:
foreach (i, (List*)me) {
result = nconc(result, pull_varnos(lfirst(i)));
if (me == NULL)
return (NIL);
switch (nodeTag(me))
{
case T_List:
foreach(i, (List *) me)
{
result = nconc(result, pull_varnos(lfirst(i)));
}
break;
case T_ArrayRef:
foreach(i, ((ArrayRef *) me)->refupperindexpr)
result = nconc(result, pull_varnos(lfirst(i)));
foreach(i, ((ArrayRef *) me)->reflowerindexpr)
result = nconc(result, pull_varnos(lfirst(i)));
result = nconc(result, pull_varnos(((ArrayRef *) me)->refassgnexpr));
break;
case T_Var:
result = lconsi(((Var *) me)->varno, NIL);
break;
default:
break;
}
break;
case T_ArrayRef:
foreach (i, ((ArrayRef*) me)->refupperindexpr)
result = nconc(result, pull_varnos(lfirst(i)));
foreach (i, ((ArrayRef*) me)->reflowerindexpr)
result = nconc(result, pull_varnos(lfirst(i)));
result = nconc(result, pull_varnos(((ArrayRef*) me)->refassgnexpr));
break;
case T_Var:
result = lconsi(((Var*) me)->varno, NIL);
break;
default:
break;
}
return(result);
return (result);
}
/*
/*
* contain_var_clause--
* Recursively find var nodes from a clause by pulling vars from the
* left and right operands of the clause.
*
* Returns true if any varnode found.
*/
bool contain_var_clause(Node *clause)
{
if (clause==NULL)
return FALSE;
else if (IsA(clause,Var))
return TRUE;
else if (IsA(clause,Iter))
return contain_var_clause(((Iter*)clause)->iterexpr);
else if (single_node(clause))
return FALSE;
else if (or_clause(clause)) {
List *temp;
foreach (temp, ((Expr*)clause)->args) {
if (contain_var_clause(lfirst(temp)))
return TRUE;
}
return FALSE;
} else if (is_funcclause (clause)) {
List *temp;
foreach(temp, ((Expr *)clause)->args) {
if (contain_var_clause(lfirst(temp)))
return TRUE;
}
return FALSE;
} else if (IsA(clause,ArrayRef)) {
List *temp;
foreach(temp, ((ArrayRef*)clause)->refupperindexpr) {
if (contain_var_clause(lfirst(temp)))
return TRUE;
}
foreach(temp, ((ArrayRef*)clause)->reflowerindexpr) {
if (contain_var_clause(lfirst(temp)))
return TRUE;
}
if (contain_var_clause(((ArrayRef*)clause)->refexpr))
return TRUE;
if (contain_var_clause(((ArrayRef*)clause)->refassgnexpr))
return TRUE;
return FALSE;
} else if (not_clause(clause))
return contain_var_clause((Node*)get_notclausearg((Expr*)clause));
else if (is_opclause(clause))
return (contain_var_clause((Node*)get_leftop((Expr*)clause)) ||
contain_var_clause((Node*)get_rightop((Expr*)clause)));
return FALSE;
}
/*
* pull_var_clause--
* Recursively pulls all var nodes from a clause by pulling vars from the
* left and right operands of the clause.
*
* Returns list of varnodes found.
*/
List *
pull_var_clause(Node *clause)
{
List *retval = NIL;
if (clause==NULL)
return(NIL);
else if (IsA(clause,Var))
retval = lcons(clause,NIL);
else if (IsA(clause,Iter))
retval = pull_var_clause(((Iter*)clause)->iterexpr);
else if (single_node(clause))
retval = NIL;
else if (or_clause(clause)) {
List *temp;
foreach (temp, ((Expr*)clause)->args)
retval = nconc(retval, pull_var_clause(lfirst(temp)));
} else if (is_funcclause (clause)) {
List *temp;
foreach(temp, ((Expr *)clause)->args)
retval = nconc (retval,pull_var_clause(lfirst(temp)));
} else if (IsA(clause,Aggreg)) {
retval = pull_var_clause(((Aggreg*)clause)->target);
} else if (IsA(clause,ArrayRef)) {
List *temp;
foreach(temp, ((ArrayRef*)clause)->refupperindexpr)
retval = nconc (retval,pull_var_clause(lfirst(temp)));
foreach(temp, ((ArrayRef*)clause)->reflowerindexpr)
retval = nconc (retval,pull_var_clause(lfirst(temp)));
retval = nconc(retval,
pull_var_clause(((ArrayRef*)clause)->refexpr));
retval = nconc(retval,
pull_var_clause(((ArrayRef*)clause)->refassgnexpr));
} else if (not_clause(clause))
retval = pull_var_clause((Node*)get_notclausearg((Expr*)clause));
else if (is_opclause(clause))
retval = nconc(pull_var_clause((Node*)get_leftop((Expr*)clause)),
pull_var_clause((Node*)get_rightop((Expr*)clause)));
else
retval = NIL;
return (retval);
}
/*
* var_equal
*
* Returns t iff two var nodes correspond to the same attribute.
* Recursively find var nodes from a clause by pulling vars from the
* left and right operands of the clause.
*
* Returns true if any varnode found.
*/
bool
var_equal(Var *var1, Var *var2)
contain_var_clause(Node * clause)
{
if (IsA (var1,Var) && IsA (var2,Var) &&
(((Var*)var1)->varno == ((Var*)var2)->varno) &&
(((Var*)var1)->vartype == ((Var*)var2)->vartype) &&
(((Var*)var1)->varattno == ((Var*)var2)->varattno)) {
if (clause == NULL)
return FALSE;
else if (IsA(clause, Var))
return TRUE;
else if (IsA(clause, Iter))
return contain_var_clause(((Iter *) clause)->iterexpr);
else if (single_node(clause))
return FALSE;
else if (or_clause(clause))
{
List *temp;
return(true);
} else
return(false);
foreach(temp, ((Expr *) clause)->args)
{
if (contain_var_clause(lfirst(temp)))
return TRUE;
}
return FALSE;
}
else if (is_funcclause(clause))
{
List *temp;
foreach(temp, ((Expr *) clause)->args)
{
if (contain_var_clause(lfirst(temp)))
return TRUE;
}
return FALSE;
}
else if (IsA(clause, ArrayRef))
{
List *temp;
foreach(temp, ((ArrayRef *) clause)->refupperindexpr)
{
if (contain_var_clause(lfirst(temp)))
return TRUE;
}
foreach(temp, ((ArrayRef *) clause)->reflowerindexpr)
{
if (contain_var_clause(lfirst(temp)))
return TRUE;
}
if (contain_var_clause(((ArrayRef *) clause)->refexpr))
return TRUE;
if (contain_var_clause(((ArrayRef *) clause)->refassgnexpr))
return TRUE;
return FALSE;
}
else if (not_clause(clause))
return contain_var_clause((Node *) get_notclausearg((Expr *) clause));
else if (is_opclause(clause))
return (contain_var_clause((Node *) get_leftop((Expr *) clause)) ||
contain_var_clause((Node *) get_rightop((Expr *) clause)));
return FALSE;
}
/*
* pull_var_clause--
* Recursively pulls all var nodes from a clause by pulling vars from the
* left and right operands of the clause.
*
* Returns list of varnodes found.
*/
List *
pull_var_clause(Node * clause)
{
List *retval = NIL;
if (clause == NULL)
return (NIL);
else if (IsA(clause, Var))
retval = lcons(clause, NIL);
else if (IsA(clause, Iter))
retval = pull_var_clause(((Iter *) clause)->iterexpr);
else if (single_node(clause))
retval = NIL;
else if (or_clause(clause))
{
List *temp;
foreach(temp, ((Expr *) clause)->args)
retval = nconc(retval, pull_var_clause(lfirst(temp)));
}
else if (is_funcclause(clause))
{
List *temp;
foreach(temp, ((Expr *) clause)->args)
retval = nconc(retval, pull_var_clause(lfirst(temp)));
}
else if (IsA(clause, Aggreg))
{
retval = pull_var_clause(((Aggreg *) clause)->target);
}
else if (IsA(clause, ArrayRef))
{
List *temp;
foreach(temp, ((ArrayRef *) clause)->refupperindexpr)
retval = nconc(retval, pull_var_clause(lfirst(temp)));
foreach(temp, ((ArrayRef *) clause)->reflowerindexpr)
retval = nconc(retval, pull_var_clause(lfirst(temp)));
retval = nconc(retval,
pull_var_clause(((ArrayRef *) clause)->refexpr));
retval = nconc(retval,
pull_var_clause(((ArrayRef *) clause)->refassgnexpr));
}
else if (not_clause(clause))
retval = pull_var_clause((Node *) get_notclausearg((Expr *) clause));
else if (is_opclause(clause))
retval = nconc(pull_var_clause((Node *) get_leftop((Expr *) clause)),
pull_var_clause((Node *) get_rightop((Expr *) clause)));
else
retval = NIL;
return (retval);
}
/*
* var_equal
*
* Returns t iff two var nodes correspond to the same attribute.
*/
bool
var_equal(Var * var1, Var * var2)
{
if (IsA(var1, Var) && IsA(var2, Var) &&
(((Var *) var1)->varno == ((Var *) var2)->varno) &&
(((Var *) var1)->vartype == ((Var *) var2)->vartype) &&
(((Var *) var1)->varattno == ((Var *) var2)->varattno))
{
return (true);
}
else
return (false);
}