]> granicus.if.org Git - postgresql/blobdiff - src/backend/nodes/equalfuncs.c
Update copyrights to 2003.
[postgresql] / src / backend / nodes / equalfuncs.c
index 2ea41d6e522600cf7cf7690fa05a1d3a72f3ef90..a6b4889f74e69870c279a6c8a8c1ca8a0cc28e60 100644 (file)
@@ -3,39 +3,94 @@
  * equalfuncs.c
  *       Equality functions to compare node trees.
  *
- * NOTE: a general convention when copying or comparing plan nodes is
- * that we ignore the executor state subnode.  We do not need to look
- * at it because no current uses of copyObject() or equal() need to
- * deal with already-executing plan trees.     By leaving the state subnodes
- * out, we avoid needing to write copy/compare routines for all the
- * different executor state node types.
+ * NOTE: we currently support comparing all node types found in parse
+ * trees.  We do not support comparing executor state trees; there
+ * is no need for that, and no point in maintaining all the code that
+ * would be needed.  We also do not support comparing Path trees, mainly
+ * because the circular linkages between RelOptInfo and Path nodes can't
+ * be handled easily in a simple depth-first traversal.
  *
- * Currently, in fact, equal() doesn't know how to compare Plan nodes
- * at all, let alone their executor-state subnodes.  This will probably
- * need to be fixed someday, but presently there is no need to compare
- * plan trees.
+ * Currently, in fact, equal() doesn't know how to compare Plan trees
+ * either.     This might need to be fixed someday.
  *
  *
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.110 2002/02/24 20:20:20 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.206 2003/08/04 02:39:59 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "postgres.h"
 
-#include "nodes/plannodes.h"
+#include "nodes/params.h"
+#include "nodes/parsenodes.h"
 #include "nodes/relation.h"
 #include "utils/datum.h"
 
 
+/*
+ * Macros to simplify comparison of different kinds of fields. Use these
+ * wherever possible to reduce the chance for silly typos.     Note that these
+ * hard-wire the convention that the local variables in an Equal routine are
+ * named 'a' and 'b'.
+ */
+
+/* Compare a simple scalar field (int, float, bool, enum, etc) */
+#define COMPARE_SCALAR_FIELD(fldname) \
+       do { \
+               if (a->fldname != b->fldname) \
+                       return false; \
+       } while (0)
+
+/* Compare a field that is a pointer to some kind of Node or Node tree */
+#define COMPARE_NODE_FIELD(fldname) \
+       do { \
+               if (!equal(a->fldname, b->fldname)) \
+                       return false; \
+       } while (0)
+
+/* Compare a field that is a pointer to a list of integers */
+#define COMPARE_INTLIST_FIELD(fldname) \
+       do { \
+               if (!equali(a->fldname, b->fldname)) \
+                       return false; \
+       } while (0)
+
+/* Compare a field that is a pointer to a list of Oids */
+#define COMPARE_OIDLIST_FIELD(fldname) \
+       do { \
+               if (!equalo(a->fldname, b->fldname)) \
+                       return false; \
+       } while (0)
+
+/* Compare a field that is a pointer to a Bitmapset */
+#define COMPARE_BITMAPSET_FIELD(fldname) \
+       do { \
+               if (!bms_equal(a->fldname, b->fldname)) \
+                       return false; \
+       } while (0)
+
+/* Compare a field that is a pointer to a C string, or perhaps NULL */
+#define COMPARE_STRING_FIELD(fldname) \
+       do { \
+               if (!equalstr(a->fldname, b->fldname)) \
+                       return false; \
+       } while (0)
+
 /* Macro for comparing string fields that might be NULL */
 #define equalstr(a, b) \
        (((a) != NULL && (b) != NULL) ? (strcmp(a, b) == 0) : (a) == (b))
 
+/* Compare a field that is a pointer to a simple palloc'd object of size sz */
+#define COMPARE_POINTER_FIELD(fldname, sz) \
+       do { \
+               if (memcmp(a->fldname, b->fldname, (sz)) != 0) \
+                       return false; \
+       } while (0)
+
 
 /*
  *     Stuff from primnodes.h
 static bool
 _equalResdom(Resdom *a, Resdom *b)
 {
-       if (a->resno != b->resno)
-               return false;
-       if (a->restype != b->restype)
-               return false;
-       if (a->restypmod != b->restypmod)
-               return false;
-       if (!equalstr(a->resname, b->resname))
-               return false;
-       if (a->ressortgroupref != b->ressortgroupref)
-               return false;
-       if (a->reskey != b->reskey)
-               return false;
-       if (a->reskeyop != b->reskeyop)
-               return false;
-       /* we ignore resjunk flag ... is this correct? */
+       COMPARE_SCALAR_FIELD(resno);
+       COMPARE_SCALAR_FIELD(restype);
+       COMPARE_SCALAR_FIELD(restypmod);
+       COMPARE_STRING_FIELD(resname);
+       COMPARE_SCALAR_FIELD(ressortgroupref);
+       COMPARE_SCALAR_FIELD(resorigtbl);
+       COMPARE_SCALAR_FIELD(resorigcol);
+       COMPARE_SCALAR_FIELD(resjunk);
 
        return true;
 }
 
 static bool
-_equalFjoin(Fjoin *a, Fjoin *b)
+_equalAlias(Alias *a, Alias *b)
 {
-       int                     nNodes;
-
-       if (a->fj_initialized != b->fj_initialized)
-               return false;
-       if (a->fj_nNodes != b->fj_nNodes)
-               return false;
-       if (!equal(a->fj_innerNode, b->fj_innerNode))
-               return false;
-
-       nNodes = a->fj_nNodes;
-       if (memcmp(a->fj_results, b->fj_results, nNodes * sizeof(Datum)) != 0)
-               return false;
-       if (memcmp(a->fj_alwaysDone, b->fj_alwaysDone, nNodes * sizeof(bool)) != 0)
-               return false;
+       COMPARE_STRING_FIELD(aliasname);
+       COMPARE_NODE_FIELD(colnames);
 
        return true;
 }
 
 static bool
-_equalExpr(Expr *a, Expr *b)
+_equalRangeVar(RangeVar *a, RangeVar *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))
-               return false;
-       if (!equal(a->args, b->args))
-               return false;
+       COMPARE_STRING_FIELD(catalogname);
+       COMPARE_STRING_FIELD(schemaname);
+       COMPARE_STRING_FIELD(relname);
+       COMPARE_SCALAR_FIELD(inhOpt);
+       COMPARE_SCALAR_FIELD(istemp);
+       COMPARE_NODE_FIELD(alias);
 
        return true;
 }
 
-static bool
-_equalVar(Var *a, Var *b)
-{
-       if (a->varno != b->varno)
-               return false;
-       if (a->varattno != b->varattno)
-               return false;
-       if (a->vartype != b->vartype)
-               return false;
-       if (a->vartypmod != b->vartypmod)
-               return false;
-       if (a->varlevelsup != b->varlevelsup)
-               return false;
-       if (a->varnoold != b->varnoold)
-               return false;
-       if (a->varoattno != b->varoattno)
-               return false;
-
-       return true;
-}
+/*
+ * We don't need an _equalExpr because Expr is an abstract supertype which
+ * should never actually get instantiated.     Also, since it has no common
+ * fields except NodeTag, there's no need for a helper routine to factor
+ * out comparing the common fields...
+ */
 
 static bool
-_equalOper(Oper *a, Oper *b)
+_equalVar(Var *a, Var *b)
 {
-       if (a->opno != b->opno)
-               return false;
-       if (a->opresulttype != b->opresulttype)
-               return false;
-
-       /*
-        * We do not examine opid 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.
-        *
-        * (Besides, op_fcache is executor state, which we don't check --- see
-        * notes at head of file.)
-        *
-        * It's probably not really necessary to check opresulttype either...
-        */
+       COMPARE_SCALAR_FIELD(varno);
+       COMPARE_SCALAR_FIELD(varattno);
+       COMPARE_SCALAR_FIELD(vartype);
+       COMPARE_SCALAR_FIELD(vartypmod);
+       COMPARE_SCALAR_FIELD(varlevelsup);
+       COMPARE_SCALAR_FIELD(varnoold);
+       COMPARE_SCALAR_FIELD(varoattno);
 
        return true;
 }
@@ -148,15 +157,10 @@ _equalOper(Oper *a, Oper *b)
 static bool
 _equalConst(Const *a, Const *b)
 {
-       if (a->consttype != b->consttype)
-               return false;
-       if (a->constlen != b->constlen)
-               return false;
-       if (a->constisnull != b->constisnull)
-               return false;
-       if (a->constbyval != b->constbyval)
-               return false;
-       /* XXX What about constisset and constiscast? */
+       COMPARE_SCALAR_FIELD(consttype);
+       COMPARE_SCALAR_FIELD(constlen);
+       COMPARE_SCALAR_FIELD(constisnull);
+       COMPARE_SCALAR_FIELD(constbyval);
 
        /*
         * We treat all NULL constants of the same type as equal. Someday this
@@ -172,33 +176,20 @@ _equalConst(Const *a, Const *b)
 static bool
 _equalParam(Param *a, Param *b)
 {
-       if (a->paramkind != b->paramkind)
-               return false;
-       if (a->paramtype != b->paramtype)
-               return false;
+       COMPARE_SCALAR_FIELD(paramkind);
+       COMPARE_SCALAR_FIELD(paramtype);
 
        switch (a->paramkind)
        {
                case PARAM_NAMED:
-               case PARAM_NEW:
-               case PARAM_OLD:
-                       if (strcmp(a->paramname, b->paramname) != 0)
-                               return false;
+                       COMPARE_STRING_FIELD(paramname);
                        break;
                case PARAM_NUM:
                case PARAM_EXEC:
-                       if (a->paramid != b->paramid)
-                               return false;
-                       break;
-               case PARAM_INVALID:
-
-                       /*
-                        * XXX: Hmmm... What are we supposed to return in this case ??
-                        */
-                       return true;
+                       COMPARE_SCALAR_FIELD(paramid);
                        break;
                default:
-                       elog(ERROR, "_equalParam: Invalid paramkind value: %d",
+                       elog(ERROR, "unrecognized paramkind: %d",
                                 a->paramkind);
        }
 
@@ -206,420 +197,438 @@ _equalParam(Param *a, Param *b)
 }
 
 static bool
-_equalFunc(Func *a, Func *b)
+_equalAggref(Aggref *a, Aggref *b)
 {
-       if (a->funcid != b->funcid)
-               return false;
-       if (a->functype != b->functype)
-               return false;
-       /* Note we do not look at func_fcache; see notes for _equalOper */
+       COMPARE_SCALAR_FIELD(aggfnoid);
+       COMPARE_SCALAR_FIELD(aggtype);
+       COMPARE_NODE_FIELD(target);
+       COMPARE_SCALAR_FIELD(agglevelsup);
+       COMPARE_SCALAR_FIELD(aggstar);
+       COMPARE_SCALAR_FIELD(aggdistinct);
 
        return true;
 }
 
 static bool
-_equalAggref(Aggref *a, Aggref *b)
+_equalArrayRef(ArrayRef *a, ArrayRef *b)
 {
-       if (strcmp(a->aggname, b->aggname) != 0)
-               return false;
-       if (a->basetype != b->basetype)
-               return false;
-       if (a->aggtype != b->aggtype)
-               return false;
-       if (!equal(a->target, b->target))
-               return false;
-       if (a->aggstar != b->aggstar)
-               return false;
-       if (a->aggdistinct != b->aggdistinct)
-               return false;
-       /* ignore aggno, which is only a private field for the executor */
+       COMPARE_SCALAR_FIELD(refrestype);
+       COMPARE_SCALAR_FIELD(refarraytype);
+       COMPARE_SCALAR_FIELD(refelemtype);
+       COMPARE_NODE_FIELD(refupperindexpr);
+       COMPARE_NODE_FIELD(reflowerindexpr);
+       COMPARE_NODE_FIELD(refexpr);
+       COMPARE_NODE_FIELD(refassgnexpr);
+
        return true;
 }
 
 static bool
-_equalSubLink(SubLink *a, SubLink *b)
+_equalFuncExpr(FuncExpr * a, FuncExpr * b)
 {
-       if (a->subLinkType != b->subLinkType)
-               return false;
-       if (a->useor != b->useor)
-               return false;
-       if (!equal(a->lefthand, b->lefthand))
-               return false;
-       if (!equal(a->oper, b->oper))
-               return false;
-       if (!equal(a->subselect, b->subselect))
+       COMPARE_SCALAR_FIELD(funcid);
+       COMPARE_SCALAR_FIELD(funcresulttype);
+       COMPARE_SCALAR_FIELD(funcretset);
+
+       /*
+        * Special-case COERCE_DONTCARE, so that pathkeys can build coercion
+        * nodes that are equal() to both explicit and implicit coercions.
+        */
+       if (a->funcformat != b->funcformat &&
+               a->funcformat != COERCE_DONTCARE &&
+               b->funcformat != COERCE_DONTCARE)
                return false;
+
+       COMPARE_NODE_FIELD(args);
+
        return true;
 }
 
 static bool
-_equalArrayRef(ArrayRef *a, ArrayRef *b)
+_equalOpExpr(OpExpr * a, OpExpr * 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))
+       COMPARE_SCALAR_FIELD(opno);
+
+       /*
+        * Special-case opfuncid: it is allowable for it to differ if one node
+        * contains zero and the other doesn't.  This just means that the one
+        * node isn't as far along in the parse/plan pipeline and hasn't had
+        * the opfuncid cache filled yet.
+        */
+       if (a->opfuncid != b->opfuncid &&
+               a->opfuncid != 0 &&
+               b->opfuncid != 0)
                return false;
-       return equal(a->refassgnexpr, b->refassgnexpr);
+
+       COMPARE_SCALAR_FIELD(opresulttype);
+       COMPARE_SCALAR_FIELD(opretset);
+       COMPARE_NODE_FIELD(args);
+
+       return true;
 }
 
 static bool
-_equalFieldSelect(FieldSelect *a, FieldSelect *b)
+_equalDistinctExpr(DistinctExpr * a, DistinctExpr * b)
 {
-       if (!equal(a->arg, b->arg))
-               return false;
-       if (a->fieldnum != b->fieldnum)
-               return false;
-       if (a->resulttype != b->resulttype)
-               return false;
-       if (a->resulttypmod != b->resulttypmod)
+       COMPARE_SCALAR_FIELD(opno);
+
+       /*
+        * Special-case opfuncid: it is allowable for it to differ if one node
+        * contains zero and the other doesn't.  This just means that the one
+        * node isn't as far along in the parse/plan pipeline and hasn't had
+        * the opfuncid cache filled yet.
+        */
+       if (a->opfuncid != b->opfuncid &&
+               a->opfuncid != 0 &&
+               b->opfuncid != 0)
                return false;
+
+       COMPARE_SCALAR_FIELD(opresulttype);
+       COMPARE_SCALAR_FIELD(opretset);
+       COMPARE_NODE_FIELD(args);
+
        return true;
 }
 
 static bool
-_equalRelabelType(RelabelType *a, RelabelType *b)
+_equalScalarArrayOpExpr(ScalarArrayOpExpr * a, ScalarArrayOpExpr * b)
 {
-       if (!equal(a->arg, b->arg))
-               return false;
-       if (a->resulttype != b->resulttype)
-               return false;
-       if (a->resulttypmod != b->resulttypmod)
+       COMPARE_SCALAR_FIELD(opno);
+
+       /*
+        * Special-case opfuncid: it is allowable for it to differ if one node
+        * contains zero and the other doesn't.  This just means that the one
+        * node isn't as far along in the parse/plan pipeline and hasn't had
+        * the opfuncid cache filled yet.
+        */
+       if (a->opfuncid != b->opfuncid &&
+               a->opfuncid != 0 &&
+               b->opfuncid != 0)
                return false;
+
+       COMPARE_SCALAR_FIELD(useOr);
+       COMPARE_NODE_FIELD(args);
+
        return true;
 }
 
 static bool
-_equalRangeTblRef(RangeTblRef *a, RangeTblRef *b)
+_equalBoolExpr(BoolExpr * a, BoolExpr * b)
 {
-       if (a->rtindex != b->rtindex)
-               return false;
+       COMPARE_SCALAR_FIELD(boolop);
+       COMPARE_NODE_FIELD(args);
 
        return true;
 }
 
 static bool
-_equalFromExpr(FromExpr *a, FromExpr *b)
+_equalSubLink(SubLink *a, SubLink *b)
 {
-       if (!equal(a->fromlist, b->fromlist))
-               return false;
-       if (!equal(a->quals, b->quals))
-               return false;
+       COMPARE_SCALAR_FIELD(subLinkType);
+       COMPARE_SCALAR_FIELD(useOr);
+       COMPARE_NODE_FIELD(lefthand);
+       COMPARE_NODE_FIELD(operName);
+       COMPARE_OIDLIST_FIELD(operOids);
+       COMPARE_NODE_FIELD(subselect);
 
        return true;
 }
 
 static bool
-_equalJoinExpr(JoinExpr *a, JoinExpr *b)
+_equalSubPlan(SubPlan *a, SubPlan *b)
 {
-       if (a->jointype != b->jointype)
-               return false;
-       if (a->isNatural != b->isNatural)
-               return false;
-       if (!equal(a->larg, b->larg))
-               return false;
-       if (!equal(a->rarg, b->rarg))
-               return false;
-       if (!equal(a->using, b->using))
-               return false;
-       if (!equal(a->quals, b->quals))
-               return false;
-       if (!equal(a->alias, b->alias))
-               return false;
-       if (!equal(a->colnames, b->colnames))
-               return false;
-       if (!equal(a->colvars, b->colvars))
-               return false;
+       COMPARE_SCALAR_FIELD(subLinkType);
+       COMPARE_SCALAR_FIELD(useOr);
+       COMPARE_NODE_FIELD(exprs);
+       COMPARE_INTLIST_FIELD(paramIds);
+       /* should compare plans, but have to settle for comparing plan IDs */
+       COMPARE_SCALAR_FIELD(plan_id);
+       COMPARE_NODE_FIELD(rtable);
+       COMPARE_SCALAR_FIELD(useHashTable);
+       COMPARE_SCALAR_FIELD(unknownEqFalse);
+       COMPARE_INTLIST_FIELD(setParam);
+       COMPARE_INTLIST_FIELD(parParam);
+       COMPARE_NODE_FIELD(args);
 
        return true;
 }
 
-/*
- * Stuff from relation.h
- */
-
 static bool
-_equalRelOptInfo(RelOptInfo *a, RelOptInfo *b)
+_equalFieldSelect(FieldSelect *a, FieldSelect *b)
 {
-       /*
-        * We treat RelOptInfos as equal if they refer to the same base rels
-        * joined in the same order.  Is this appropriate/sufficient?
-        */
-       return equali(a->relids, b->relids);
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_SCALAR_FIELD(fieldnum);
+       COMPARE_SCALAR_FIELD(resulttype);
+       COMPARE_SCALAR_FIELD(resulttypmod);
+
+       return true;
 }
 
 static bool
-_equalIndexOptInfo(IndexOptInfo *a, IndexOptInfo *b)
+_equalRelabelType(RelabelType *a, RelabelType *b)
 {
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_SCALAR_FIELD(resulttype);
+       COMPARE_SCALAR_FIELD(resulttypmod);
+
        /*
-        * We treat IndexOptInfos as equal if they refer to the same index. Is
-        * this sufficient?
+        * Special-case COERCE_DONTCARE, so that pathkeys can build coercion
+        * nodes that are equal() to both explicit and implicit coercions.
         */
-       if (a->indexoid != b->indexoid)
+       if (a->relabelformat != b->relabelformat &&
+               a->relabelformat != COERCE_DONTCARE &&
+               b->relabelformat != COERCE_DONTCARE)
                return false;
+
        return true;
 }
 
 static bool
-_equalPathKeyItem(PathKeyItem *a, PathKeyItem *b)
+_equalCaseExpr(CaseExpr *a, CaseExpr *b)
 {
-       if (a->sortop != b->sortop)
-               return false;
-       if (!equal(a->key, b->key))
-               return false;
+       COMPARE_SCALAR_FIELD(casetype);
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_NODE_FIELD(args);
+       COMPARE_NODE_FIELD(defresult);
+
        return true;
 }
 
 static bool
-_equalPath(Path *a, Path *b)
+_equalCaseWhen(CaseWhen *a, CaseWhen *b)
 {
-       if (a->pathtype != b->pathtype)
-               return false;
-       if (!equal(a->parent, b->parent))
-               return false;
+       COMPARE_NODE_FIELD(expr);
+       COMPARE_NODE_FIELD(result);
 
-       /*
-        * do not check path costs, since they may not be set yet, and being
-        * float values there are roundoff error issues anyway...
-        */
-       if (!equal(a->pathkeys, b->pathkeys))
-               return false;
        return true;
 }
 
 static bool
-_equalIndexPath(IndexPath *a, IndexPath *b)
+_equalArrayExpr(ArrayExpr * a, ArrayExpr * b)
 {
-       if (!_equalPath((Path *) a, (Path *) b))
-               return false;
-       if (!equal(a->indexinfo, b->indexinfo))
-               return false;
-       if (!equal(a->indexqual, b->indexqual))
-               return false;
-       if (a->indexscandir != b->indexscandir)
-               return false;
-       if (!equali(a->joinrelids, b->joinrelids))
-               return false;
-       if (a->alljoinquals != b->alljoinquals)
-               return false;
+       COMPARE_SCALAR_FIELD(array_typeid);
+       COMPARE_SCALAR_FIELD(element_typeid);
+       COMPARE_NODE_FIELD(elements);
+       COMPARE_SCALAR_FIELD(ndims);
 
-       /*
-        * Skip 'rows' because of possibility of floating-point roundoff
-        * error. It should be derivable from the other fields anyway.
-        */
        return true;
 }
 
 static bool
-_equalTidPath(TidPath *a, TidPath *b)
+_equalCoalesceExpr(CoalesceExpr * a, CoalesceExpr * b)
 {
-       if (!_equalPath((Path *) a, (Path *) b))
-               return false;
-       if (!equal(a->tideval, b->tideval))
-               return false;
-       if (!equali(a->unjoined_relids, b->unjoined_relids))
-               return false;
+       COMPARE_SCALAR_FIELD(coalescetype);
+       COMPARE_NODE_FIELD(args);
+
        return true;
 }
 
 static bool
-_equalAppendPath(AppendPath *a, AppendPath *b)
+_equalNullIfExpr(NullIfExpr * a, NullIfExpr * b)
 {
-       if (!_equalPath((Path *) a, (Path *) b))
-               return false;
-       if (!equal(a->subpaths, b->subpaths))
+       COMPARE_SCALAR_FIELD(opno);
+
+       /*
+        * Special-case opfuncid: it is allowable for it to differ if one node
+        * contains zero and the other doesn't.  This just means that the one
+        * node isn't as far along in the parse/plan pipeline and hasn't had
+        * the opfuncid cache filled yet.
+        */
+       if (a->opfuncid != b->opfuncid &&
+               a->opfuncid != 0 &&
+               b->opfuncid != 0)
                return false;
+
+       COMPARE_SCALAR_FIELD(opresulttype);
+       COMPARE_SCALAR_FIELD(opretset);
+       COMPARE_NODE_FIELD(args);
+
        return true;
 }
 
 static bool
-_equalJoinPath(JoinPath *a, JoinPath *b)
+_equalNullTest(NullTest *a, NullTest *b)
 {
-       if (!_equalPath((Path *) a, (Path *) b))
-               return false;
-       if (a->jointype != b->jointype)
-               return false;
-       if (!equal(a->outerjoinpath, b->outerjoinpath))
-               return false;
-       if (!equal(a->innerjoinpath, b->innerjoinpath))
-               return false;
-       if (!equal(a->joinrestrictinfo, b->joinrestrictinfo))
-               return false;
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_SCALAR_FIELD(nulltesttype);
+
        return true;
 }
 
 static bool
-_equalNestPath(NestPath *a, NestPath *b)
+_equalBooleanTest(BooleanTest *a, BooleanTest *b)
 {
-       if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
-               return false;
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_SCALAR_FIELD(booltesttype);
+
        return true;
 }
 
 static bool
-_equalMergePath(MergePath *a, MergePath *b)
+_equalCoerceToDomain(CoerceToDomain * a, CoerceToDomain * b)
 {
-       if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
-               return false;
-       if (!equal(a->path_mergeclauses, b->path_mergeclauses))
-               return false;
-       if (!equal(a->outersortkeys, b->outersortkeys))
-               return false;
-       if (!equal(a->innersortkeys, b->innersortkeys))
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_SCALAR_FIELD(resulttype);
+       COMPARE_SCALAR_FIELD(resulttypmod);
+
+       /*
+        * Special-case COERCE_DONTCARE, so that pathkeys can build coercion
+        * nodes that are equal() to both explicit and implicit coercions.
+        */
+       if (a->coercionformat != b->coercionformat &&
+               a->coercionformat != COERCE_DONTCARE &&
+               b->coercionformat != COERCE_DONTCARE)
                return false;
+
        return true;
 }
 
 static bool
-_equalHashPath(HashPath *a, HashPath *b)
+_equalCoerceToDomainValue(CoerceToDomainValue * a, CoerceToDomainValue * b)
 {
-       if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
-               return false;
-       if (!equal(a->path_hashclauses, b->path_hashclauses))
-               return false;
+       COMPARE_SCALAR_FIELD(typeId);
+       COMPARE_SCALAR_FIELD(typeMod);
+
        return true;
 }
 
 static bool
-_equalSubPlan(SubPlan *a, SubPlan *b)
+_equalSetToDefault(SetToDefault * a, SetToDefault * b)
 {
-       /* should compare plans, but have to settle for comparing plan IDs */
-       if (a->plan_id != b->plan_id)
-               return false;
-
-       if (!equal(a->rtable, b->rtable))
-               return false;
-
-       if (!equal(a->sublink, b->sublink))
-               return false;
+       COMPARE_SCALAR_FIELD(typeId);
+       COMPARE_SCALAR_FIELD(typeMod);
 
        return true;
 }
 
 static bool
-_equalRestrictInfo(RestrictInfo *a, RestrictInfo *b)
+_equalTargetEntry(TargetEntry *a, TargetEntry *b)
 {
-       if (!equal(a->clause, b->clause))
-               return false;
-       if (a->ispusheddown != b->ispusheddown)
-               return false;
+       COMPARE_NODE_FIELD(resdom);
+       COMPARE_NODE_FIELD(expr);
 
-       /*
-        * We ignore eval_cost, this_selec, left/right_pathkey, and
-        * left/right_bucketsize, since they may not be set yet, and should be
-        * derivable from the clause anyway.  Probably it's not really
-        * necessary to compare any of these remaining fields ...
-        */
-       if (!equal(a->subclauseindices, b->subclauseindices))
-               return false;
-       if (a->mergejoinoperator != b->mergejoinoperator)
-               return false;
-       if (a->left_sortop != b->left_sortop)
-               return false;
-       if (a->right_sortop != b->right_sortop)
-               return false;
-       if (a->hashjoinoperator != b->hashjoinoperator)
-               return false;
        return true;
 }
 
 static bool
-_equalJoinInfo(JoinInfo *a, JoinInfo *b)
+_equalRangeTblRef(RangeTblRef *a, RangeTblRef *b)
 {
-       if (!equali(a->unjoined_relids, b->unjoined_relids))
-               return false;
-       if (!equal(a->jinfo_restrictinfo, b->jinfo_restrictinfo))
-               return false;
+       COMPARE_SCALAR_FIELD(rtindex);
+
        return true;
 }
 
 static bool
-_equalIter(Iter *a, Iter *b)
+_equalJoinExpr(JoinExpr *a, JoinExpr *b)
 {
-       return equal(a->iterexpr, b->iterexpr);
+       COMPARE_SCALAR_FIELD(jointype);
+       COMPARE_SCALAR_FIELD(isNatural);
+       COMPARE_NODE_FIELD(larg);
+       COMPARE_NODE_FIELD(rarg);
+       COMPARE_NODE_FIELD(using);
+       COMPARE_NODE_FIELD(quals);
+       COMPARE_NODE_FIELD(alias);
+       COMPARE_SCALAR_FIELD(rtindex);
+
+       return true;
 }
 
 static bool
-_equalStream(Stream *a, Stream *b)
+_equalFromExpr(FromExpr *a, FromExpr *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);
+       COMPARE_NODE_FIELD(fromlist);
+       COMPARE_NODE_FIELD(quals);
+
+       return true;
 }
 
+
 /*
- * Stuff from parsenodes.h
+ * Stuff from relation.h
  */
 
 static bool
-_equalQuery(Query *a, Query *b)
+_equalPathKeyItem(PathKeyItem *a, PathKeyItem *b)
 {
-       if (a->commandType != b->commandType)
-               return false;
-       if (!equal(a->utilityStmt, b->utilityStmt))
-               return false;
-       if (a->resultRelation != b->resultRelation)
-               return false;
-       if (!equalstr(a->into, b->into))
-               return false;
-       if (a->isPortal != b->isPortal)
-               return false;
-       if (a->isBinary != b->isBinary)
-               return false;
-       if (a->isTemp != b->isTemp)
-               return false;
-       if (a->hasAggs != b->hasAggs)
-               return false;
-       if (a->hasSubLinks != b->hasSubLinks)
-               return false;
-       if (!equal(a->rtable, b->rtable))
-               return false;
-       if (!equal(a->jointree, b->jointree))
-               return false;
-       if (!equali(a->rowMarks, b->rowMarks))
-               return false;
-       if (!equal(a->targetList, b->targetList))
-               return false;
-       if (!equal(a->groupClause, b->groupClause))
-               return false;
-       if (!equal(a->havingQual, b->havingQual))
-               return false;
-       if (!equal(a->distinctClause, b->distinctClause))
-               return false;
-       if (!equal(a->sortClause, b->sortClause))
-               return false;
-       if (!equal(a->limitOffset, b->limitOffset))
-               return false;
-       if (!equal(a->limitCount, b->limitCount))
-               return false;
-       if (!equal(a->setOperations, b->setOperations))
-               return false;
-       if (!equali(a->resultRelations, b->resultRelations))
-               return false;
+       COMPARE_NODE_FIELD(key);
+       COMPARE_SCALAR_FIELD(sortop);
+
+       return true;
+}
+
+static bool
+_equalRestrictInfo(RestrictInfo *a, RestrictInfo *b)
+{
+       COMPARE_NODE_FIELD(clause);
+       COMPARE_SCALAR_FIELD(ispusheddown);
+
+       /*
+        * We ignore subclauseindices, eval_cost, this_selec,
+        * left/right_relids, left/right_pathkey, and left/right_bucketsize,
+        * since they may not be set yet, and should be derivable from the
+        * clause anyway.  Probably it's not really necessary to compare any
+        * of these remaining fields ...
+        */
+       COMPARE_SCALAR_FIELD(mergejoinoperator);
+       COMPARE_SCALAR_FIELD(left_sortop);
+       COMPARE_SCALAR_FIELD(right_sortop);
+       COMPARE_SCALAR_FIELD(hashjoinoperator);
+
+       return true;
+}
+
+static bool
+_equalJoinInfo(JoinInfo *a, JoinInfo *b)
+{
+       COMPARE_BITMAPSET_FIELD(unjoined_relids);
+       COMPARE_NODE_FIELD(jinfo_restrictinfo);
+
+       return true;
+}
+
+static bool
+_equalInClauseInfo(InClauseInfo * a, InClauseInfo * b)
+{
+       COMPARE_BITMAPSET_FIELD(lefthand);
+       COMPARE_BITMAPSET_FIELD(righthand);
+       COMPARE_NODE_FIELD(sub_targetlist);
+
+       return true;
+}
+
+
+/*
+ * Stuff from parsenodes.h
+ */
+
+static bool
+_equalQuery(Query *a, Query *b)
+{
+       COMPARE_SCALAR_FIELD(commandType);
+       COMPARE_SCALAR_FIELD(querySource);
+       COMPARE_SCALAR_FIELD(canSetTag);
+       COMPARE_NODE_FIELD(utilityStmt);
+       COMPARE_SCALAR_FIELD(resultRelation);
+       COMPARE_NODE_FIELD(into);
+       COMPARE_SCALAR_FIELD(hasAggs);
+       COMPARE_SCALAR_FIELD(hasSubLinks);
+       COMPARE_NODE_FIELD(rtable);
+       COMPARE_NODE_FIELD(jointree);
+       COMPARE_INTLIST_FIELD(rowMarks);
+       COMPARE_NODE_FIELD(targetList);
+       COMPARE_NODE_FIELD(groupClause);
+       COMPARE_NODE_FIELD(havingQual);
+       COMPARE_NODE_FIELD(distinctClause);
+       COMPARE_NODE_FIELD(sortClause);
+       COMPARE_NODE_FIELD(limitOffset);
+       COMPARE_NODE_FIELD(limitCount);
+       COMPARE_NODE_FIELD(setOperations);
+       COMPARE_INTLIST_FIELD(resultRelations);
+       COMPARE_NODE_FIELD(in_info_list);
+       COMPARE_SCALAR_FIELD(hasJoinRTEs);
 
        /*
-        * We do not check the internal-to-the-planner fields: base_rel_list,
+        * We do not check the other planner internal fields: base_rel_list,
         * other_rel_list, join_rel_list, equi_key_list, query_pathkeys. They
         * might not be set yet, and in any case they should be derivable from
         * the other fields.
@@ -630,14 +639,10 @@ _equalQuery(Query *a, Query *b)
 static bool
 _equalInsertStmt(InsertStmt *a, InsertStmt *b)
 {
-       if (!equalstr(a->relname, b->relname))
-               return false;
-       if (!equal(a->cols, b->cols))
-               return false;
-       if (!equal(a->targetList, b->targetList))
-               return false;
-       if (!equal(a->selectStmt, b->selectStmt))
-               return false;
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_NODE_FIELD(cols);
+       COMPARE_NODE_FIELD(targetList);
+       COMPARE_NODE_FIELD(selectStmt);
 
        return true;
 }
@@ -645,12 +650,8 @@ _equalInsertStmt(InsertStmt *a, InsertStmt *b)
 static bool
 _equalDeleteStmt(DeleteStmt *a, DeleteStmt *b)
 {
-       if (!equalstr(a->relname, b->relname))
-               return false;
-       if (!equal(a->whereClause, b->whereClause))
-               return false;
-       if (a->inhOpt != b->inhOpt)
-               return false;
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_NODE_FIELD(whereClause);
 
        return true;
 }
@@ -658,16 +659,10 @@ _equalDeleteStmt(DeleteStmt *a, DeleteStmt *b)
 static bool
 _equalUpdateStmt(UpdateStmt *a, UpdateStmt *b)
 {
-       if (!equalstr(a->relname, b->relname))
-               return false;
-       if (!equal(a->targetList, b->targetList))
-               return false;
-       if (!equal(a->whereClause, b->whereClause))
-               return false;
-       if (!equal(a->fromClause, b->fromClause))
-               return false;
-       if (a->inhOpt != b->inhOpt)
-               return false;
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_NODE_FIELD(targetList);
+       COMPARE_NODE_FIELD(whereClause);
+       COMPARE_NODE_FIELD(fromClause);
 
        return true;
 }
@@ -675,44 +670,22 @@ _equalUpdateStmt(UpdateStmt *a, UpdateStmt *b)
 static bool
 _equalSelectStmt(SelectStmt *a, SelectStmt *b)
 {
-       if (!equal(a->distinctClause, b->distinctClause))
-               return false;
-       if (!equalstr(a->into, b->into))
-               return false;
-       if (a->istemp != b->istemp)
-               return false;
-       if (!equal(a->intoColNames, b->intoColNames))
-               return false;
-       if (!equal(a->targetList, b->targetList))
-               return false;
-       if (!equal(a->fromClause, b->fromClause))
-               return false;
-       if (!equal(a->whereClause, b->whereClause))
-               return false;
-       if (!equal(a->groupClause, b->groupClause))
-               return false;
-       if (!equal(a->havingClause, b->havingClause))
-               return false;
-       if (!equal(a->sortClause, b->sortClause))
-               return false;
-       if (!equalstr(a->portalname, b->portalname))
-               return false;
-       if (a->binary != b->binary)
-               return false;
-       if (!equal(a->limitOffset, b->limitOffset))
-               return false;
-       if (!equal(a->limitCount, b->limitCount))
-               return false;
-       if (!equal(a->forUpdate, b->forUpdate))
-               return false;
-       if (a->op != b->op)
-               return false;
-       if (a->all != b->all)
-               return false;
-       if (!equal(a->larg, b->larg))
-               return false;
-       if (!equal(a->rarg, b->rarg))
-               return false;
+       COMPARE_NODE_FIELD(distinctClause);
+       COMPARE_NODE_FIELD(into);
+       COMPARE_NODE_FIELD(intoColNames);
+       COMPARE_NODE_FIELD(targetList);
+       COMPARE_NODE_FIELD(fromClause);
+       COMPARE_NODE_FIELD(whereClause);
+       COMPARE_NODE_FIELD(groupClause);
+       COMPARE_NODE_FIELD(havingClause);
+       COMPARE_NODE_FIELD(sortClause);
+       COMPARE_NODE_FIELD(limitOffset);
+       COMPARE_NODE_FIELD(limitCount);
+       COMPARE_NODE_FIELD(forUpdate);
+       COMPARE_SCALAR_FIELD(op);
+       COMPARE_SCALAR_FIELD(all);
+       COMPARE_NODE_FIELD(larg);
+       COMPARE_NODE_FIELD(rarg);
 
        return true;
 }
@@ -720,16 +693,11 @@ _equalSelectStmt(SelectStmt *a, SelectStmt *b)
 static bool
 _equalSetOperationStmt(SetOperationStmt *a, SetOperationStmt *b)
 {
-       if (a->op != b->op)
-               return false;
-       if (a->all != b->all)
-               return false;
-       if (!equal(a->larg, b->larg))
-               return false;
-       if (!equal(a->rarg, b->rarg))
-               return false;
-       if (!equali(a->colTypes, b->colTypes))
-               return false;
+       COMPARE_SCALAR_FIELD(op);
+       COMPARE_SCALAR_FIELD(all);
+       COMPARE_NODE_FIELD(larg);
+       COMPARE_NODE_FIELD(rarg);
+       COMPARE_OIDLIST_FIELD(colTypes);
 
        return true;
 }
@@ -737,18 +705,23 @@ _equalSetOperationStmt(SetOperationStmt *a, SetOperationStmt *b)
 static bool
 _equalAlterTableStmt(AlterTableStmt *a, AlterTableStmt *b)
 {
-       if (a->subtype != b->subtype)
-               return false;
-       if (!equalstr(a->relname, b->relname))
-               return false;
-       if (a->inhOpt != b->inhOpt)
-               return false;
-       if (!equalstr(a->name, b->name))
-               return false;
-       if (!equal(a->def, b->def))
-               return false;
-       if (a->behavior != b->behavior)
-               return false;
+       COMPARE_SCALAR_FIELD(subtype);
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(def);
+       COMPARE_SCALAR_FIELD(behavior);
+
+       return true;
+}
+
+static bool
+_equalAlterDomainStmt(AlterDomainStmt * a, AlterDomainStmt * b)
+{
+       COMPARE_SCALAR_FIELD(subtype);
+       COMPARE_NODE_FIELD(typename);
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(def);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
@@ -756,16 +729,13 @@ _equalAlterTableStmt(AlterTableStmt *a, AlterTableStmt *b)
 static bool
 _equalGrantStmt(GrantStmt *a, GrantStmt *b)
 {
-       if (a->is_grant != b->is_grant)
-               return false;
-       if (a->objtype != b->objtype)
-               return false;
-       if (!equal(a->objects, b->objects))
-               return false;
-       if (!equal(a->privileges, b->privileges))
-               return false;
-       if (!equal(a->grantees, b->grantees))
-               return false;
+       COMPARE_SCALAR_FIELD(is_grant);
+       COMPARE_SCALAR_FIELD(objtype);
+       COMPARE_NODE_FIELD(objects);
+       COMPARE_INTLIST_FIELD(privileges);
+       COMPARE_NODE_FIELD(grantees);
+       COMPARE_SCALAR_FIELD(grant_option);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
@@ -773,22 +743,35 @@ _equalGrantStmt(GrantStmt *a, GrantStmt *b)
 static bool
 _equalPrivGrantee(PrivGrantee *a, PrivGrantee *b)
 {
-       return equalstr(a->username, b->username)
-               && equalstr(a->groupname, b->groupname);
+       COMPARE_STRING_FIELD(username);
+       COMPARE_STRING_FIELD(groupname);
+
+       return true;
 }
 
 static bool
 _equalFuncWithArgs(FuncWithArgs *a, FuncWithArgs *b)
 {
-       return equalstr(a->funcname, b->funcname)
-               && equal(a->funcargs, b->funcargs);
+       COMPARE_NODE_FIELD(funcname);
+       COMPARE_NODE_FIELD(funcargs);
+
+       return true;
+}
+
+static bool
+_equalDeclareCursorStmt(DeclareCursorStmt * a, DeclareCursorStmt * b)
+{
+       COMPARE_STRING_FIELD(portalname);
+       COMPARE_SCALAR_FIELD(options);
+       COMPARE_NODE_FIELD(query);
+
+       return true;
 }
 
 static bool
 _equalClosePortalStmt(ClosePortalStmt *a, ClosePortalStmt *b)
 {
-       if (!equalstr(a->portalname, b->portalname))
-               return false;
+       COMPARE_STRING_FIELD(portalname);
 
        return true;
 }
@@ -796,10 +779,8 @@ _equalClosePortalStmt(ClosePortalStmt *a, ClosePortalStmt *b)
 static bool
 _equalClusterStmt(ClusterStmt *a, ClusterStmt *b)
 {
-       if (!equalstr(a->relname, b->relname))
-               return false;
-       if (!equalstr(a->indexname, b->indexname))
-               return false;
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_STRING_FIELD(indexname);
 
        return true;
 }
@@ -807,20 +788,11 @@ _equalClusterStmt(ClusterStmt *a, ClusterStmt *b)
 static bool
 _equalCopyStmt(CopyStmt *a, CopyStmt *b)
 {
-       if (a->binary != b->binary)
-               return false;
-       if (!equalstr(a->relname, b->relname))
-               return false;
-       if (a->oids != b->oids)
-               return false;
-       if (a->direction != b->direction)
-               return false;
-       if (!equalstr(a->filename, b->filename))
-               return false;
-       if (!equalstr(a->delimiter, b->delimiter))
-               return false;
-       if (!equalstr(a->null_print, b->null_print))
-               return false;
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_NODE_FIELD(attlist);
+       COMPARE_SCALAR_FIELD(is_from);
+       COMPARE_STRING_FIELD(filename);
+       COMPARE_NODE_FIELD(options);
 
        return true;
 }
@@ -828,33 +800,21 @@ _equalCopyStmt(CopyStmt *a, CopyStmt *b)
 static bool
 _equalCreateStmt(CreateStmt *a, CreateStmt *b)
 {
-       if (!equalstr(a->relname, b->relname))
-               return false;
-       if (!equal(a->tableElts, b->tableElts))
-               return false;
-       if (!equal(a->inhRelnames, b->inhRelnames))
-               return false;
-       if (!equal(a->constraints, b->constraints))
-               return false;
-       if (a->istemp != b->istemp)
-               return false;
-       if (a->hasoids != b->hasoids)
-               return false;
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_NODE_FIELD(tableElts);
+       COMPARE_NODE_FIELD(inhRelations);
+       COMPARE_NODE_FIELD(constraints);
+       COMPARE_SCALAR_FIELD(hasoids);
+       COMPARE_SCALAR_FIELD(oncommit);
 
        return true;
 }
 
 static bool
-_equalVersionStmt(VersionStmt *a, VersionStmt *b)
+_equalInhRelation(InhRelation * a, InhRelation * b)
 {
-       if (!equalstr(a->relname, b->relname))
-               return false;
-       if (a->direction != b->direction)
-               return false;
-       if (!equalstr(a->fromRelname, b->fromRelname))
-               return false;
-       if (!equalstr(a->date, b->date))
-               return false;
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_SCALAR_FIELD(including_defaults);
 
        return true;
 }
@@ -862,12 +822,9 @@ _equalVersionStmt(VersionStmt *a, VersionStmt *b)
 static bool
 _equalDefineStmt(DefineStmt *a, DefineStmt *b)
 {
-       if (a->defType != b->defType)
-               return false;
-       if (!equalstr(a->defname, b->defname))
-               return false;
-       if (!equal(a->definition, b->definition))
-               return false;
+       COMPARE_SCALAR_FIELD(kind);
+       COMPARE_NODE_FIELD(defnames);
+       COMPARE_NODE_FIELD(definition);
 
        return true;
 }
@@ -875,10 +832,9 @@ _equalDefineStmt(DefineStmt *a, DefineStmt *b)
 static bool
 _equalDropStmt(DropStmt *a, DropStmt *b)
 {
-       if (!equal(a->names, b->names))
-               return false;
-       if (a->removeType != b->removeType)
-               return false;
+       COMPARE_NODE_FIELD(objects);
+       COMPARE_SCALAR_FIELD(removeType);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
@@ -886,8 +842,7 @@ _equalDropStmt(DropStmt *a, DropStmt *b)
 static bool
 _equalTruncateStmt(TruncateStmt *a, TruncateStmt *b)
 {
-       if (!equalstr(a->relName, b->relName))
-               return false;
+       COMPARE_NODE_FIELD(relation);
 
        return true;
 }
@@ -895,16 +850,10 @@ _equalTruncateStmt(TruncateStmt *a, TruncateStmt *b)
 static bool
 _equalCommentStmt(CommentStmt *a, CommentStmt *b)
 {
-       if (a->objtype != b->objtype)
-               return false;
-       if (!equalstr(a->objname, b->objname))
-               return false;
-       if (!equalstr(a->objproperty, b->objproperty))
-               return false;
-       if (!equal(a->objlist, b->objlist))
-               return false;
-       if (!equalstr(a->comment, b->comment))
-               return false;
+       COMPARE_SCALAR_FIELD(objtype);
+       COMPARE_NODE_FIELD(objname);
+       COMPARE_NODE_FIELD(objargs);
+       COMPARE_STRING_FIELD(comment);
 
        return true;
 }
@@ -912,14 +861,10 @@ _equalCommentStmt(CommentStmt *a, CommentStmt *b)
 static bool
 _equalFetchStmt(FetchStmt *a, FetchStmt *b)
 {
-       if (a->direction != b->direction)
-               return false;
-       if (a->howMany != b->howMany)
-               return false;
-       if (!equalstr(a->portalname, b->portalname))
-               return false;
-       if (a->ismove != b->ismove)
-               return false;
+       COMPARE_SCALAR_FIELD(direction);
+       COMPARE_SCALAR_FIELD(howMany);
+       COMPARE_STRING_FIELD(portalname);
+       COMPARE_SCALAR_FIELD(ismove);
 
        return true;
 }
@@ -927,43 +872,28 @@ _equalFetchStmt(FetchStmt *a, FetchStmt *b)
 static bool
 _equalIndexStmt(IndexStmt *a, IndexStmt *b)
 {
-       if (!equalstr(a->idxname, b->idxname))
-               return false;
-       if (!equalstr(a->relname, b->relname))
-               return false;
-       if (!equalstr(a->accessMethod, b->accessMethod))
-               return false;
-       if (!equal(a->indexParams, b->indexParams))
-               return false;
-       if (!equal(a->whereClause, b->whereClause))
-               return false;
-       if (!equal(a->rangetable, b->rangetable))
-               return false;
-       if (a->unique != b->unique)
-               return false;
-       if (a->primary != b->primary)
-               return false;
+       COMPARE_STRING_FIELD(idxname);
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_STRING_FIELD(accessMethod);
+       COMPARE_NODE_FIELD(indexParams);
+       COMPARE_NODE_FIELD(whereClause);
+       COMPARE_NODE_FIELD(rangetable);
+       COMPARE_SCALAR_FIELD(unique);
+       COMPARE_SCALAR_FIELD(primary);
+       COMPARE_SCALAR_FIELD(isconstraint);
 
        return true;
 }
 
 static bool
-_equalProcedureStmt(ProcedureStmt *a, ProcedureStmt *b)
+_equalCreateFunctionStmt(CreateFunctionStmt *a, CreateFunctionStmt *b)
 {
-       if (a->replace != b->replace)
-               return false;
-       if (!equalstr(a->funcname, b->funcname))
-               return false;
-       if (!equal(a->argTypes, b->argTypes))
-               return false;
-       if (!equal(a->returnType, b->returnType))
-               return false;
-       if (!equal(a->withClause, b->withClause))
-               return false;
-       if (!equal(a->as, b->as))
-               return false;
-       if (!equalstr(a->language, b->language))
-               return false;
+       COMPARE_SCALAR_FIELD(replace);
+       COMPARE_NODE_FIELD(funcname);
+       COMPARE_NODE_FIELD(argTypes);
+       COMPARE_NODE_FIELD(returnType);
+       COMPARE_NODE_FIELD(options);
+       COMPARE_NODE_FIELD(withClause);
 
        return true;
 }
@@ -971,10 +901,9 @@ _equalProcedureStmt(ProcedureStmt *a, ProcedureStmt *b)
 static bool
 _equalRemoveAggrStmt(RemoveAggrStmt *a, RemoveAggrStmt *b)
 {
-       if (!equalstr(a->aggname, b->aggname))
-               return false;
-       if (!equal(a->aggtype, b->aggtype))
-               return false;
+       COMPARE_NODE_FIELD(aggname);
+       COMPARE_NODE_FIELD(aggtype);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
@@ -982,10 +911,9 @@ _equalRemoveAggrStmt(RemoveAggrStmt *a, RemoveAggrStmt *b)
 static bool
 _equalRemoveFuncStmt(RemoveFuncStmt *a, RemoveFuncStmt *b)
 {
-       if (!equalstr(a->funcname, b->funcname))
-               return false;
-       if (!equal(a->args, b->args))
-               return false;
+       COMPARE_NODE_FIELD(funcname);
+       COMPARE_NODE_FIELD(args);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
@@ -993,26 +921,32 @@ _equalRemoveFuncStmt(RemoveFuncStmt *a, RemoveFuncStmt *b)
 static bool
 _equalRemoveOperStmt(RemoveOperStmt *a, RemoveOperStmt *b)
 {
-       if (!equalstr(a->opname, b->opname))
-               return false;
-       if (!equal(a->args, b->args))
-               return false;
+       COMPARE_NODE_FIELD(opname);
+       COMPARE_NODE_FIELD(args);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
 
+static bool
+_equalRemoveOpClassStmt(RemoveOpClassStmt *a, RemoveOpClassStmt *b)
+{
+       COMPARE_NODE_FIELD(opclassname);
+       COMPARE_STRING_FIELD(amname);
+       COMPARE_SCALAR_FIELD(behavior);
+
+       return true;
+}
 
 static bool
 _equalRenameStmt(RenameStmt *a, RenameStmt *b)
 {
-       if (!equalstr(a->relname, b->relname))
-               return false;
-       if (a->inhOpt != b->inhOpt)
-               return false;
-       if (!equalstr(a->column, b->column))
-               return false;
-       if (!equalstr(a->newname, b->newname))
-               return false;
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_NODE_FIELD(object);
+       COMPARE_NODE_FIELD(objarg);
+       COMPARE_STRING_FIELD(subname);
+       COMPARE_STRING_FIELD(newname);
+       COMPARE_SCALAR_FIELD(renameType);
 
        return true;
 }
@@ -1020,18 +954,13 @@ _equalRenameStmt(RenameStmt *a, RenameStmt *b)
 static bool
 _equalRuleStmt(RuleStmt *a, RuleStmt *b)
 {
-       if (!equalstr(a->rulename, b->rulename))
-               return false;
-       if (!equal(a->whereClause, b->whereClause))
-               return false;
-       if (a->event != b->event)
-               return false;
-       if (!equal(a->object, b->object))
-               return false;
-       if (a->instead != b->instead)
-               return false;
-       if (!equal(a->actions, b->actions))
-               return false;
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_STRING_FIELD(rulename);
+       COMPARE_NODE_FIELD(whereClause);
+       COMPARE_SCALAR_FIELD(event);
+       COMPARE_SCALAR_FIELD(instead);
+       COMPARE_NODE_FIELD(actions);
+       COMPARE_SCALAR_FIELD(replace);
 
        return true;
 }
@@ -1039,8 +968,7 @@ _equalRuleStmt(RuleStmt *a, RuleStmt *b)
 static bool
 _equalNotifyStmt(NotifyStmt *a, NotifyStmt *b)
 {
-       if (!equalstr(a->relname, b->relname))
-               return false;
+       COMPARE_NODE_FIELD(relation);
 
        return true;
 }
@@ -1048,8 +976,7 @@ _equalNotifyStmt(NotifyStmt *a, NotifyStmt *b)
 static bool
 _equalListenStmt(ListenStmt *a, ListenStmt *b)
 {
-       if (!equalstr(a->relname, b->relname))
-               return false;
+       COMPARE_NODE_FIELD(relation);
 
        return true;
 }
@@ -1057,8 +984,7 @@ _equalListenStmt(ListenStmt *a, ListenStmt *b)
 static bool
 _equalUnlistenStmt(UnlistenStmt *a, UnlistenStmt *b)
 {
-       if (!equalstr(a->relname, b->relname))
-               return false;
+       COMPARE_NODE_FIELD(relation);
 
        return true;
 }
@@ -1066,8 +992,17 @@ _equalUnlistenStmt(UnlistenStmt *a, UnlistenStmt *b)
 static bool
 _equalTransactionStmt(TransactionStmt *a, TransactionStmt *b)
 {
-       if (a->command != b->command)
-               return false;
+       COMPARE_SCALAR_FIELD(kind);
+       COMPARE_NODE_FIELD(options);
+
+       return true;
+}
+
+static bool
+_equalCompositeTypeStmt(CompositeTypeStmt *a, CompositeTypeStmt *b)
+{
+       COMPARE_NODE_FIELD(typevar);
+       COMPARE_NODE_FIELD(coldeflist);
 
        return true;
 }
@@ -1075,12 +1010,10 @@ _equalTransactionStmt(TransactionStmt *a, TransactionStmt *b)
 static bool
 _equalViewStmt(ViewStmt *a, ViewStmt *b)
 {
-       if (!equalstr(a->viewname, b->viewname))
-               return false;
-       if (!equal(a->aliases, b->aliases))
-               return false;
-       if (!equal(a->query, b->query))
-               return false;
+       COMPARE_NODE_FIELD(view);
+       COMPARE_NODE_FIELD(aliases);
+       COMPARE_NODE_FIELD(query);
+       COMPARE_SCALAR_FIELD(replace);
 
        return true;
 }
@@ -1088,8 +1021,42 @@ _equalViewStmt(ViewStmt *a, ViewStmt *b)
 static bool
 _equalLoadStmt(LoadStmt *a, LoadStmt *b)
 {
-       if (!equalstr(a->filename, b->filename))
-               return false;
+       COMPARE_STRING_FIELD(filename);
+
+       return true;
+}
+
+static bool
+_equalCreateDomainStmt(CreateDomainStmt *a, CreateDomainStmt *b)
+{
+       COMPARE_NODE_FIELD(domainname);
+       COMPARE_NODE_FIELD(typename);
+       COMPARE_NODE_FIELD(constraints);
+
+       return true;
+}
+
+static bool
+_equalCreateOpClassStmt(CreateOpClassStmt *a, CreateOpClassStmt *b)
+{
+       COMPARE_NODE_FIELD(opclassname);
+       COMPARE_STRING_FIELD(amname);
+       COMPARE_NODE_FIELD(datatype);
+       COMPARE_NODE_FIELD(items);
+       COMPARE_SCALAR_FIELD(isDefault);
+
+       return true;
+}
+
+static bool
+_equalCreateOpClassItem(CreateOpClassItem *a, CreateOpClassItem *b)
+{
+       COMPARE_SCALAR_FIELD(itemtype);
+       COMPARE_NODE_FIELD(name);
+       COMPARE_NODE_FIELD(args);
+       COMPARE_SCALAR_FIELD(number);
+       COMPARE_SCALAR_FIELD(recheck);
+       COMPARE_NODE_FIELD(storedtype);
 
        return true;
 }
@@ -1097,16 +1064,18 @@ _equalLoadStmt(LoadStmt *a, LoadStmt *b)
 static bool
 _equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b)
 {
-       if (!equalstr(a->dbname, b->dbname))
-               return false;
-       if (!equalstr(a->dbowner, b->dbowner))
-               return false;
-       if (!equalstr(a->dbpath, b->dbpath))
-               return false;
-       if (!equalstr(a->dbtemplate, b->dbtemplate))
-               return false;
-       if (a->encoding != b->encoding)
-               return false;
+       COMPARE_STRING_FIELD(dbname);
+       COMPARE_NODE_FIELD(options);
+
+       return true;
+}
+
+static bool
+_equalAlterDatabaseSetStmt(AlterDatabaseSetStmt *a, AlterDatabaseSetStmt *b)
+{
+       COMPARE_STRING_FIELD(dbname);
+       COMPARE_STRING_FIELD(variable);
+       COMPARE_NODE_FIELD(value);
 
        return true;
 }
@@ -1114,8 +1083,7 @@ _equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b)
 static bool
 _equalDropdbStmt(DropdbStmt *a, DropdbStmt *b)
 {
-       if (!equalstr(a->dbname, b->dbname))
-               return false;
+       COMPARE_STRING_FIELD(dbname);
 
        return true;
 }
@@ -1123,20 +1091,13 @@ _equalDropdbStmt(DropdbStmt *a, DropdbStmt *b)
 static bool
 _equalVacuumStmt(VacuumStmt *a, VacuumStmt *b)
 {
-       if (a->vacuum != b->vacuum)
-               return false;
-       if (a->full != b->full)
-               return false;
-       if (a->analyze != b->analyze)
-               return false;
-       if (a->freeze != b->freeze)
-               return false;
-       if (a->verbose != b->verbose)
-               return false;
-       if (!equalstr(a->vacrel, b->vacrel))
-               return false;
-       if (!equal(a->va_cols, b->va_cols))
-               return false;
+       COMPARE_SCALAR_FIELD(vacuum);
+       COMPARE_SCALAR_FIELD(full);
+       COMPARE_SCALAR_FIELD(analyze);
+       COMPARE_SCALAR_FIELD(freeze);
+       COMPARE_SCALAR_FIELD(verbose);
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_NODE_FIELD(va_cols);
 
        return true;
 }
@@ -1144,12 +1105,9 @@ _equalVacuumStmt(VacuumStmt *a, VacuumStmt *b)
 static bool
 _equalExplainStmt(ExplainStmt *a, ExplainStmt *b)
 {
-       if (!equal(a->query, b->query))
-               return false;
-       if (a->verbose != b->verbose)
-               return false;
-       if (a->analyze != b->analyze)
-               return false;
+       COMPARE_NODE_FIELD(query);
+       COMPARE_SCALAR_FIELD(verbose);
+       COMPARE_SCALAR_FIELD(analyze);
 
        return true;
 }
@@ -1157,10 +1115,17 @@ _equalExplainStmt(ExplainStmt *a, ExplainStmt *b)
 static bool
 _equalCreateSeqStmt(CreateSeqStmt *a, CreateSeqStmt *b)
 {
-       if (!equalstr(a->seqname, b->seqname))
-               return false;
-       if (!equal(a->options, b->options))
-               return false;
+       COMPARE_NODE_FIELD(sequence);
+       COMPARE_NODE_FIELD(options);
+
+       return true;
+}
+
+static bool
+_equalAlterSeqStmt(AlterSeqStmt * a, AlterSeqStmt * b)
+{
+       COMPARE_NODE_FIELD(sequence);
+       COMPARE_NODE_FIELD(options);
 
        return true;
 }
@@ -1168,10 +1133,9 @@ _equalCreateSeqStmt(CreateSeqStmt *a, CreateSeqStmt *b)
 static bool
 _equalVariableSetStmt(VariableSetStmt *a, VariableSetStmt *b)
 {
-       if (!equalstr(a->name, b->name))
-               return false;
-       if (!equal(a->args, b->args))
-               return false;
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(args);
+       COMPARE_SCALAR_FIELD(is_local);
 
        return true;
 }
@@ -1179,8 +1143,7 @@ _equalVariableSetStmt(VariableSetStmt *a, VariableSetStmt *b)
 static bool
 _equalVariableShowStmt(VariableShowStmt *a, VariableShowStmt *b)
 {
-       if (!equalstr(a->name, b->name))
-               return false;
+       COMPARE_STRING_FIELD(name);
 
        return true;
 }
@@ -1188,8 +1151,7 @@ _equalVariableShowStmt(VariableShowStmt *a, VariableShowStmt *b)
 static bool
 _equalVariableResetStmt(VariableResetStmt *a, VariableResetStmt *b)
 {
-       if (!equalstr(a->name, b->name))
-               return false;
+       COMPARE_STRING_FIELD(name);
 
        return true;
 }
@@ -1197,47 +1159,29 @@ _equalVariableResetStmt(VariableResetStmt *a, VariableResetStmt *b)
 static bool
 _equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b)
 {
-       if (!equalstr(a->trigname, b->trigname))
-               return false;
-       if (!equalstr(a->relname, b->relname))
-               return false;
-       if (!equalstr(a->funcname, b->funcname))
-               return false;
-       if (!equal(a->args, b->args))
-               return false;
-       if (a->before != b->before)
-               return false;
-       if (a->row != b->row)
-               return false;
-       if (strcmp(a->actions, b->actions) != 0)
-               return false;
-       if (!equalstr(a->lang, b->lang))
-               return false;
-       if (!equalstr(a->text, b->text))
-               return false;
-       if (!equal(a->attr, b->attr))
-               return false;
-       if (!equalstr(a->when, b->when))
-               return false;
-       if (a->isconstraint != b->isconstraint)
-               return false;
-       if (a->deferrable != b->deferrable)
-               return false;
-       if (a->initdeferred != b->initdeferred)
-               return false;
-       if (!equalstr(a->constrrelname, b->constrrelname))
+       COMPARE_STRING_FIELD(trigname);
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_NODE_FIELD(funcname);
+       COMPARE_NODE_FIELD(args);
+       COMPARE_SCALAR_FIELD(before);
+       COMPARE_SCALAR_FIELD(row);
+       if (strcmp(a->actions, b->actions) != 0)        /* in-line string field */
                return false;
+       COMPARE_SCALAR_FIELD(isconstraint);
+       COMPARE_SCALAR_FIELD(deferrable);
+       COMPARE_SCALAR_FIELD(initdeferred);
+       COMPARE_NODE_FIELD(constrrel);
 
        return true;
 }
 
 static bool
-_equalDropTrigStmt(DropTrigStmt *a, DropTrigStmt *b)
+_equalDropPropertyStmt(DropPropertyStmt *a, DropPropertyStmt *b)
 {
-       if (!equalstr(a->trigname, b->trigname))
-               return false;
-       if (!equalstr(a->relname, b->relname))
-               return false;
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_STRING_FIELD(property);
+       COMPARE_SCALAR_FIELD(removeType);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
@@ -1245,14 +1189,10 @@ _equalDropTrigStmt(DropTrigStmt *a, DropTrigStmt *b)
 static bool
 _equalCreatePLangStmt(CreatePLangStmt *a, CreatePLangStmt *b)
 {
-       if (!equalstr(a->plname, b->plname))
-               return false;
-       if (!equalstr(a->plhandler, b->plhandler))
-               return false;
-       if (!equalstr(a->plcompiler, b->plcompiler))
-               return false;
-       if (a->pltrusted != b->pltrusted)
-               return false;
+       COMPARE_STRING_FIELD(plname);
+       COMPARE_NODE_FIELD(plhandler);
+       COMPARE_NODE_FIELD(plvalidator);
+       COMPARE_SCALAR_FIELD(pltrusted);
 
        return true;
 }
@@ -1260,8 +1200,8 @@ _equalCreatePLangStmt(CreatePLangStmt *a, CreatePLangStmt *b)
 static bool
 _equalDropPLangStmt(DropPLangStmt *a, DropPLangStmt *b)
 {
-       if (!equalstr(a->plname, b->plname))
-               return false;
+       COMPARE_STRING_FIELD(plname);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
@@ -1269,10 +1209,8 @@ _equalDropPLangStmt(DropPLangStmt *a, DropPLangStmt *b)
 static bool
 _equalCreateUserStmt(CreateUserStmt *a, CreateUserStmt *b)
 {
-       if (!equalstr(a->user, b->user))
-               return false;
-       if (!equal(a->options, b->options))
-               return false;
+       COMPARE_STRING_FIELD(user);
+       COMPARE_NODE_FIELD(options);
 
        return true;
 }
@@ -1280,10 +1218,18 @@ _equalCreateUserStmt(CreateUserStmt *a, CreateUserStmt *b)
 static bool
 _equalAlterUserStmt(AlterUserStmt *a, AlterUserStmt *b)
 {
-       if (!equalstr(a->user, b->user))
-               return false;
-       if (!equal(a->options, b->options))
-               return false;
+       COMPARE_STRING_FIELD(user);
+       COMPARE_NODE_FIELD(options);
+
+       return true;
+}
+
+static bool
+_equalAlterUserSetStmt(AlterUserSetStmt *a, AlterUserSetStmt *b)
+{
+       COMPARE_STRING_FIELD(user);
+       COMPARE_STRING_FIELD(variable);
+       COMPARE_NODE_FIELD(value);
 
        return true;
 }
@@ -1291,8 +1237,7 @@ _equalAlterUserStmt(AlterUserStmt *a, AlterUserStmt *b)
 static bool
 _equalDropUserStmt(DropUserStmt *a, DropUserStmt *b)
 {
-       if (!equal(a->users, b->users))
-               return false;
+       COMPARE_NODE_FIELD(users);
 
        return true;
 }
@@ -1300,422 +1245,363 @@ _equalDropUserStmt(DropUserStmt *a, DropUserStmt *b)
 static bool
 _equalLockStmt(LockStmt *a, LockStmt *b)
 {
-       if (!equal(a->rellist, b->rellist))
-               return false;
-       if (a->mode != b->mode)
-               return false;
+       COMPARE_NODE_FIELD(relations);
+       COMPARE_SCALAR_FIELD(mode);
+
+       return true;
+}
+
+static bool
+_equalConstraintsSetStmt(ConstraintsSetStmt *a, ConstraintsSetStmt *b)
+{
+       COMPARE_NODE_FIELD(constraints);
+       COMPARE_SCALAR_FIELD(deferred);
+
+       return true;
+}
+
+static bool
+_equalCreateGroupStmt(CreateGroupStmt *a, CreateGroupStmt *b)
+{
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(options);
 
        return true;
 }
 
 static bool
-_equalConstraintsSetStmt(ConstraintsSetStmt *a, ConstraintsSetStmt *b)
+_equalAlterGroupStmt(AlterGroupStmt *a, AlterGroupStmt *b)
 {
-       if (!equal(a->constraints, b->constraints))
-               return false;
-       if (a->deferred != b->deferred)
-               return false;
+       COMPARE_STRING_FIELD(name);
+       COMPARE_SCALAR_FIELD(action);
+       COMPARE_NODE_FIELD(listUsers);
 
        return true;
 }
 
 static bool
-_equalCreateGroupStmt(CreateGroupStmt *a, CreateGroupStmt *b)
+_equalDropGroupStmt(DropGroupStmt *a, DropGroupStmt *b)
 {
-       if (!equalstr(a->name, b->name))
-               return false;
-       if (!equal(a->options, b->options))
-               return false;
+       COMPARE_STRING_FIELD(name);
 
        return true;
 }
 
 static bool
-_equalAlterGroupStmt(AlterGroupStmt *a, AlterGroupStmt *b)
+_equalReindexStmt(ReindexStmt *a, ReindexStmt *b)
 {
-       if (!equalstr(a->name, b->name))
-               return false;
-       if (a->action != b->action)
-               return false;
-       if (!equal(a->listUsers, b->listUsers))
-               return false;
+       COMPARE_SCALAR_FIELD(kind);
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_STRING_FIELD(name);
+       COMPARE_SCALAR_FIELD(force);
+       COMPARE_SCALAR_FIELD(all);
 
        return true;
 }
 
 static bool
-_equalDropGroupStmt(DropGroupStmt *a, DropGroupStmt *b)
+_equalCreateSchemaStmt(CreateSchemaStmt *a, CreateSchemaStmt *b)
 {
-       if (!equalstr(a->name, b->name))
-               return false;
+       COMPARE_STRING_FIELD(schemaname);
+       COMPARE_STRING_FIELD(authid);
+       COMPARE_NODE_FIELD(schemaElts);
 
        return true;
 }
 
 static bool
-_equalReindexStmt(ReindexStmt *a, ReindexStmt *b)
+_equalCreateConversionStmt(CreateConversionStmt *a, CreateConversionStmt *b)
 {
-       if (a->reindexType != b->reindexType)
-               return false;
-       if (!equalstr(a->name, b->name))
-               return false;
-       if (a->force != b->force)
-               return false;
-       if (a->all != b->all)
-               return false;
+       COMPARE_NODE_FIELD(conversion_name);
+       COMPARE_STRING_FIELD(for_encoding_name);
+       COMPARE_STRING_FIELD(to_encoding_name);
+       COMPARE_NODE_FIELD(func_name);
+       COMPARE_SCALAR_FIELD(def);
 
        return true;
 }
 
 static bool
-_equalAExpr(A_Expr *a, A_Expr *b)
+_equalCreateCastStmt(CreateCastStmt *a, CreateCastStmt *b)
 {
-       if (a->oper != b->oper)
-               return false;
-       if (!equalstr(a->opname, b->opname))
-               return false;
-       if (!equal(a->lexpr, b->lexpr))
-               return false;
-       if (!equal(a->rexpr, b->rexpr))
-               return false;
+       COMPARE_NODE_FIELD(sourcetype);
+       COMPARE_NODE_FIELD(targettype);
+       COMPARE_NODE_FIELD(func);
+       COMPARE_SCALAR_FIELD(context);
 
        return true;
 }
 
 static bool
-_equalAttr(Attr *a, Attr *b)
+_equalDropCastStmt(DropCastStmt *a, DropCastStmt *b)
 {
-       if (strcmp(a->relname, b->relname) != 0)
-               return false;
-       if (!equal(a->paramNo, b->paramNo))
-               return false;
-       if (!equal(a->attrs, b->attrs))
-               return false;
-       if (!equal(a->indirection, b->indirection))
-               return false;
+       COMPARE_NODE_FIELD(sourcetype);
+       COMPARE_NODE_FIELD(targettype);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
 
 static bool
-_equalAConst(A_Const *a, A_Const *b)
+_equalPrepareStmt(PrepareStmt *a, PrepareStmt *b)
 {
-       if (!equal(&a->val, &b->val))
-               return false;
-       if (!equal(a->typename, b->typename))
-               return false;
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(argtypes);
+       COMPARE_OIDLIST_FIELD(argtype_oids);
+       COMPARE_NODE_FIELD(query);
 
        return true;
 }
 
 static bool
-_equalParamNo(ParamNo *a, ParamNo *b)
+_equalExecuteStmt(ExecuteStmt *a, ExecuteStmt *b)
 {
-       if (a->number != b->number)
-               return false;
-       if (!equal(a->typename, b->typename))
-               return false;
-       if (!equal(a->indirection, b->indirection))
-               return false;
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(into);
+       COMPARE_NODE_FIELD(params);
 
        return true;
 }
 
 static bool
-_equalIdent(Ident *a, Ident *b)
+_equalDeallocateStmt(DeallocateStmt *a, DeallocateStmt *b)
 {
-       if (!equalstr(a->name, b->name))
-               return false;
-       if (!equal(a->indirection, b->indirection))
-               return false;
-       if (a->isRel != b->isRel)
-               return false;
+       COMPARE_STRING_FIELD(name);
 
        return true;
 }
 
+
+/*
+ * stuff from parsenodes.h
+ */
+
 static bool
-_equalFuncCall(FuncCall *a, FuncCall *b)
+_equalAExpr(A_Expr *a, A_Expr *b)
 {
-       if (!equalstr(a->funcname, b->funcname))
-               return false;
-       if (!equal(a->args, b->args))
-               return false;
-       if (a->agg_star != b->agg_star)
-               return false;
-       if (a->agg_distinct != b->agg_distinct)
-               return false;
+       COMPARE_SCALAR_FIELD(kind);
+       COMPARE_NODE_FIELD(name);
+       COMPARE_NODE_FIELD(lexpr);
+       COMPARE_NODE_FIELD(rexpr);
 
        return true;
 }
 
 static bool
-_equalAIndices(A_Indices *a, A_Indices *b)
+_equalColumnRef(ColumnRef *a, ColumnRef *b)
 {
-       if (!equal(a->lidx, b->lidx))
-               return false;
-       if (!equal(a->uidx, b->uidx))
-               return false;
+       COMPARE_NODE_FIELD(fields);
+       COMPARE_NODE_FIELD(indirection);
 
        return true;
 }
 
 static bool
-_equalResTarget(ResTarget *a, ResTarget *b)
+_equalParamRef(ParamRef *a, ParamRef *b)
 {
-       if (!equalstr(a->name, b->name))
-               return false;
-       if (!equal(a->indirection, b->indirection))
-               return false;
-       if (!equal(a->val, b->val))
-               return false;
+       COMPARE_SCALAR_FIELD(number);
+       COMPARE_NODE_FIELD(fields);
+       COMPARE_NODE_FIELD(indirection);
 
        return true;
 }
 
 static bool
-_equalTypeCast(TypeCast *a, TypeCast *b)
+_equalAConst(A_Const *a, A_Const *b)
 {
-       if (!equal(a->arg, b->arg))
-               return false;
-       if (!equal(a->typename, b->typename))
+       if (!equal(&a->val, &b->val))           /* hack for in-line Value field */
                return false;
+       COMPARE_NODE_FIELD(typename);
 
        return true;
 }
 
 static bool
-_equalSortGroupBy(SortGroupBy *a, SortGroupBy *b)
+_equalFuncCall(FuncCall *a, FuncCall *b)
 {
-       if (!equalstr(a->useOp, b->useOp))
-               return false;
-       if (!equal(a->node, b->node))
-               return false;
+       COMPARE_NODE_FIELD(funcname);
+       COMPARE_NODE_FIELD(args);
+       COMPARE_SCALAR_FIELD(agg_star);
+       COMPARE_SCALAR_FIELD(agg_distinct);
 
        return true;
 }
 
 static bool
-_equalRangeVar(RangeVar *a, RangeVar *b)
+_equalAIndices(A_Indices *a, A_Indices *b)
 {
-       if (!equalstr(a->relname, b->relname))
-               return false;
-       if (a->inhOpt != b->inhOpt)
-               return false;
-       if (!equal(a->name, b->name))
-               return false;
+       COMPARE_NODE_FIELD(lidx);
+       COMPARE_NODE_FIELD(uidx);
 
        return true;
 }
 
 static bool
-_equalRangeSubselect(RangeSubselect *a, RangeSubselect *b)
+_equalExprFieldSelect(ExprFieldSelect *a, ExprFieldSelect *b)
 {
-       if (!equal(a->subquery, b->subquery))
-               return false;
-       if (!equal(a->name, b->name))
-               return false;
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_NODE_FIELD(fields);
+       COMPARE_NODE_FIELD(indirection);
 
        return true;
 }
 
 static bool
-_equalTypeName(TypeName *a, TypeName *b)
+_equalResTarget(ResTarget *a, ResTarget *b)
 {
-       if (!equalstr(a->name, b->name))
-               return false;
-       if (a->timezone != b->timezone)
-               return false;
-       if (a->setof != b->setof)
-               return false;
-       if (a->typmod != b->typmod)
-               return false;
-       if (!equal(a->arrayBounds, b->arrayBounds))
-               return false;
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(indirection);
+       COMPARE_NODE_FIELD(val);
 
        return true;
 }
 
 static bool
-_equalIndexElem(IndexElem *a, IndexElem *b)
+_equalTypeName(TypeName *a, TypeName *b)
 {
-       if (!equalstr(a->name, b->name))
-               return false;
-       if (!equal(a->args, b->args))
-               return false;
-       if (!equalstr(a->class, b->class))
-               return false;
+       COMPARE_NODE_FIELD(names);
+       COMPARE_SCALAR_FIELD(typeid);
+       COMPARE_SCALAR_FIELD(timezone);
+       COMPARE_SCALAR_FIELD(setof);
+       COMPARE_SCALAR_FIELD(pct_type);
+       COMPARE_SCALAR_FIELD(typmod);
+       COMPARE_NODE_FIELD(arrayBounds);
 
        return true;
 }
 
 static bool
-_equalColumnDef(ColumnDef *a, ColumnDef *b)
+_equalTypeCast(TypeCast *a, TypeCast *b)
 {
-       if (!equalstr(a->colname, b->colname))
-               return false;
-       if (!equal(a->typename, b->typename))
-               return false;
-       if (a->is_not_null != b->is_not_null)
-               return false;
-       if (!equal(a->raw_default, b->raw_default))
-               return false;
-       if (!equalstr(a->cooked_default, b->cooked_default))
-               return false;
-       if (!equal(a->constraints, b->constraints))
-               return false;
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_NODE_FIELD(typename);
 
        return true;
 }
 
 static bool
-_equalConstraint(Constraint *a, Constraint *b)
+_equalSortGroupBy(SortGroupBy *a, SortGroupBy *b)
 {
-       if (a->contype != b->contype)
-               return false;
-       if (!equalstr(a->name, b->name))
-               return false;
-       if (!equal(a->raw_expr, b->raw_expr))
-               return false;
-       if (!equalstr(a->cooked_expr, b->cooked_expr))
-               return false;
-       if (!equal(a->keys, b->keys))
-               return false;
+       COMPARE_NODE_FIELD(useOp);
+       COMPARE_NODE_FIELD(node);
 
        return true;
 }
 
 static bool
-_equalDefElem(DefElem *a, DefElem *b)
+_equalRangeSubselect(RangeSubselect *a, RangeSubselect *b)
 {
-       if (!equalstr(a->defname, b->defname))
-               return false;
-       if (!equal(a->arg, b->arg))
-               return false;
+       COMPARE_NODE_FIELD(subquery);
+       COMPARE_NODE_FIELD(alias);
 
        return true;
 }
 
 static bool
-_equalTargetEntry(TargetEntry *a, TargetEntry *b)
+_equalRangeFunction(RangeFunction *a, RangeFunction *b)
 {
-       if (!equal(a->resdom, b->resdom))
-               return false;
-       if (!equal(a->fjoin, b->fjoin))
-               return false;
-       if (!equal(a->expr, b->expr))
-               return false;
+       COMPARE_NODE_FIELD(funccallnode);
+       COMPARE_NODE_FIELD(alias);
+       COMPARE_NODE_FIELD(coldeflist);
 
        return true;
 }
 
 static bool
-_equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
+_equalIndexElem(IndexElem *a, IndexElem *b)
 {
-       if (!equalstr(a->relname, b->relname))
-               return false;
-       if (a->relid != b->relid)
-               return false;
-       if (!equal(a->subquery, b->subquery))
-               return false;
-       if (!equal(a->alias, b->alias))
-               return false;
-       if (!equal(a->eref, b->eref))
-               return false;
-       if (a->inh != b->inh)
-               return false;
-       if (a->inFromCl != b->inFromCl)
-               return false;
-       if (a->checkForRead != b->checkForRead)
-               return false;
-       if (a->checkForWrite != b->checkForWrite)
-               return false;
-       if (a->checkAsUser != b->checkAsUser)
-               return false;
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(expr);
+       COMPARE_NODE_FIELD(opclass);
 
        return true;
 }
 
 static bool
-_equalSortClause(SortClause *a, SortClause *b)
+_equalColumnDef(ColumnDef *a, ColumnDef *b)
 {
-       if (a->tleSortGroupRef != b->tleSortGroupRef)
-               return false;
-       if (a->sortop != b->sortop)
-               return false;
+       COMPARE_STRING_FIELD(colname);
+       COMPARE_NODE_FIELD(typename);
+       COMPARE_SCALAR_FIELD(inhcount);
+       COMPARE_SCALAR_FIELD(is_local);
+       COMPARE_SCALAR_FIELD(is_not_null);
+       COMPARE_NODE_FIELD(raw_default);
+       COMPARE_STRING_FIELD(cooked_default);
+       COMPARE_NODE_FIELD(constraints);
+       COMPARE_NODE_FIELD(support);
 
        return true;
 }
 
 static bool
-_equalFkConstraint(FkConstraint *a, FkConstraint *b)
+_equalConstraint(Constraint *a, Constraint *b)
 {
-       if (!equalstr(a->constr_name, b->constr_name))
-               return false;
-       if (!equalstr(a->pktable_name, b->pktable_name))
-               return false;
-       if (!equal(a->fk_attrs, b->fk_attrs))
-               return false;
-       if (!equal(a->pk_attrs, b->pk_attrs))
-               return false;
-       if (!equalstr(a->match_type, b->match_type))
-               return false;
-       if (a->actions != b->actions)
-               return false;
-       if (a->deferrable != b->deferrable)
-               return false;
-       if (a->initdeferred != b->initdeferred)
-               return false;
+       COMPARE_SCALAR_FIELD(contype);
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(raw_expr);
+       COMPARE_STRING_FIELD(cooked_expr);
+       COMPARE_NODE_FIELD(keys);
 
        return true;
 }
 
 static bool
-_equalCaseExpr(CaseExpr *a, CaseExpr *b)
+_equalDefElem(DefElem *a, DefElem *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;
+       COMPARE_STRING_FIELD(defname);
+       COMPARE_NODE_FIELD(arg);
 
        return true;
 }
 
 static bool
-_equalCaseWhen(CaseWhen *a, CaseWhen *b)
+_equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
 {
-       if (!equal(a->expr, b->expr))
-               return false;
-       if (!equal(a->result, b->result))
-               return false;
+       COMPARE_SCALAR_FIELD(rtekind);
+       COMPARE_SCALAR_FIELD(relid);
+       COMPARE_NODE_FIELD(subquery);
+       COMPARE_NODE_FIELD(funcexpr);
+       COMPARE_NODE_FIELD(coldeflist);
+       COMPARE_SCALAR_FIELD(jointype);
+       COMPARE_NODE_FIELD(joinaliasvars);
+       COMPARE_NODE_FIELD(alias);
+       COMPARE_NODE_FIELD(eref);
+       COMPARE_SCALAR_FIELD(inh);
+       COMPARE_SCALAR_FIELD(inFromCl);
+       COMPARE_SCALAR_FIELD(checkForRead);
+       COMPARE_SCALAR_FIELD(checkForWrite);
+       COMPARE_SCALAR_FIELD(checkAsUser);
 
        return true;
 }
 
 static bool
-_equalNullTest(NullTest *a, NullTest *b)
+_equalSortClause(SortClause *a, SortClause *b)
 {
-       if (!equal(a->arg, b->arg))
-               return false;
-       if (a->nulltesttype != b->nulltesttype)
-               return false;
+       COMPARE_SCALAR_FIELD(tleSortGroupRef);
+       COMPARE_SCALAR_FIELD(sortop);
+
        return true;
 }
 
 static bool
-_equalBooleanTest(BooleanTest *a, BooleanTest *b)
+_equalFkConstraint(FkConstraint *a, FkConstraint *b)
 {
-       if (!equal(a->arg, b->arg))
-               return false;
-       if (a->booltesttype != b->booltesttype)
-               return false;
+       COMPARE_STRING_FIELD(constr_name);
+       COMPARE_NODE_FIELD(pktable);
+       COMPARE_NODE_FIELD(fk_attrs);
+       COMPARE_NODE_FIELD(pk_attrs);
+       COMPARE_SCALAR_FIELD(fk_matchtype);
+       COMPARE_SCALAR_FIELD(fk_upd_action);
+       COMPARE_SCALAR_FIELD(fk_del_action);
+       COMPARE_SCALAR_FIELD(deferrable);
+       COMPARE_SCALAR_FIELD(initdeferred);
+       COMPARE_SCALAR_FIELD(skip_validation);
+
        return true;
 }
 
+
 /*
  * Stuff from pg_list.h
  */
@@ -1723,18 +1609,23 @@ _equalBooleanTest(BooleanTest *a, BooleanTest *b)
 static bool
 _equalValue(Value *a, Value *b)
 {
-       if (a->type != b->type)
-               return false;
+       COMPARE_SCALAR_FIELD(type);
 
        switch (a->type)
        {
                case T_Integer:
-                       return a->val.ival == b->val.ival;
+                       COMPARE_SCALAR_FIELD(val.ival);
+                       break;
                case T_Float:
                case T_String:
                case T_BitString:
-                       return strcmp(a->val.str, b->val.str) == 0;
+                       COMPARE_STRING_FIELD(val.str);
+                       break;
+               case T_Null:
+                       /* nothing to do */
+                       break;
                default:
+                       elog(ERROR, "unrecognized node type: %d", (int) a->type);
                        break;
        }
 
@@ -1748,7 +1639,7 @@ _equalValue(Value *a, Value *b)
 bool
 equal(void *a, void *b)
 {
-       bool            retval = false;
+       bool            retval;
 
        if (a == b)
                return true;
@@ -1767,25 +1658,21 @@ equal(void *a, void *b)
 
        switch (nodeTag(a))
        {
-               case T_SubPlan:
-                       retval = _equalSubPlan(a, b);
-                       break;
-
+                       /*
+                        * PRIMITIVE NODES
+                        */
                case T_Resdom:
                        retval = _equalResdom(a, b);
                        break;
-               case T_Fjoin:
-                       retval = _equalFjoin(a, b);
+               case T_Alias:
+                       retval = _equalAlias(a, b);
                        break;
-               case T_Expr:
-                       retval = _equalExpr(a, b);
+               case T_RangeVar:
+                       retval = _equalRangeVar(a, b);
                        break;
                case T_Var:
                        retval = _equalVar(a, b);
                        break;
-               case T_Oper:
-                       retval = _equalOper(a, b);
-                       break;
                case T_Const:
                        retval = _equalConst(a, b);
                        break;
@@ -1795,24 +1682,69 @@ equal(void *a, void *b)
                case T_Aggref:
                        retval = _equalAggref(a, b);
                        break;
+               case T_ArrayRef:
+                       retval = _equalArrayRef(a, b);
+                       break;
+               case T_FuncExpr:
+                       retval = _equalFuncExpr(a, b);
+                       break;
+               case T_OpExpr:
+                       retval = _equalOpExpr(a, b);
+                       break;
+               case T_DistinctExpr:
+                       retval = _equalDistinctExpr(a, b);
+                       break;
+               case T_ScalarArrayOpExpr:
+                       retval = _equalScalarArrayOpExpr(a, b);
+                       break;
+               case T_BoolExpr:
+                       retval = _equalBoolExpr(a, b);
+                       break;
                case T_SubLink:
                        retval = _equalSubLink(a, b);
                        break;
-               case T_Func:
-                       retval = _equalFunc(a, b);
+               case T_SubPlan:
+                       retval = _equalSubPlan(a, b);
                        break;
                case T_FieldSelect:
                        retval = _equalFieldSelect(a, b);
                        break;
-               case T_ArrayRef:
-                       retval = _equalArrayRef(a, b);
-                       break;
-               case T_Iter:
-                       retval = _equalIter(a, b);
-                       break;
                case T_RelabelType:
                        retval = _equalRelabelType(a, b);
                        break;
+               case T_CaseExpr:
+                       retval = _equalCaseExpr(a, b);
+                       break;
+               case T_CaseWhen:
+                       retval = _equalCaseWhen(a, b);
+                       break;
+               case T_ArrayExpr:
+                       retval = _equalArrayExpr(a, b);
+                       break;
+               case T_CoalesceExpr:
+                       retval = _equalCoalesceExpr(a, b);
+                       break;
+               case T_NullIfExpr:
+                       retval = _equalNullIfExpr(a, b);
+                       break;
+               case T_NullTest:
+                       retval = _equalNullTest(a, b);
+                       break;
+               case T_BooleanTest:
+                       retval = _equalBooleanTest(a, b);
+                       break;
+               case T_CoerceToDomain:
+                       retval = _equalCoerceToDomain(a, b);
+                       break;
+               case T_CoerceToDomainValue:
+                       retval = _equalCoerceToDomainValue(a, b);
+                       break;
+               case T_SetToDefault:
+                       retval = _equalSetToDefault(a, b);
+                       break;
+               case T_TargetEntry:
+                       retval = _equalTargetEntry(a, b);
+                       break;
                case T_RangeTblRef:
                        retval = _equalRangeTblRef(a, b);
                        break;
@@ -1823,24 +1755,9 @@ equal(void *a, void *b)
                        retval = _equalJoinExpr(a, b);
                        break;
 
-               case T_RelOptInfo:
-                       retval = _equalRelOptInfo(a, b);
-                       break;
-               case T_Path:
-                       retval = _equalPath(a, b);
-                       break;
-               case T_IndexPath:
-                       retval = _equalIndexPath(a, b);
-                       break;
-               case T_NestPath:
-                       retval = _equalNestPath(a, b);
-                       break;
-               case T_MergePath:
-                       retval = _equalMergePath(a, b);
-                       break;
-               case T_HashPath:
-                       retval = _equalHashPath(a, b);
-                       break;
+                       /*
+                        * RELATION NODES
+                        */
                case T_PathKeyItem:
                        retval = _equalPathKeyItem(a, b);
                        break;
@@ -1850,19 +1767,13 @@ equal(void *a, void *b)
                case T_JoinInfo:
                        retval = _equalJoinInfo(a, b);
                        break;
-               case T_Stream:
-                       retval = _equalStream(a, b);
-                       break;
-               case T_TidPath:
-                       retval = _equalTidPath(a, b);
-                       break;
-               case T_AppendPath:
-                       retval = _equalAppendPath(a, b);
-                       break;
-               case T_IndexOptInfo:
-                       retval = _equalIndexOptInfo(a, b);
+               case T_InClauseInfo:
+                       retval = _equalInClauseInfo(a, b);
                        break;
 
+                       /*
+                        * LIST NODES
+                        */
                case T_List:
                        {
                                List       *la = (List *) a;
@@ -1884,13 +1795,18 @@ equal(void *a, void *b)
                                retval = true;
                        }
                        break;
+
                case T_Integer:
                case T_Float:
                case T_String:
                case T_BitString:
+               case T_Null:
                        retval = _equalValue(a, b);
                        break;
 
+                       /*
+                        * PARSE NODES
+                        */
                case T_Query:
                        retval = _equalQuery(a, b);
                        break;
@@ -1912,9 +1828,15 @@ equal(void *a, void *b)
                case T_AlterTableStmt:
                        retval = _equalAlterTableStmt(a, b);
                        break;
+               case T_AlterDomainStmt:
+                       retval = _equalAlterDomainStmt(a, b);
+                       break;
                case T_GrantStmt:
                        retval = _equalGrantStmt(a, b);
                        break;
+               case T_DeclareCursorStmt:
+                       retval = _equalDeclareCursorStmt(a, b);
+                       break;
                case T_ClosePortalStmt:
                        retval = _equalClosePortalStmt(a, b);
                        break;
@@ -1927,8 +1849,8 @@ equal(void *a, void *b)
                case T_CreateStmt:
                        retval = _equalCreateStmt(a, b);
                        break;
-               case T_VersionStmt:
-                       retval = _equalVersionStmt(a, b);
+               case T_InhRelation:
+                       retval = _equalInhRelation(a, b);
                        break;
                case T_DefineStmt:
                        retval = _equalDefineStmt(a, b);
@@ -1948,8 +1870,8 @@ equal(void *a, void *b)
                case T_IndexStmt:
                        retval = _equalIndexStmt(a, b);
                        break;
-               case T_ProcedureStmt:
-                       retval = _equalProcedureStmt(a, b);
+               case T_CreateFunctionStmt:
+                       retval = _equalCreateFunctionStmt(a, b);
                        break;
                case T_RemoveAggrStmt:
                        retval = _equalRemoveAggrStmt(a, b);
@@ -1960,6 +1882,9 @@ equal(void *a, void *b)
                case T_RemoveOperStmt:
                        retval = _equalRemoveOperStmt(a, b);
                        break;
+               case T_RemoveOpClassStmt:
+                       retval = _equalRemoveOpClassStmt(a, b);
+                       break;
                case T_RenameStmt:
                        retval = _equalRenameStmt(a, b);
                        break;
@@ -1978,15 +1903,30 @@ equal(void *a, void *b)
                case T_TransactionStmt:
                        retval = _equalTransactionStmt(a, b);
                        break;
+               case T_CompositeTypeStmt:
+                       retval = _equalCompositeTypeStmt(a, b);
+                       break;
                case T_ViewStmt:
                        retval = _equalViewStmt(a, b);
                        break;
                case T_LoadStmt:
                        retval = _equalLoadStmt(a, b);
                        break;
+               case T_CreateDomainStmt:
+                       retval = _equalCreateDomainStmt(a, b);
+                       break;
+               case T_CreateOpClassStmt:
+                       retval = _equalCreateOpClassStmt(a, b);
+                       break;
+               case T_CreateOpClassItem:
+                       retval = _equalCreateOpClassItem(a, b);
+                       break;
                case T_CreatedbStmt:
                        retval = _equalCreatedbStmt(a, b);
                        break;
+               case T_AlterDatabaseSetStmt:
+                       retval = _equalAlterDatabaseSetStmt(a, b);
+                       break;
                case T_DropdbStmt:
                        retval = _equalDropdbStmt(a, b);
                        break;
@@ -1999,6 +1939,9 @@ equal(void *a, void *b)
                case T_CreateSeqStmt:
                        retval = _equalCreateSeqStmt(a, b);
                        break;
+               case T_AlterSeqStmt:
+                       retval = _equalAlterSeqStmt(a, b);
+                       break;
                case T_VariableSetStmt:
                        retval = _equalVariableSetStmt(a, b);
                        break;
@@ -2011,8 +1954,8 @@ equal(void *a, void *b)
                case T_CreateTrigStmt:
                        retval = _equalCreateTrigStmt(a, b);
                        break;
-               case T_DropTrigStmt:
-                       retval = _equalDropTrigStmt(a, b);
+               case T_DropPropertyStmt:
+                       retval = _equalDropPropertyStmt(a, b);
                        break;
                case T_CreatePLangStmt:
                        retval = _equalCreatePLangStmt(a, b);
@@ -2026,6 +1969,9 @@ equal(void *a, void *b)
                case T_AlterUserStmt:
                        retval = _equalAlterUserStmt(a, b);
                        break;
+               case T_AlterUserSetStmt:
+                       retval = _equalAlterUserSetStmt(a, b);
+                       break;
                case T_DropUserStmt:
                        retval = _equalDropUserStmt(a, b);
                        break;
@@ -2050,28 +1996,49 @@ equal(void *a, void *b)
                case T_CheckPointStmt:
                        retval = true;
                        break;
+               case T_CreateSchemaStmt:
+                       retval = _equalCreateSchemaStmt(a, b);
+                       break;
+               case T_CreateConversionStmt:
+                       retval = _equalCreateConversionStmt(a, b);
+                       break;
+               case T_CreateCastStmt:
+                       retval = _equalCreateCastStmt(a, b);
+                       break;
+               case T_DropCastStmt:
+                       retval = _equalDropCastStmt(a, b);
+                       break;
+               case T_PrepareStmt:
+                       retval = _equalPrepareStmt(a, b);
+                       break;
+               case T_ExecuteStmt:
+                       retval = _equalExecuteStmt(a, b);
+                       break;
+               case T_DeallocateStmt:
+                       retval = _equalDeallocateStmt(a, b);
+                       break;
 
                case T_A_Expr:
                        retval = _equalAExpr(a, b);
                        break;
-               case T_Attr:
-                       retval = _equalAttr(a, b);
+               case T_ColumnRef:
+                       retval = _equalColumnRef(a, b);
+                       break;
+               case T_ParamRef:
+                       retval = _equalParamRef(a, b);
                        break;
                case T_A_Const:
                        retval = _equalAConst(a, b);
                        break;
-               case T_ParamNo:
-                       retval = _equalParamNo(a, b);
-                       break;
-               case T_Ident:
-                       retval = _equalIdent(a, b);
-                       break;
                case T_FuncCall:
                        retval = _equalFuncCall(a, b);
                        break;
                case T_A_Indices:
                        retval = _equalAIndices(a, b);
                        break;
+               case T_ExprFieldSelect:
+                       retval = _equalExprFieldSelect(a, b);
+                       break;
                case T_ResTarget:
                        retval = _equalResTarget(a, b);
                        break;
@@ -2081,12 +2048,12 @@ equal(void *a, void *b)
                case T_SortGroupBy:
                        retval = _equalSortGroupBy(a, b);
                        break;
-               case T_RangeVar:
-                       retval = _equalRangeVar(a, b);
-                       break;
                case T_RangeSubselect:
                        retval = _equalRangeSubselect(a, b);
                        break;
+               case T_RangeFunction:
+                       retval = _equalRangeFunction(a, b);
+                       break;
                case T_TypeName:
                        retval = _equalTypeName(a, b);
                        break;
@@ -2102,9 +2069,6 @@ equal(void *a, void *b)
                case T_DefElem:
                        retval = _equalDefElem(a, b);
                        break;
-               case T_TargetEntry:
-                       retval = _equalTargetEntry(a, b);
-                       break;
                case T_RangeTblEntry:
                        retval = _equalRangeTblEntry(a, b);
                        break;
@@ -2115,18 +2079,6 @@ equal(void *a, void *b)
                        /* GroupClause is equivalent to SortClause */
                        retval = _equalSortClause(a, b);
                        break;
-               case T_CaseExpr:
-                       retval = _equalCaseExpr(a, b);
-                       break;
-               case T_CaseWhen:
-                       retval = _equalCaseWhen(a, b);
-                       break;
-               case T_NullTest:
-                       retval = _equalNullTest(a, b);
-                       break;
-               case T_BooleanTest:
-                       retval = _equalBooleanTest(a, b);
-                       break;
                case T_FkConstraint:
                        retval = _equalFkConstraint(a, b);
                        break;
@@ -2138,8 +2090,9 @@ equal(void *a, void *b)
                        break;
 
                default:
-                       elog(NOTICE, "equal: don't know whether nodes of type %d are equal",
-                                nodeTag(a));
+                       elog(ERROR, "unrecognized node type: %d",
+                                (int) nodeTag(a));
+                       retval = false;         /* keep compiler quiet */
                        break;
        }