Add equal() funcs for Case nodes ... amazing we had not
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 29 Jul 1999 02:45:36 +0000 (02:45 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 29 Jul 1999 02:45:36 +0000 (02:45 +0000)
detected this omission before.  Miscellaneous other cleanups.

src/backend/nodes/equalfuncs.c

index 5560deaea53a5569099118f9a120ab7cf8efc1da..576601faf57021958405b59fced01cada4c1496a 100644 (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 $
  *
  *-------------------------------------------------------------------------
  */
 
 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)
-       return false;
-   if (a->functype != b->functype)
+   if (a->arrayelemtype != b->arrayelemtype)
        return false;
-   if (a->funcisindex != b->funcisindex)
+   /* We need not check arrayelemlength, arrayelembyval if types match */
+   if (a->arrayndim != b->arrayndim)
        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;
-   if (!equal(a->func_tlist, b->func_tlist))
+   if (a->arrayhigh.indx[0] != b->arrayhigh.indx[0])
        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;
+       if (lfirsti(l) != lfirsti(b))
            return false;
-       lb = lnext(lb);
+       b = lnext(b);
    }
+   if (b != NIL)
+       return false;
    return true;
 }