Commit 6b157f37 authored by Tom Lane's avatar Tom Lane

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

detected this omission before.  Miscellaneous other cleanups.
parent a06fd1f3
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* equalfuncs.c * equalfuncs.c
* equal functions to compare the nodes * equality functions to compare node trees
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -20,13 +20,11 @@
static bool equali(List *a, List *b); static bool equali(List *a, List *b);
/* /*
* Stuff from primnodes.h * Stuff from primnodes.h
*/ */
/*
* Resdom is a subclass of Node.
*/
static bool static bool
_equalResdom(Resdom *a, Resdom *b) _equalResdom(Resdom *a, Resdom *b)
{ {
...@@ -40,10 +38,11 @@ _equalResdom(Resdom *a, Resdom *b) ...@@ -40,10 +38,11 @@ _equalResdom(Resdom *a, Resdom *b)
return false; return false;
if (a->reskey != b->reskey) if (a->reskey != b->reskey)
return false; return false;
if (a->resgroupref != b->resgroupref)
return false;
if (a->reskeyop != b->reskeyop) if (a->reskeyop != b->reskeyop)
return false; return false;
if (a->resgroupref != b->resgroupref)
return false;
/* we ignore resjunk flag ... is this correct? */
return true; return true;
} }
...@@ -69,12 +68,13 @@ _equalFjoin(Fjoin *a, Fjoin *b) ...@@ -69,12 +68,13 @@ _equalFjoin(Fjoin *a, Fjoin *b)
return true; return true;
} }
/*
* Expr is a subclass of Node.
*/
static bool static bool
_equalExpr(Expr *a, Expr *b) _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) if (a->opType != b->opType)
return false; return false;
if (!equal(a->oper, b->oper)) if (!equal(a->oper, b->oper))
...@@ -85,35 +85,6 @@ _equalExpr(Expr *a, Expr *b) ...@@ -85,35 +85,6 @@ _equalExpr(Expr *a, Expr *b)
return true; 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 static bool
_equalVar(Var *a, Var *b) _equalVar(Var *a, Var *b)
{ {
...@@ -135,45 +106,6 @@ _equalVar(Var *a, Var *b) ...@@ -135,45 +106,6 @@ _equalVar(Var *a, Var *b)
return true; 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 static bool
_equalOper(Oper *a, Oper *b) _equalOper(Oper *a, Oper *b)
{ {
...@@ -181,21 +113,19 @@ _equalOper(Oper *a, Oper *b) ...@@ -181,21 +113,19 @@ _equalOper(Oper *a, Oper *b)
return false; return false;
if (a->opresulttype != b->opresulttype) if (a->opresulttype != b->opresulttype)
return false; 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; return true;
} }
/*
* Const is a subclass of Expr.
*/
static bool static bool
_equalConst(Const *a, Const *b) _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) if (a->consttype != b->consttype)
return false; return false;
if (a->constlen != b->constlen) if (a->constlen != b->constlen)
...@@ -204,13 +134,11 @@ _equalConst(Const *a, Const *b) ...@@ -204,13 +134,11 @@ _equalConst(Const *a, Const *b)
return false; return false;
if (a->constbyval != b->constbyval) if (a->constbyval != b->constbyval)
return false; return false;
/* XXX What about constisset and constiscast? */
return (datumIsEqual(a->constvalue, b->constvalue, return (datumIsEqual(a->constvalue, b->constvalue,
a->consttype, a->constbyval, a->constlen)); a->consttype, a->constbyval, a->constlen));
} }
/*
* Param is a subclass of Expr.
*/
static bool static bool
_equalParam(Param *a, Param *b) _equalParam(Param *a, Param *b)
{ {
...@@ -249,9 +177,26 @@ _equalParam(Param *a, Param *b) ...@@ -249,9 +177,26 @@ _equalParam(Param *a, Param *b)
return true; return true;
} }
/* static bool
* Aggref is a subclass of Expr. _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 static bool
_equalAggref(Aggref *a, Aggref *b) _equalAggref(Aggref *a, Aggref *b)
{ {
...@@ -270,68 +215,61 @@ _equalAggref(Aggref *a, Aggref *b) ...@@ -270,68 +215,61 @@ _equalAggref(Aggref *a, Aggref *b)
return true; return true;
} }
/*
* Func is a subclass of Expr.
*/
static bool 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)
return false; return false;
if (a->funcisindex != b->funcisindex) /* We need not check arrayelemlength, arrayelembyval if types match */
if (a->arrayndim != b->arrayndim)
return false; return false;
if (a->funcsize != b->funcsize) /* XXX shouldn't we be checking all indices??? */
if (a->arraylow.indx[0] != b->arraylow.indx[0])
return false; return false;
if (!equal(a->func_tlist, b->func_tlist)) if (a->arrayhigh.indx[0] != b->arrayhigh.indx[0])
return false; return false;
if (!equal(a->func_planlist, b->func_planlist)) if (a->arraylen != b->arraylen)
return false; return false;
return true; return true;
} }
/*
* RestrictInfo is a subclass of Node.
*/
static bool static bool
_equalRestrictInfo(RestrictInfo *a, RestrictInfo *b) _equalArrayRef(ArrayRef *a, ArrayRef *b)
{ {
Assert(IsA(a, RestrictInfo)); if (a->refelemtype != b->refelemtype)
Assert(IsA(b, RestrictInfo));
if (!equal(a->clause, b->clause))
return false; return false;
if (a->selectivity != b->selectivity) if (a->refattrlength != b->refattrlength)
return false; return false;
#ifdef EqualMergeOrderExists if (a->refelemlength != b->refelemlength)
if (!EqualMergeOrder(a->mergejoinorder, b->mergejoinorder))
return false; return false;
#endif if (a->refelembyval != b->refelembyval)
if (a->hashjoinoperator != b->hashjoinoperator)
return false; 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 static bool
_equalRelOptInfo(RelOptInfo *a, RelOptInfo *b) _equalRelOptInfo(RelOptInfo *a, RelOptInfo *b)
{ {
Assert(IsA(a, RelOptInfo)); /* We treat RelOptInfos as equal if they refer to the same base rels
Assert(IsA(b, RelOptInfo)); * joined in the same order. Is this sufficient?
*/
return equal(a->relids, b->relids); return equal(a->relids, b->relids);
} }
static bool static bool
_equalJoinMethod(JoinMethod *a, JoinMethod *b) _equalJoinMethod(JoinMethod *a, JoinMethod *b)
{ {
Assert(IsA(a, JoinMethod));
Assert(IsA(b, JoinMethod));
if (!equal(a->jmkeys, b->jmkeys)) if (!equal(a->jmkeys, b->jmkeys))
return false; return false;
if (!equal(a->clauses, b->clauses)) if (!equal(a->clauses, b->clauses))
...@@ -344,16 +282,17 @@ _equalPath(Path *a, Path *b) ...@@ -344,16 +282,17 @@ _equalPath(Path *a, Path *b)
{ {
if (a->pathtype != b->pathtype) if (a->pathtype != b->pathtype)
return false; return false;
if (a->parent != b->parent) if (a->parent != b->parent) /* should this use equal() ? */
return false; return false;
/* do not check path_cost, since it may not be set yet, and being
/* * a float there are roundoff error issues anyway...
* if (a->path_cost != b->path_cost) return(false);
*/ */
/* XXX this should probably be in an _equalPathOrder function... */
if (a->pathorder->ordtype != b->pathorder->ordtype)
return false;
if (a->pathorder->ordtype == SORTOP_ORDER) if (a->pathorder->ordtype == SORTOP_ORDER)
{ {
int i = 0;
if (a->pathorder->ord.sortop == NULL || if (a->pathorder->ord.sortop == NULL ||
b->pathorder->ord.sortop == NULL) b->pathorder->ord.sortop == NULL)
{ {
...@@ -362,15 +301,15 @@ _equalPath(Path *a, Path *b) ...@@ -362,15 +301,15 @@ _equalPath(Path *a, Path *b)
} }
else else
{ {
while (a->pathorder->ord.sortop[i] != 0 && int i = 0;
b->pathorder->ord.sortop[i] != 0)
while (a->pathorder->ord.sortop[i] != 0)
{ {
if (a->pathorder->ord.sortop[i] != b->pathorder->ord.sortop[i]) if (a->pathorder->ord.sortop[i] != b->pathorder->ord.sortop[i])
return false; return false;
i++; i++;
} }
if (a->pathorder->ord.sortop[i] != 0 || if (b->pathorder->ord.sortop[i] != 0)
b->pathorder->ord.sortop[i] != 0)
return false; return false;
} }
} }
...@@ -379,12 +318,10 @@ _equalPath(Path *a, Path *b) ...@@ -379,12 +318,10 @@ _equalPath(Path *a, Path *b)
if (!equal(a->pathorder->ord.merge, b->pathorder->ord.merge)) if (!equal(a->pathorder->ord.merge, b->pathorder->ord.merge))
return false; return false;
} }
if (!equal(a->pathkeys, b->pathkeys)) if (!equal(a->pathkeys, b->pathkeys))
return false; return false;
/* do not check outerjoincost either */
/*
* if (a->outerjoincost != b->outerjoincost) return(false);
*/
if (!equali(a->joinid, b->joinid)) if (!equali(a->joinid, b->joinid))
return false; return false;
return true; return true;
...@@ -399,15 +336,13 @@ _equalIndexPath(IndexPath *a, IndexPath *b) ...@@ -399,15 +336,13 @@ _equalIndexPath(IndexPath *a, IndexPath *b)
return false; return false;
if (!equal(a->indexqual, b->indexqual)) if (!equal(a->indexqual, b->indexqual))
return false; return false;
/* We do not need to check indexkeys */
return true; return true;
} }
static bool static bool
_equalNestPath(NestPath *a, NestPath *b) _equalNestPath(NestPath *a, NestPath *b)
{ {
Assert(IsA_JoinPath(a));
Assert(IsA_JoinPath(b));
if (!_equalPath((Path *) a, (Path *) b)) if (!_equalPath((Path *) a, (Path *) b))
return false; return false;
if (!equal(a->pathinfo, b->pathinfo)) if (!equal(a->pathinfo, b->pathinfo))
...@@ -422,9 +357,6 @@ _equalNestPath(NestPath *a, NestPath *b) ...@@ -422,9 +357,6 @@ _equalNestPath(NestPath *a, NestPath *b)
static bool static bool
_equalMergePath(MergePath *a, MergePath *b) _equalMergePath(MergePath *a, MergePath *b)
{ {
Assert(IsA(a, MergePath));
Assert(IsA(b, MergePath));
if (!_equalNestPath((NestPath *) a, (NestPath *) b)) if (!_equalNestPath((NestPath *) a, (NestPath *) b))
return false; return false;
if (!equal(a->path_mergeclauses, b->path_mergeclauses)) if (!equal(a->path_mergeclauses, b->path_mergeclauses))
...@@ -439,12 +371,9 @@ _equalMergePath(MergePath *a, MergePath *b) ...@@ -439,12 +371,9 @@ _equalMergePath(MergePath *a, MergePath *b)
static bool static bool
_equalHashPath(HashPath *a, HashPath *b) _equalHashPath(HashPath *a, HashPath *b)
{ {
Assert(IsA(a, HashPath));
Assert(IsA(b, HashPath));
if (!_equalNestPath((NestPath *) a, (NestPath *) b)) if (!_equalNestPath((NestPath *) a, (NestPath *) b))
return false; return false;
if (!equal((a->path_hashclauses), (b->path_hashclauses))) if (!equal(a->path_hashclauses, b->path_hashclauses))
return false; return false;
if (!equal(a->outerhashkeys, b->outerhashkeys)) if (!equal(a->outerhashkeys, b->outerhashkeys))
return false; return false;
...@@ -456,9 +385,6 @@ _equalHashPath(HashPath *a, HashPath *b) ...@@ -456,9 +385,6 @@ _equalHashPath(HashPath *a, HashPath *b)
static bool static bool
_equalJoinKey(JoinKey *a, JoinKey *b) _equalJoinKey(JoinKey *a, JoinKey *b)
{ {
Assert(IsA(a, JoinKey));
Assert(IsA(b, JoinKey));
if (!equal(a->outer, b->outer)) if (!equal(a->outer, b->outer))
return false; return false;
if (!equal(a->inner, b->inner)) if (!equal(a->inner, b->inner))
...@@ -469,11 +395,6 @@ _equalJoinKey(JoinKey *a, JoinKey *b) ...@@ -469,11 +395,6 @@ _equalJoinKey(JoinKey *a, JoinKey *b)
static bool static bool
_equalMergeOrder(MergeOrder *a, MergeOrder *b) _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) if (a->join_operator != b->join_operator)
return false; return false;
if (a->left_operator != b->left_operator) if (a->left_operator != b->left_operator)
...@@ -490,9 +411,8 @@ _equalMergeOrder(MergeOrder *a, MergeOrder *b) ...@@ -490,9 +411,8 @@ _equalMergeOrder(MergeOrder *a, MergeOrder *b)
static bool static bool
_equalHashInfo(HashInfo *a, HashInfo *b) _equalHashInfo(HashInfo *a, HashInfo *b)
{ {
Assert(IsA(a, HashInfo)); if (!_equalJoinMethod((JoinMethod *) a, (JoinMethod *) b))
Assert(IsA(b, HashInfo)); return false;
if (a->hashop != b->hashop) if (a->hashop != b->hashop)
return false; return false;
return true; return true;
...@@ -500,13 +420,13 @@ _equalHashInfo(HashInfo *a, HashInfo *b) ...@@ -500,13 +420,13 @@ _equalHashInfo(HashInfo *a, HashInfo *b)
/* XXX This equality function is a quick hack, should be /* XXX This equality function is a quick hack, should be
* fixed to compare all fields. * 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 static bool
_equalIndexScan(IndexScan *a, IndexScan *b) _equalIndexScan(IndexScan *a, IndexScan *b)
{ {
Assert(IsA(a, IndexScan));
Assert(IsA(b, IndexScan));
/* /*
* if(a->scan.plan.cost != b->scan.plan.cost) return(false); * if(a->scan.plan.cost != b->scan.plan.cost) return(false);
*/ */
...@@ -537,8 +457,6 @@ _equalSubPlan(SubPlan *a, SubPlan *b) ...@@ -537,8 +457,6 @@ _equalSubPlan(SubPlan *a, SubPlan *b)
static bool static bool
_equalJoinInfo(JoinInfo *a, JoinInfo *b) _equalJoinInfo(JoinInfo *a, JoinInfo *b)
{ {
Assert(IsA(a, JoinInfo));
Assert(IsA(b, JoinInfo));
if (!equal(a->unjoined_relids, b->unjoined_relids)) if (!equal(a->unjoined_relids, b->unjoined_relids))
return false; return false;
if (!equal(a->jinfo_restrictinfo, b->jinfo_restrictinfo)) if (!equal(a->jinfo_restrictinfo, b->jinfo_restrictinfo))
...@@ -550,6 +468,45 @@ _equalJoinInfo(JoinInfo *a, JoinInfo *b) ...@@ -550,6 +468,45 @@ _equalJoinInfo(JoinInfo *a, JoinInfo *b)
return true; 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 * Stuff from execnodes.h
*/ */
...@@ -696,6 +653,32 @@ _equalTargetEntry(TargetEntry *a, TargetEntry *b) ...@@ -696,6 +653,32 @@ _equalTargetEntry(TargetEntry *a, TargetEntry *b)
return true; 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 * Stuff from pg_list.h
*/ */
...@@ -842,9 +825,10 @@ equal(void *a, void *b) ...@@ -842,9 +825,10 @@ equal(void *a, void *b)
List *lb = (List *) b; List *lb = (List *) b;
List *l; List *l;
if (a == NULL && b == NULL) /* Try to reject by length check before we grovel through
return true; * all the elements...
if (length(a) != length(b)) */
if (length(la) != length(lb))
return false; return false;
foreach(l, la) foreach(l, la)
{ {
...@@ -864,6 +848,12 @@ equal(void *a, void *b) ...@@ -864,6 +848,12 @@ equal(void *a, void *b)
case T_TargetEntry: case T_TargetEntry:
retval = _equalTargetEntry(a, b); retval = _equalTargetEntry(a, b);
break; break;
case T_CaseExpr:
retval = _equalCaseExpr(a, b);
break;
case T_CaseWhen:
retval = _equalCaseWhen(a, b);
break;
default: default:
elog(NOTICE, "equal: don't know whether nodes of type %d are equal", elog(NOTICE, "equal: don't know whether nodes of type %d are equal",
nodeTag(a)); nodeTag(a));
...@@ -876,25 +866,21 @@ equal(void *a, void *b) ...@@ -876,25 +866,21 @@ equal(void *a, void *b)
/* /*
* equali * equali
* compares two lists of integers * compares two lists of integers
*
* XXX temp hack. needs something like T_IntList
*/ */
static bool static bool
equali(List *a, List *b) equali(List *a, List *b)
{ {
List *la = (List *) a;
List *lb = (List *) b;
List *l; List *l;
if (a == NULL && b == NULL) foreach(l, a)
return true;
if (length(a) != length(b))
return false;
foreach(l, la)
{ {
if (lfirsti(l) != lfirsti(lb)) if (b == NIL)
return false;
if (lfirsti(l) != lfirsti(b))
return false; return false;
lb = lnext(lb); b = lnext(b);
} }
if (b != NIL)
return false;
return true; return true;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment