Add equal() funcs for Case nodes ... amazing we had not

detected this omission before.  Miscellaneous other cleanups.
This commit is contained in:
Tom Lane 1999-07-29 02:45:36 +00:00
parent a06fd1f316
commit 6b157f376a
1 changed files with 164 additions and 178 deletions

View File

@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* equalfuncs.c
* equal functions to compare the nodes
* equality functions to compare node trees
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.44 1999/07/24 23:21:06 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.45 1999/07/29 02:45:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -20,13 +20,11 @@
static bool equali(List *a, List *b);
/*
* Stuff from primnodes.h
*/
/*
* Resdom is a subclass of Node.
*/
static bool
_equalResdom(Resdom *a, Resdom *b)
{
@ -40,10 +38,11 @@ _equalResdom(Resdom *a, Resdom *b)
return false;
if (a->reskey != b->reskey)
return false;
if (a->resgroupref != b->resgroupref)
return false;
if (a->reskeyop != b->reskeyop)
return false;
if (a->resgroupref != b->resgroupref)
return false;
/* we ignore resjunk flag ... is this correct? */
return true;
}
@ -69,12 +68,13 @@ _equalFjoin(Fjoin *a, Fjoin *b)
return true;
}
/*
* Expr is a subclass of Node.
*/
static bool
_equalExpr(Expr *a, Expr *b)
{
/* We do not examine typeOid, since the optimizer often doesn't
* bother to set it in created nodes, and it is logically a
* derivative of the oper field anyway.
*/
if (a->opType != b->opType)
return false;
if (!equal(a->oper, b->oper))
@ -85,35 +85,6 @@ _equalExpr(Expr *a, Expr *b)
return true;
}
static bool
_equalIter(Iter *a, Iter *b)
{
return equal(a->iterexpr, b->iterexpr);
}
static bool
_equalStream(Stream *a, Stream *b)
{
if (a->clausetype != b->clausetype)
return false;
if (a->groupup != b->groupup)
return false;
if (a->groupcost != b->groupcost)
return false;
if (a->groupsel != b->groupsel)
return false;
if (!equal(a->pathptr, b->pathptr))
return false;
if (!equal(a->cinfo, b->cinfo))
return false;
if (!equal(a->upstream, b->upstream))
return false;
return equal(a->downstream, b->downstream);
}
/*
* Var is a subclass of Expr.
*/
static bool
_equalVar(Var *a, Var *b)
{
@ -135,45 +106,6 @@ _equalVar(Var *a, Var *b)
return true;
}
static bool
_equalArray(Array *a, Array *b)
{
if (a->arrayelemtype != b->arrayelemtype)
return false;
if (a->arrayndim != b->arrayndim)
return false;
if (a->arraylow.indx[0] != b->arraylow.indx[0])
return false;
if (a->arrayhigh.indx[0] != b->arrayhigh.indx[0])
return false;
if (a->arraylen != b->arraylen)
return false;
return TRUE;
}
static bool
_equalArrayRef(ArrayRef *a, ArrayRef *b)
{
if (a->refelemtype != b->refelemtype)
return false;
if (a->refattrlength != b->refattrlength)
return false;
if (a->refelemlength != b->refelemlength)
return false;
if (a->refelembyval != b->refelembyval)
return false;
if (!equal(a->refupperindexpr, b->refupperindexpr))
return false;
if (!equal(a->reflowerindexpr, b->reflowerindexpr))
return false;
if (!equal(a->refexpr, b->refexpr))
return false;
return equal(a->refassgnexpr, b->refassgnexpr);
}
/*
* Oper is a subclass of Expr.
*/
static bool
_equalOper(Oper *a, Oper *b)
{
@ -181,21 +113,19 @@ _equalOper(Oper *a, Oper *b)
return false;
if (a->opresulttype != b->opresulttype)
return false;
/* We do not examine opid, opsize, or op_fcache, since these are
* logically derived from opno, and they may not be set yet depending
* on how far along the node is in the parse/plan pipeline.
*
* It's probably not really necessary to check opresulttype either...
*/
return true;
}
/*
* Const is a subclass of Expr.
*/
static bool
_equalConst(Const *a, Const *b)
{
/*
* * this function used to do a pointer compare on a and b. That's *
* ridiculous. -- JMH, 7/11/92
*/
if (a->consttype != b->consttype)
return false;
if (a->constlen != b->constlen)
@ -204,13 +134,11 @@ _equalConst(Const *a, Const *b)
return false;
if (a->constbyval != b->constbyval)
return false;
/* XXX What about constisset and constiscast? */
return (datumIsEqual(a->constvalue, b->constvalue,
a->consttype, a->constbyval, a->constlen));
}
/*
* Param is a subclass of Expr.
*/
static bool
_equalParam(Param *a, Param *b)
{
@ -249,9 +177,26 @@ _equalParam(Param *a, Param *b)
return true;
}
/*
* Aggref is a subclass of Expr.
*/
static bool
_equalFunc(Func *a, Func *b)
{
if (a->funcid != b->funcid)
return false;
if (a->functype != b->functype)
return false;
if (a->funcisindex != b->funcisindex)
return false;
if (a->funcsize != b->funcsize)
return false;
/* Note we do not look at func_fcache */
if (!equal(a->func_tlist, b->func_tlist))
return false;
if (!equal(a->func_planlist, b->func_planlist))
return false;
return true;
}
static bool
_equalAggref(Aggref *a, Aggref *b)
{
@ -270,68 +215,61 @@ _equalAggref(Aggref *a, Aggref *b)
return true;
}
/*
* Func is a subclass of Expr.
*/
static bool
_equalFunc(Func *a, Func *b)
_equalArray(Array *a, Array *b)
{
if (a->funcid != b->funcid)
if (a->arrayelemtype != b->arrayelemtype)
return false;
if (a->functype != b->functype)
/* We need not check arrayelemlength, arrayelembyval if types match */
if (a->arrayndim != b->arrayndim)
return false;
if (a->funcisindex != b->funcisindex)
/* XXX shouldn't we be checking all indices??? */
if (a->arraylow.indx[0] != b->arraylow.indx[0])
return false;
if (a->funcsize != b->funcsize)
if (a->arrayhigh.indx[0] != b->arrayhigh.indx[0])
return false;
if (!equal(a->func_tlist, b->func_tlist))
return false;
if (!equal(a->func_planlist, b->func_planlist))
if (a->arraylen != b->arraylen)
return false;
return true;
}
/*
* RestrictInfo is a subclass of Node.
*/
static bool
_equalRestrictInfo(RestrictInfo *a, RestrictInfo *b)
_equalArrayRef(ArrayRef *a, ArrayRef *b)
{
Assert(IsA(a, RestrictInfo));
Assert(IsA(b, RestrictInfo));
if (!equal(a->clause, b->clause))
if (a->refelemtype != b->refelemtype)
return false;
if (a->selectivity != b->selectivity)
if (a->refattrlength != b->refattrlength)
return false;
#ifdef EqualMergeOrderExists
if (!EqualMergeOrder(a->mergejoinorder, b->mergejoinorder))
if (a->refelemlength != b->refelemlength)
return false;
#endif
if (a->hashjoinoperator != b->hashjoinoperator)
if (a->refelembyval != b->refelembyval)
return false;
return equal(a->indexids, b->indexids);
if (!equal(a->refupperindexpr, b->refupperindexpr))
return false;
if (!equal(a->reflowerindexpr, b->reflowerindexpr))
return false;
if (!equal(a->refexpr, b->refexpr))
return false;
return equal(a->refassgnexpr, b->refassgnexpr);
}
/*
* RelOptInfo is a subclass of Node.
* Stuff from relation.h
*/
static bool
_equalRelOptInfo(RelOptInfo *a, RelOptInfo *b)
{
Assert(IsA(a, RelOptInfo));
Assert(IsA(b, RelOptInfo));
/* We treat RelOptInfos as equal if they refer to the same base rels
* joined in the same order. Is this sufficient?
*/
return equal(a->relids, b->relids);
}
static bool
_equalJoinMethod(JoinMethod *a, JoinMethod *b)
{
Assert(IsA(a, JoinMethod));
Assert(IsA(b, JoinMethod));
if (!equal(a->jmkeys, b->jmkeys))
return false;
if (!equal(a->clauses, b->clauses))
@ -344,16 +282,17 @@ _equalPath(Path *a, Path *b)
{
if (a->pathtype != b->pathtype)
return false;
if (a->parent != b->parent)
if (a->parent != b->parent) /* should this use equal() ? */
return false;
/*
* if (a->path_cost != b->path_cost) return(false);
/* do not check path_cost, since it may not be set yet, and being
* a float there are roundoff error issues anyway...
*/
/* XXX this should probably be in an _equalPathOrder function... */
if (a->pathorder->ordtype != b->pathorder->ordtype)
return false;
if (a->pathorder->ordtype == SORTOP_ORDER)
{
int i = 0;
if (a->pathorder->ord.sortop == NULL ||
b->pathorder->ord.sortop == NULL)
{
@ -362,15 +301,15 @@ _equalPath(Path *a, Path *b)
}
else
{
while (a->pathorder->ord.sortop[i] != 0 &&
b->pathorder->ord.sortop[i] != 0)
int i = 0;
while (a->pathorder->ord.sortop[i] != 0)
{
if (a->pathorder->ord.sortop[i] != b->pathorder->ord.sortop[i])
return false;
i++;
}
if (a->pathorder->ord.sortop[i] != 0 ||
b->pathorder->ord.sortop[i] != 0)
if (b->pathorder->ord.sortop[i] != 0)
return false;
}
}
@ -379,12 +318,10 @@ _equalPath(Path *a, Path *b)
if (!equal(a->pathorder->ord.merge, b->pathorder->ord.merge))
return false;
}
if (!equal(a->pathkeys, b->pathkeys))
return false;
/*
* if (a->outerjoincost != b->outerjoincost) return(false);
*/
/* do not check outerjoincost either */
if (!equali(a->joinid, b->joinid))
return false;
return true;
@ -399,15 +336,13 @@ _equalIndexPath(IndexPath *a, IndexPath *b)
return false;
if (!equal(a->indexqual, b->indexqual))
return false;
/* We do not need to check indexkeys */
return true;
}
static bool
_equalNestPath(NestPath *a, NestPath *b)
{
Assert(IsA_JoinPath(a));
Assert(IsA_JoinPath(b));
if (!_equalPath((Path *) a, (Path *) b))
return false;
if (!equal(a->pathinfo, b->pathinfo))
@ -422,9 +357,6 @@ _equalNestPath(NestPath *a, NestPath *b)
static bool
_equalMergePath(MergePath *a, MergePath *b)
{
Assert(IsA(a, MergePath));
Assert(IsA(b, MergePath));
if (!_equalNestPath((NestPath *) a, (NestPath *) b))
return false;
if (!equal(a->path_mergeclauses, b->path_mergeclauses))
@ -439,12 +371,9 @@ _equalMergePath(MergePath *a, MergePath *b)
static bool
_equalHashPath(HashPath *a, HashPath *b)
{
Assert(IsA(a, HashPath));
Assert(IsA(b, HashPath));
if (!_equalNestPath((NestPath *) a, (NestPath *) b))
return false;
if (!equal((a->path_hashclauses), (b->path_hashclauses)))
if (!equal(a->path_hashclauses, b->path_hashclauses))
return false;
if (!equal(a->outerhashkeys, b->outerhashkeys))
return false;
@ -456,9 +385,6 @@ _equalHashPath(HashPath *a, HashPath *b)
static bool
_equalJoinKey(JoinKey *a, JoinKey *b)
{
Assert(IsA(a, JoinKey));
Assert(IsA(b, JoinKey));
if (!equal(a->outer, b->outer))
return false;
if (!equal(a->inner, b->inner))
@ -469,11 +395,6 @@ _equalJoinKey(JoinKey *a, JoinKey *b)
static bool
_equalMergeOrder(MergeOrder *a, MergeOrder *b)
{
if (a == (MergeOrder *) NULL && b == (MergeOrder *) NULL)
return true;
Assert(IsA(a, MergeOrder));
Assert(IsA(b, MergeOrder));
if (a->join_operator != b->join_operator)
return false;
if (a->left_operator != b->left_operator)
@ -490,9 +411,8 @@ _equalMergeOrder(MergeOrder *a, MergeOrder *b)
static bool
_equalHashInfo(HashInfo *a, HashInfo *b)
{
Assert(IsA(a, HashInfo));
Assert(IsA(b, HashInfo));
if (!_equalJoinMethod((JoinMethod *) a, (JoinMethod *) b))
return false;
if (a->hashop != b->hashop)
return false;
return true;
@ -500,13 +420,13 @@ _equalHashInfo(HashInfo *a, HashInfo *b)
/* XXX This equality function is a quick hack, should be
* fixed to compare all fields.
*
* XXX Why is this even here? We don't have equal() funcs for
* any other kinds of Plan nodes... likely this is dead code...
*/
static bool
_equalIndexScan(IndexScan *a, IndexScan *b)
{
Assert(IsA(a, IndexScan));
Assert(IsA(b, IndexScan));
/*
* if(a->scan.plan.cost != b->scan.plan.cost) return(false);
*/
@ -537,8 +457,6 @@ _equalSubPlan(SubPlan *a, SubPlan *b)
static bool
_equalJoinInfo(JoinInfo *a, JoinInfo *b)
{
Assert(IsA(a, JoinInfo));
Assert(IsA(b, JoinInfo));
if (!equal(a->unjoined_relids, b->unjoined_relids))
return false;
if (!equal(a->jinfo_restrictinfo, b->jinfo_restrictinfo))
@ -550,6 +468,45 @@ _equalJoinInfo(JoinInfo *a, JoinInfo *b)
return true;
}
static bool
_equalRestrictInfo(RestrictInfo *a, RestrictInfo *b)
{
if (!equal(a->clause, b->clause))
return false;
/* do not check selectivity because of roundoff error worries */
if (!equal(a->mergejoinorder, b->mergejoinorder))
return false;
if (a->hashjoinoperator != b->hashjoinoperator)
return false;
return equal(a->indexids, b->indexids);
}
static bool
_equalIter(Iter *a, Iter *b)
{
return equal(a->iterexpr, b->iterexpr);
}
static bool
_equalStream(Stream *a, Stream *b)
{
if (a->clausetype != b->clausetype)
return false;
if (a->groupup != b->groupup)
return false;
if (a->groupcost != b->groupcost)
return false;
if (a->groupsel != b->groupsel)
return false;
if (!equal(a->pathptr, b->pathptr))
return false;
if (!equal(a->cinfo, b->cinfo))
return false;
if (!equal(a->upstream, b->upstream))
return false;
return equal(a->downstream, b->downstream);
}
/*
* Stuff from execnodes.h
*/
@ -696,6 +653,32 @@ _equalTargetEntry(TargetEntry *a, TargetEntry *b)
return true;
}
static bool
_equalCaseExpr(CaseExpr *a, CaseExpr *b)
{
if (a->casetype != b->casetype)
return false;
if (!equal(a->arg, b->arg))
return false;
if (!equal(a->args, b->args))
return false;
if (!equal(a->defresult, b->defresult))
return false;
return true;
}
static bool
_equalCaseWhen(CaseWhen *a, CaseWhen *b)
{
if (!equal(a->expr, b->expr))
return false;
if (!equal(a->result, b->result))
return false;
return true;
}
/*
* Stuff from pg_list.h
*/
@ -842,9 +825,10 @@ equal(void *a, void *b)
List *lb = (List *) b;
List *l;
if (a == NULL && b == NULL)
return true;
if (length(a) != length(b))
/* Try to reject by length check before we grovel through
* all the elements...
*/
if (length(la) != length(lb))
return false;
foreach(l, la)
{
@ -864,6 +848,12 @@ equal(void *a, void *b)
case T_TargetEntry:
retval = _equalTargetEntry(a, b);
break;
case T_CaseExpr:
retval = _equalCaseExpr(a, b);
break;
case T_CaseWhen:
retval = _equalCaseWhen(a, b);
break;
default:
elog(NOTICE, "equal: don't know whether nodes of type %d are equal",
nodeTag(a));
@ -876,25 +866,21 @@ equal(void *a, void *b)
/*
* equali
* compares two lists of integers
*
* XXX temp hack. needs something like T_IntList
*/
static bool
equali(List *a, List *b)
{
List *la = (List *) a;
List *lb = (List *) b;
List *l;
if (a == NULL && b == NULL)
return true;
if (length(a) != length(b))
return false;
foreach(l, la)
foreach(l, a)
{
if (lfirsti(l) != lfirsti(lb))
if (b == NIL)
return false;
lb = lnext(lb);
if (lfirsti(l) != lfirsti(b))
return false;
b = lnext(b);
}
if (b != NIL)
return false;
return true;
}