]> granicus.if.org Git - postgresql/commitdiff
Restructure the code in copyfuncs and equalfuncs to put much heavier
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 25 Nov 2002 03:33:27 +0000 (03:33 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 25 Nov 2002 03:33:27 +0000 (03:33 +0000)
reliance on macros, in hopes of eliminating silly typos (like copying
to the wrong field) and just generally making it easier to see the forest
instead of the trees.  As an example, here is the new code for A_Indices:

static A_Indices *
_copyAIndices(A_Indices *from)
{
A_Indices  *newnode = makeNode(A_Indices);

COPY_NODE_FIELD(lidx);
COPY_NODE_FIELD(uidx);

return newnode;
}

static bool
_equalAIndices(A_Indices *a, A_Indices *b)
{
COMPARE_NODE_FIELD(lidx);
COMPARE_NODE_FIELD(uidx);

return true;
}

I plan to redo outfuncs/readfuncs in a similar style, but am committing
what I've got.

src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c

index da3bf7b7213d0c0542fa879d2d8d81394bb87875..0f02b5d119bb4fcd17701396f515a6bec2b9c3bc 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.221 2002/11/24 21:52:13 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.222 2002/11/25 03:33:27 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 
 /*
- * Node_Copy
- *       a macro to simplify calling of copyObject on the specified field
+ * Macros to simplify copying 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 a Copy routine are
+ * named 'newnode' and 'from'.
  */
-#define Node_Copy(from, newnode, field) \
-       ((newnode)->field = copyObject((from)->field))
+
+/* Copy a simple scalar field (int, float, bool, enum, etc) */
+#define COPY_SCALAR_FIELD(fldname) \
+       (newnode->fldname = from->fldname)
+
+/* Copy a field that is a pointer to some kind of Node or Node tree */
+#define COPY_NODE_FIELD(fldname) \
+       (newnode->fldname = copyObject(from->fldname))
+
+/* Copy a field that is a pointer to a list of integers */
+#define COPY_INTLIST_FIELD(fldname) \
+       (newnode->fldname = listCopy(from->fldname))
+
+/* Copy a field that is a pointer to a C string, or perhaps NULL */
+#define COPY_STRING_FIELD(fldname) \
+       (newnode->fldname = from->fldname ? pstrdup(from->fldname) : (char *) NULL)
+
+/* Copy a field that is a pointer to a simple palloc'd object of size sz */
+#define COPY_POINTER_FIELD(fldname, sz) \
+       do { \
+               Size    _size = (sz); \
+               newnode->fldname = palloc(_size); \
+               memcpy(newnode->fldname, from->fldname, _size); \
+       } while (0)
+
+/* Special hack for fixing subplan lists of Plan nodes (ick) */
+#define FIX_SUBPLAN_LINKS(subplanfldname, fldname) \
+       do { \
+               if (from->subplanfldname != NIL) \
+                       newnode->subplanfldname = \
+                               nconc(newnode->subplanfldname, \
+                                         pull_subplans((Node *) (newnode->fldname))); \
+       } while (0)
 
 
 /*
@@ -73,41 +106,37 @@ listCopy(List *list)
  * ****************************************************************
  */
 
-/* ----------------
- *             CopyPlanFields
+/*
+ * CopyPlanFields
  *
  *             This function copies the fields of the Plan node.  It is used by
  *             all the copy functions for classes which inherit from Plan.
- * ----------------
  */
 static void
 CopyPlanFields(Plan *from, Plan *newnode)
 {
-       newnode->startup_cost = from->startup_cost;
-       newnode->total_cost = from->total_cost;
-       newnode->plan_rows = from->plan_rows;
-       newnode->plan_width = from->plan_width;
-       /* state is NOT copied */
-       Node_Copy(from, newnode, targetlist);
-       Node_Copy(from, newnode, qual);
-       Node_Copy(from, newnode, lefttree);
-       Node_Copy(from, newnode, righttree);
-       newnode->extParam = listCopy(from->extParam);
-       newnode->locParam = listCopy(from->locParam);
-       newnode->chgParam = listCopy(from->chgParam);
-       Node_Copy(from, newnode, initPlan);
+       COPY_SCALAR_FIELD(startup_cost);
+       COPY_SCALAR_FIELD(total_cost);
+       COPY_SCALAR_FIELD(plan_rows);
+       COPY_SCALAR_FIELD(plan_width);
+       /* execution state is NOT copied */
+       COPY_NODE_FIELD(targetlist);
+       COPY_NODE_FIELD(qual);
+       COPY_NODE_FIELD(lefttree);
+       COPY_NODE_FIELD(righttree);
+       COPY_INTLIST_FIELD(extParam);
+       COPY_INTLIST_FIELD(locParam);
+       COPY_INTLIST_FIELD(chgParam);
+       COPY_NODE_FIELD(initPlan);
        /* subPlan list must point to subplans in the new subtree, not the old */
-       if (from->subPlan != NIL)
-               newnode->subPlan = nconc(pull_subplans((Node *) newnode->targetlist),
-                                                                pull_subplans((Node *) newnode->qual));
-       else
-               newnode->subPlan = NIL;
-       newnode->nParamExec = from->nParamExec;
+       newnode->subPlan = NIL;
+       FIX_SUBPLAN_LINKS(subPlan, targetlist);
+       FIX_SUBPLAN_LINKS(subPlan, qual);
+       COPY_SCALAR_FIELD(nParamExec);
 }
 
-/* ----------------
- *             _copyPlan
- * ----------------
+/*
+ * _copyPlan
  */
 static Plan *
 _copyPlan(Plan *from)
@@ -115,7 +144,7 @@ _copyPlan(Plan *from)
        Plan       *newnode = makeNode(Plan);
 
        /*
-        * copy the node superclass fields
+        * copy node superclass fields
         */
        CopyPlanFields(from, newnode);
 
@@ -123,9 +152,8 @@ _copyPlan(Plan *from)
 }
 
 
-/* ----------------
- *             _copyResult
- * ----------------
+/*
+ * _copyResult
  */
 static Result *
 _copyResult(Result *from)
@@ -140,22 +168,16 @@ _copyResult(Result *from)
        /*
         * copy remainder of node
         */
-       Node_Copy(from, newnode, resconstantqual);
+       COPY_NODE_FIELD(resconstantqual);
 
-       /*
-        * We must add subplans in resconstantqual to the new plan's subPlan
-        * list
-        */
-       if (from->plan.subPlan != NIL)
-               newnode->plan.subPlan = nconc(newnode->plan.subPlan,
-                                                               pull_subplans(newnode->resconstantqual));
+       /* subPlan list must point to subplans in the new subtree, not the old */
+       FIX_SUBPLAN_LINKS(plan.subPlan, resconstantqual);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyAppend
- * ----------------
+/*
+ * _copyAppend
  */
 static Append *
 _copyAppend(Append *from)
@@ -170,30 +192,29 @@ _copyAppend(Append *from)
        /*
         * copy remainder of node
         */
-       Node_Copy(from, newnode, appendplans);
-       newnode->isTarget = from->isTarget;
+       COPY_NODE_FIELD(appendplans);
+       COPY_SCALAR_FIELD(isTarget);
 
        return newnode;
 }
 
 
-/* ----------------
- *             CopyScanFields
+/*
+ * CopyScanFields
  *
  *             This function copies the fields of the Scan node.  It is used by
  *             all the copy functions for classes which inherit from Scan.
- * ----------------
  */
 static void
 CopyScanFields(Scan *from, Scan *newnode)
 {
-       newnode->scanrelid = from->scanrelid;
-       return;
+       CopyPlanFields((Plan *) from, (Plan *) newnode);
+
+       COPY_SCALAR_FIELD(scanrelid);
 }
 
-/* ----------------
- *             _copyScan
- * ----------------
+/*
+ * _copyScan
  */
 static Scan *
 _copyScan(Scan *from)
@@ -203,15 +224,13 @@ _copyScan(Scan *from)
        /*
         * copy node superclass fields
         */
-       CopyPlanFields((Plan *) from, (Plan *) newnode);
        CopyScanFields((Scan *) from, (Scan *) newnode);
 
        return newnode;
 }
 
-/* ----------------
- *             _copySeqScan
- * ----------------
+/*
+ * _copySeqScan
  */
 static SeqScan *
 _copySeqScan(SeqScan *from)
@@ -221,15 +240,13 @@ _copySeqScan(SeqScan *from)
        /*
         * copy node superclass fields
         */
-       CopyPlanFields((Plan *) from, (Plan *) newnode);
        CopyScanFields((Scan *) from, (Scan *) newnode);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyIndexScan
- * ----------------
+/*
+ * _copyIndexScan
  */
 static IndexScan *
 _copyIndexScan(IndexScan *from)
@@ -239,34 +256,25 @@ _copyIndexScan(IndexScan *from)
        /*
         * copy node superclass fields
         */
-       CopyPlanFields((Plan *) from, (Plan *) newnode);
        CopyScanFields((Scan *) from, (Scan *) newnode);
 
        /*
         * copy remainder of node
         */
-       newnode->indxid = listCopy(from->indxid);
-       Node_Copy(from, newnode, indxqual);
-       Node_Copy(from, newnode, indxqualorig);
-       newnode->indxorderdir = from->indxorderdir;
+       COPY_INTLIST_FIELD(indxid);
+       COPY_NODE_FIELD(indxqual);
+       COPY_NODE_FIELD(indxqualorig);
+       COPY_SCALAR_FIELD(indxorderdir);
 
-       /*
-        * We must add subplans in index quals to the new plan's subPlan list
-        */
-       if (from->scan.plan.subPlan != NIL)
-       {
-               newnode->scan.plan.subPlan = nconc(newnode->scan.plan.subPlan,
-                                                         pull_subplans((Node *) newnode->indxqual));
-               newnode->scan.plan.subPlan = nconc(newnode->scan.plan.subPlan,
-                                                 pull_subplans((Node *) newnode->indxqualorig));
-       }
+       /* subPlan list must point to subplans in the new subtree, not the old */
+       FIX_SUBPLAN_LINKS(scan.plan.subPlan, indxqual);
+       FIX_SUBPLAN_LINKS(scan.plan.subPlan, indxqualorig);
 
        return newnode;
 }
 
-/* ----------------
- *                             _copyTidScan
- * ----------------
+/*
+ * _copyTidScan
  */
 static TidScan *
 _copyTidScan(TidScan *from)
@@ -276,21 +284,22 @@ _copyTidScan(TidScan *from)
        /*
         * copy node superclass fields
         */
-       CopyPlanFields((Plan *) from, (Plan *) newnode);
        CopyScanFields((Scan *) from, (Scan *) newnode);
 
        /*
         * copy remainder of node
         */
-       newnode->needRescan = from->needRescan;
-       Node_Copy(from, newnode, tideval);
+       COPY_SCALAR_FIELD(needRescan);
+       COPY_NODE_FIELD(tideval);
+
+       /* subPlan list must point to subplans in the new subtree, not the old */
+       FIX_SUBPLAN_LINKS(scan.plan.subPlan, tideval);
 
        return newnode;
 }
 
-/* ----------------
- *             _copySubqueryScan
- * ----------------
+/*
+ * _copySubqueryScan
  */
 static SubqueryScan *
 _copySubqueryScan(SubqueryScan *from)
@@ -300,20 +309,18 @@ _copySubqueryScan(SubqueryScan *from)
        /*
         * copy node superclass fields
         */
-       CopyPlanFields((Plan *) from, (Plan *) newnode);
        CopyScanFields((Scan *) from, (Scan *) newnode);
 
        /*
         * copy remainder of node
         */
-       Node_Copy(from, newnode, subplan);
+       COPY_NODE_FIELD(subplan);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyFunctionScan
- * ----------------
+/*
+ * _copyFunctionScan
  */
 static FunctionScan *
 _copyFunctionScan(FunctionScan *from)
@@ -323,34 +330,32 @@ _copyFunctionScan(FunctionScan *from)
        /*
         * copy node superclass fields
         */
-       CopyPlanFields((Plan *) from, (Plan *) newnode);
        CopyScanFields((Scan *) from, (Scan *) newnode);
 
        return newnode;
 }
 
-/* ----------------
- *             CopyJoinFields
+/*
+ * CopyJoinFields
  *
  *             This function copies the fields of the Join node.  It is used by
  *             all the copy functions for classes which inherit from Join.
- * ----------------
  */
 static void
 CopyJoinFields(Join *from, Join *newnode)
 {
-       newnode->jointype = from->jointype;
-       Node_Copy(from, newnode, joinqual);
+       CopyPlanFields((Plan *) from, (Plan *) newnode);
+
+       COPY_SCALAR_FIELD(jointype);
+       COPY_NODE_FIELD(joinqual);
+
        /* subPlan list must point to subplans in the new subtree, not the old */
-       if (from->plan.subPlan != NIL)
-               newnode->plan.subPlan = nconc(newnode->plan.subPlan,
-                                                         pull_subplans((Node *) newnode->joinqual));
+       FIX_SUBPLAN_LINKS(plan.subPlan, joinqual);
 }
 
 
-/* ----------------
- *             _copyJoin
- * ----------------
+/*
+ * _copyJoin
  */
 static Join *
 _copyJoin(Join *from)
@@ -360,16 +365,14 @@ _copyJoin(Join *from)
        /*
         * copy node superclass fields
         */
-       CopyPlanFields((Plan *) from, (Plan *) newnode);
        CopyJoinFields(from, newnode);
 
        return newnode;
 }
 
 
-/* ----------------
- *             _copyNestLoop
- * ----------------
+/*
+ * _copyNestLoop
  */
 static NestLoop *
 _copyNestLoop(NestLoop *from)
@@ -379,16 +382,14 @@ _copyNestLoop(NestLoop *from)
        /*
         * copy node superclass fields
         */
-       CopyPlanFields((Plan *) from, (Plan *) newnode);
        CopyJoinFields((Join *) from, (Join *) newnode);
 
        return newnode;
 }
 
 
-/* ----------------
- *             _copyMergeJoin
- * ----------------
+/*
+ * _copyMergeJoin
  */
 static MergeJoin *
 _copyMergeJoin(MergeJoin *from)
@@ -398,27 +399,21 @@ _copyMergeJoin(MergeJoin *from)
        /*
         * copy node superclass fields
         */
-       CopyPlanFields((Plan *) from, (Plan *) newnode);
        CopyJoinFields((Join *) from, (Join *) newnode);
 
        /*
         * copy remainder of node
         */
-       Node_Copy(from, newnode, mergeclauses);
+       COPY_NODE_FIELD(mergeclauses);
 
-       /*
-        * We must add subplans in mergeclauses to the new plan's subPlan list
-        */
-       if (from->join.plan.subPlan != NIL)
-               newnode->join.plan.subPlan = nconc(newnode->join.plan.subPlan,
-                                                 pull_subplans((Node *) newnode->mergeclauses));
+       /* subPlan list must point to subplans in the new subtree, not the old */
+       FIX_SUBPLAN_LINKS(join.plan.subPlan, mergeclauses);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyHashJoin
- * ----------------
+/*
+ * _copyHashJoin
  */
 static HashJoin *
 _copyHashJoin(HashJoin *from)
@@ -428,29 +423,23 @@ _copyHashJoin(HashJoin *from)
        /*
         * copy node superclass fields
         */
-       CopyPlanFields((Plan *) from, (Plan *) newnode);
        CopyJoinFields((Join *) from, (Join *) newnode);
 
        /*
         * copy remainder of node
         */
-       Node_Copy(from, newnode, hashclauses);
-       newnode->hashjoinop = from->hashjoinop;
+       COPY_NODE_FIELD(hashclauses);
+       COPY_SCALAR_FIELD(hashjoinop);
 
-       /*
-        * We must add subplans in hashclauses to the new plan's subPlan list
-        */
-       if (from->join.plan.subPlan != NIL)
-               newnode->join.plan.subPlan = nconc(newnode->join.plan.subPlan,
-                                                  pull_subplans((Node *) newnode->hashclauses));
+       /* subPlan list must point to subplans in the new subtree, not the old */
+       FIX_SUBPLAN_LINKS(join.plan.subPlan, hashclauses);
 
        return newnode;
 }
 
 
-/* ----------------
- *             _copyMaterial
- * ----------------
+/*
+ * _copyMaterial
  */
 static Material *
 _copyMaterial(Material *from)
@@ -466,9 +455,8 @@ _copyMaterial(Material *from)
 }
 
 
-/* ----------------
- *             _copySort
- * ----------------
+/*
+ * _copySort
  */
 static Sort *
 _copySort(Sort *from)
@@ -480,15 +468,14 @@ _copySort(Sort *from)
         */
        CopyPlanFields((Plan *) from, (Plan *) newnode);
 
-       newnode->keycount = from->keycount;
+       COPY_SCALAR_FIELD(keycount);
 
        return newnode;
 }
 
 
-/* ----------------
- *             _copyGroup
- * ----------------
+/*
+ * _copyGroup
  */
 static Group *
 _copyGroup(Group *from)
@@ -497,17 +484,14 @@ _copyGroup(Group *from)
 
        CopyPlanFields((Plan *) from, (Plan *) newnode);
 
-       newnode->numCols = from->numCols;
-       newnode->grpColIdx = palloc(from->numCols * sizeof(AttrNumber));
-       memcpy(newnode->grpColIdx, from->grpColIdx,
-                  from->numCols * sizeof(AttrNumber));
+       COPY_SCALAR_FIELD(numCols);
+       COPY_POINTER_FIELD(grpColIdx, from->numCols * sizeof(AttrNumber));
 
        return newnode;
 }
 
-/* ---------------
- *     _copyAgg
- * --------------
+/*
+ * _copyAgg
  */
 static Agg *
 _copyAgg(Agg *from)
@@ -516,37 +500,17 @@ _copyAgg(Agg *from)
 
        CopyPlanFields((Plan *) from, (Plan *) newnode);
 
-       newnode->aggstrategy = from->aggstrategy;
-       newnode->numCols = from->numCols;
+       COPY_SCALAR_FIELD(aggstrategy);
+       COPY_SCALAR_FIELD(numCols);
        if (from->numCols > 0)
-       {
-               newnode->grpColIdx = palloc(from->numCols * sizeof(AttrNumber));
-               memcpy(newnode->grpColIdx, from->grpColIdx,
-                          from->numCols * sizeof(AttrNumber));
-       }
-       newnode->numGroups = from->numGroups;
-
-       return newnode;
-}
-
-/* ---------------
- *     _copyGroupClause
- * --------------
- */
-static GroupClause *
-_copyGroupClause(GroupClause *from)
-{
-       GroupClause *newnode = makeNode(GroupClause);
-
-       newnode->tleSortGroupRef = from->tleSortGroupRef;
-       newnode->sortop = from->sortop;
+               COPY_POINTER_FIELD(grpColIdx, from->numCols * sizeof(AttrNumber));
+       COPY_SCALAR_FIELD(numGroups);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyUnique
- * ----------------
+/*
+ * _copyUnique
  */
 static Unique *
 _copyUnique(Unique *from)
@@ -561,16 +525,14 @@ _copyUnique(Unique *from)
        /*
         * copy remainder of node
         */
-       newnode->numCols = from->numCols;
-       newnode->uniqColIdx = palloc(from->numCols * sizeof(AttrNumber));
-       memcpy(newnode->uniqColIdx, from->uniqColIdx, from->numCols * sizeof(AttrNumber));
+       COPY_SCALAR_FIELD(numCols);
+       COPY_POINTER_FIELD(uniqColIdx, from->numCols * sizeof(AttrNumber));
 
        return newnode;
 }
 
-/* ----------------
- *             _copySetOp
- * ----------------
+/*
+ * _copySetOp
  */
 static SetOp *
 _copySetOp(SetOp *from)
@@ -585,18 +547,16 @@ _copySetOp(SetOp *from)
        /*
         * copy remainder of node
         */
-       newnode->cmd = from->cmd;
-       newnode->numCols = from->numCols;
-       newnode->dupColIdx = palloc(from->numCols * sizeof(AttrNumber));
-       memcpy(newnode->dupColIdx, from->dupColIdx, from->numCols * sizeof(AttrNumber));
-       newnode->flagColIdx = from->flagColIdx;
+       COPY_SCALAR_FIELD(cmd);
+       COPY_SCALAR_FIELD(numCols);
+       COPY_POINTER_FIELD(dupColIdx, from->numCols * sizeof(AttrNumber));
+       COPY_SCALAR_FIELD(flagColIdx);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyLimit
- * ----------------
+/*
+ * _copyLimit
  */
 static Limit *
 _copyLimit(Limit *from)
@@ -611,15 +571,14 @@ _copyLimit(Limit *from)
        /*
         * copy remainder of node
         */
-       Node_Copy(from, newnode, limitOffset);
-       Node_Copy(from, newnode, limitCount);
+       COPY_NODE_FIELD(limitOffset);
+       COPY_NODE_FIELD(limitCount);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyHash
- * ----------------
+/*
+ * _copyHash
  */
 static Hash *
 _copyHash(Hash *from)
@@ -634,7 +593,9 @@ _copyHash(Hash *from)
        /*
         * copy remainder of node
         */
-       Node_Copy(from, newnode, hashkey);
+       COPY_NODE_FIELD(hashkey);
+
+       /* XXX could the hashkey contain subplans?  Not at present... */
 
        return newnode;
 }
@@ -644,12 +605,12 @@ _copySubPlan(SubPlan *from)
 {
        SubPlan    *newnode = makeNode(SubPlan);
 
-       Node_Copy(from, newnode, plan);
-       newnode->plan_id = from->plan_id;
-       Node_Copy(from, newnode, rtable);
-       newnode->setParam = listCopy(from->setParam);
-       newnode->parParam = listCopy(from->parParam);
-       Node_Copy(from, newnode, sublink);
+       COPY_NODE_FIELD(plan);
+       COPY_SCALAR_FIELD(plan_id);
+       COPY_NODE_FIELD(rtable);
+       COPY_INTLIST_FIELD(setParam);
+       COPY_INTLIST_FIELD(parParam);
+       COPY_NODE_FIELD(sublink);
 
        /* do not copy execution state */
        newnode->needShutdown = false;
@@ -663,24 +624,22 @@ _copySubPlan(SubPlan *from)
  * ****************************************************************
  */
 
-/* ----------------
- *             _copyResdom
- * ----------------
+/*
+ * _copyResdom
  */
 static Resdom *
 _copyResdom(Resdom *from)
 {
        Resdom     *newnode = makeNode(Resdom);
 
-       newnode->resno = from->resno;
-       newnode->restype = from->restype;
-       newnode->restypmod = from->restypmod;
-       if (from->resname != NULL)
-               newnode->resname = pstrdup(from->resname);
-       newnode->ressortgroupref = from->ressortgroupref;
-       newnode->reskey = from->reskey;
-       newnode->reskeyop = from->reskeyop;
-       newnode->resjunk = from->resjunk;
+       COPY_SCALAR_FIELD(resno);
+       COPY_SCALAR_FIELD(restype);
+       COPY_SCALAR_FIELD(restypmod);
+       COPY_STRING_FIELD(resname);
+       COPY_SCALAR_FIELD(ressortgroupref);
+       COPY_SCALAR_FIELD(reskey);
+       COPY_SCALAR_FIELD(reskeyop);
+       COPY_SCALAR_FIELD(resjunk);
 
        return newnode;
 }
@@ -690,112 +649,105 @@ _copyFjoin(Fjoin *from)
 {
        Fjoin      *newnode = makeNode(Fjoin);
 
-       /*
-        * copy node superclass fields
-        */
+       COPY_SCALAR_FIELD(fj_initialized);
+       COPY_SCALAR_FIELD(fj_nNodes);
+       COPY_NODE_FIELD(fj_innerNode);
+       COPY_POINTER_FIELD(fj_results, from->fj_nNodes * sizeof(Datum));
+       COPY_POINTER_FIELD(fj_alwaysDone, from->fj_nNodes * sizeof(bool));
 
-       newnode->fj_initialized = from->fj_initialized;
-       newnode->fj_nNodes = from->fj_nNodes;
+       return newnode;
+}
 
-       Node_Copy(from, newnode, fj_innerNode);
+static Alias *
+_copyAlias(Alias *from)
+{
+       Alias      *newnode = makeNode(Alias);
 
-       newnode->fj_results = (DatumPtr)
-               palloc((from->fj_nNodes) * sizeof(Datum));
-       memmove(from->fj_results,
-                       newnode->fj_results,
-                       (from->fj_nNodes) * sizeof(Datum));
+       COPY_STRING_FIELD(aliasname);
+       COPY_NODE_FIELD(colnames);
 
-       newnode->fj_alwaysDone = (BoolPtr)
-               palloc((from->fj_nNodes) * sizeof(bool));
-       memmove(from->fj_alwaysDone,
-                       newnode->fj_alwaysDone,
-                       (from->fj_nNodes) * sizeof(bool));
+       return newnode;
+}
 
+static RangeVar *
+_copyRangeVar(RangeVar *from)
+{
+       RangeVar   *newnode = makeNode(RangeVar);
+
+       COPY_STRING_FIELD(catalogname);
+       COPY_STRING_FIELD(schemaname);
+       COPY_STRING_FIELD(relname);
+       COPY_SCALAR_FIELD(inhOpt);
+       COPY_SCALAR_FIELD(istemp);
+       COPY_NODE_FIELD(alias);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyExpr
- * ----------------
+/*
+ * _copyExpr
  */
 static Expr *
 _copyExpr(Expr *from)
 {
        Expr       *newnode = makeNode(Expr);
 
-       /*
-        * copy node superclass fields
-        */
-       newnode->typeOid = from->typeOid;
-       newnode->opType = from->opType;
-
-       Node_Copy(from, newnode, oper);
-       Node_Copy(from, newnode, args);
+       COPY_SCALAR_FIELD(typeOid);
+       COPY_SCALAR_FIELD(opType);
+       COPY_NODE_FIELD(oper);
+       COPY_NODE_FIELD(args);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyVar
- * ----------------
+/*
+ * _copyVar
  */
 static Var *
 _copyVar(Var *from)
 {
        Var                *newnode = makeNode(Var);
 
-       /*
-        * copy remainder of node
-        */
-       newnode->varno = from->varno;
-       newnode->varattno = from->varattno;
-       newnode->vartype = from->vartype;
-       newnode->vartypmod = from->vartypmod;
-       newnode->varlevelsup = from->varlevelsup;
-
-       newnode->varnoold = from->varnoold;
-       newnode->varoattno = from->varoattno;
+       COPY_SCALAR_FIELD(varno);
+       COPY_SCALAR_FIELD(varattno);
+       COPY_SCALAR_FIELD(vartype);
+       COPY_SCALAR_FIELD(vartypmod);
+       COPY_SCALAR_FIELD(varlevelsup);
+       COPY_SCALAR_FIELD(varnoold);
+       COPY_SCALAR_FIELD(varoattno);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyOper
- * ----------------
+/*
+ * _copyOper
  */
 static Oper *
 _copyOper(Oper *from)
 {
        Oper       *newnode = makeNode(Oper);
 
-       /*
-        * copy remainder of node
-        */
-       newnode->opno = from->opno;
-       newnode->opid = from->opid;
-       newnode->opresulttype = from->opresulttype;
-       newnode->opretset = from->opretset;
+       COPY_SCALAR_FIELD(opno);
+       COPY_SCALAR_FIELD(opid);
+       COPY_SCALAR_FIELD(opresulttype);
+       COPY_SCALAR_FIELD(opretset);
+
        /* Do not copy the run-time state, if any */
        newnode->op_fcache = NULL;
 
        return newnode;
 }
 
-/* ----------------
- *             _copyConst
- * ----------------
+/*
+ * _copyConst
  */
 static Const *
 _copyConst(Const *from)
 {
        Const      *newnode = makeNode(Const);
 
-       /*
-        * copy remainder of node
-        */
-       newnode->consttype = from->consttype;
-       newnode->constlen = from->constlen;
+       COPY_SCALAR_FIELD(consttype);
+       COPY_SCALAR_FIELD(constlen);
 
        if (from->constbyval || from->constisnull)
        {
@@ -808,141 +760,119 @@ _copyConst(Const *from)
        else
        {
                /*
-                * not passed by value.  We need a palloc'd copy.
+                * passed by reference.  We need a palloc'd copy.
                 */
                newnode->constvalue = datumCopy(from->constvalue,
                                                                                from->constbyval,
                                                                                from->constlen);
        }
 
-       newnode->constisnull = from->constisnull;
-       newnode->constbyval = from->constbyval;
-       newnode->constisset = from->constisset;
-       newnode->constiscast = from->constiscast;
+       COPY_SCALAR_FIELD(constisnull);
+       COPY_SCALAR_FIELD(constbyval);
+       COPY_SCALAR_FIELD(constisset);
+       COPY_SCALAR_FIELD(constiscast);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyParam
- * ----------------
+/*
+ * _copyParam
  */
 static Param *
 _copyParam(Param *from)
 {
        Param      *newnode = makeNode(Param);
 
-       /*
-        * copy remainder of node
-        */
-       newnode->paramkind = from->paramkind;
-       newnode->paramid = from->paramid;
-
-       if (from->paramname != NULL)
-               newnode->paramname = pstrdup(from->paramname);
-       newnode->paramtype = from->paramtype;
+       COPY_SCALAR_FIELD(paramkind);
+       COPY_SCALAR_FIELD(paramid);
+       COPY_STRING_FIELD(paramname);
+       COPY_SCALAR_FIELD(paramtype);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyFunc
- * ----------------
+/*
+ * _copyFunc
  */
 static Func *
 _copyFunc(Func *from)
 {
        Func       *newnode = makeNode(Func);
 
-       /*
-        * copy remainder of node
-        */
-       newnode->funcid = from->funcid;
-       newnode->funcresulttype = from->funcresulttype;
-       newnode->funcretset = from->funcretset;
-       newnode->funcformat = from->funcformat;
+       COPY_SCALAR_FIELD(funcid);
+       COPY_SCALAR_FIELD(funcresulttype);
+       COPY_SCALAR_FIELD(funcretset);
+       COPY_SCALAR_FIELD(funcformat);
+
        /* Do not copy the run-time state, if any */
        newnode->func_fcache = NULL;
 
        return newnode;
 }
 
-/* ----------------
- *             _copyAggref
- * ----------------
+/*
+ * _copyAggref
  */
 static Aggref *
 _copyAggref(Aggref *from)
 {
        Aggref     *newnode = makeNode(Aggref);
 
-       newnode->aggfnoid = from->aggfnoid;
-       newnode->aggtype = from->aggtype;
-       Node_Copy(from, newnode, target);
-       newnode->aggstar = from->aggstar;
-       newnode->aggdistinct = from->aggdistinct;
-       newnode->aggno = from->aggno;           /* probably not needed */
+       COPY_SCALAR_FIELD(aggfnoid);
+       COPY_SCALAR_FIELD(aggtype);
+       COPY_NODE_FIELD(target);
+       COPY_SCALAR_FIELD(aggstar);
+       COPY_SCALAR_FIELD(aggdistinct);
+       COPY_SCALAR_FIELD(aggno);       /* probably not necessary */
 
        return newnode;
 }
 
-/* ----------------
- *             _copySubLink
- * ----------------
+/*
+ * _copySubLink
  */
 static SubLink *
 _copySubLink(SubLink *from)
 {
        SubLink    *newnode = makeNode(SubLink);
 
-       /*
-        * copy remainder of node
-        */
-       newnode->subLinkType = from->subLinkType;
-       newnode->useor = from->useor;
-       Node_Copy(from, newnode, lefthand);
-       Node_Copy(from, newnode, oper);
-       Node_Copy(from, newnode, subselect);
+       COPY_SCALAR_FIELD(subLinkType);
+       COPY_SCALAR_FIELD(useor);
+       COPY_NODE_FIELD(lefthand);
+       COPY_NODE_FIELD(oper);
+       COPY_NODE_FIELD(subselect);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyFieldSelect
- * ----------------
+/*
+ * _copyFieldSelect
  */
 static FieldSelect *
 _copyFieldSelect(FieldSelect *from)
 {
        FieldSelect *newnode = makeNode(FieldSelect);
 
-       /*
-        * copy remainder of node
-        */
-       Node_Copy(from, newnode, arg);
-       newnode->fieldnum = from->fieldnum;
-       newnode->resulttype = from->resulttype;
-       newnode->resulttypmod = from->resulttypmod;
+       COPY_NODE_FIELD(arg);
+       COPY_SCALAR_FIELD(fieldnum);
+       COPY_SCALAR_FIELD(resulttype);
+       COPY_SCALAR_FIELD(resulttypmod);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyRelabelType
- * ----------------
+/*
+ * _copyRelabelType
  */
 static RelabelType *
 _copyRelabelType(RelabelType *from)
 {
        RelabelType *newnode = makeNode(RelabelType);
 
-       /*
-        * copy remainder of node
-        */
-       Node_Copy(from, newnode, arg);
-       newnode->resulttype = from->resulttype;
-       newnode->resulttypmod = from->resulttypmod;
-       newnode->relabelformat = from->relabelformat;
+       COPY_NODE_FIELD(arg);
+       COPY_SCALAR_FIELD(resulttype);
+       COPY_SCALAR_FIELD(resulttypmod);
+       COPY_SCALAR_FIELD(relabelformat);
 
        return newnode;
 }
@@ -952,18 +882,7 @@ _copyRangeTblRef(RangeTblRef *from)
 {
        RangeTblRef *newnode = makeNode(RangeTblRef);
 
-       newnode->rtindex = from->rtindex;
-
-       return newnode;
-}
-
-static FromExpr *
-_copyFromExpr(FromExpr *from)
-{
-       FromExpr   *newnode = makeNode(FromExpr);
-
-       Node_Copy(from, newnode, fromlist);
-       Node_Copy(from, newnode, quals);
+       COPY_SCALAR_FIELD(rtindex);
 
        return newnode;
 }
@@ -973,114 +892,25 @@ _copyJoinExpr(JoinExpr *from)
 {
        JoinExpr   *newnode = makeNode(JoinExpr);
 
-       newnode->jointype = from->jointype;
-       newnode->isNatural = from->isNatural;
-       Node_Copy(from, newnode, larg);
-       Node_Copy(from, newnode, rarg);
-       Node_Copy(from, newnode, using);
-       Node_Copy(from, newnode, quals);
-       Node_Copy(from, newnode, alias);
-       newnode->rtindex = from->rtindex;
-
-       return newnode;
-}
-
-static CaseExpr *
-_copyCaseExpr(CaseExpr *from)
-{
-       CaseExpr   *newnode = makeNode(CaseExpr);
-
-       /*
-        * copy remainder of node
-        */
-       newnode->casetype = from->casetype;
-
-       Node_Copy(from, newnode, arg);
-       Node_Copy(from, newnode, args);
-       Node_Copy(from, newnode, defresult);
-
-       return newnode;
-}
-
-static CaseWhen *
-_copyCaseWhen(CaseWhen *from)
-{
-       CaseWhen   *newnode = makeNode(CaseWhen);
-
-       /*
-        * copy remainder of node
-        */
-       Node_Copy(from, newnode, expr);
-       Node_Copy(from, newnode, result);
+       COPY_SCALAR_FIELD(jointype);
+       COPY_SCALAR_FIELD(isNatural);
+       COPY_NODE_FIELD(larg);
+       COPY_NODE_FIELD(rarg);
+       COPY_NODE_FIELD(using);
+       COPY_NODE_FIELD(quals);
+       COPY_NODE_FIELD(alias);
+       COPY_SCALAR_FIELD(rtindex);
 
        return newnode;
 }
 
-static NullTest *
-_copyNullTest(NullTest *from)
-{
-       NullTest   *newnode = makeNode(NullTest);
-
-       /*
-        * copy remainder of node
-        */
-       Node_Copy(from, newnode, arg);
-       newnode->nulltesttype = from->nulltesttype;
-
-       return newnode;
-}
-
-static BooleanTest *
-_copyBooleanTest(BooleanTest *from)
-{
-       BooleanTest *newnode = makeNode(BooleanTest);
-
-       /*
-        * copy remainder of node
-        */
-       Node_Copy(from, newnode, arg);
-       newnode->booltesttype = from->booltesttype;
-
-       return newnode;
-}
-
-static ConstraintTest *
-_copyConstraintTest(ConstraintTest *from)
-{
-       ConstraintTest *newnode = makeNode(ConstraintTest);
-
-       /*
-        * copy remainder of node
-        */
-       Node_Copy(from, newnode, arg);
-       newnode->testtype = from->testtype;
-       if (from->name)
-               newnode->name = pstrdup(from->name);
-       if (from->domname)
-               newnode->domname = pstrdup(from->domname);
-       Node_Copy(from, newnode, check_expr);
-
-       return newnode;
-}
-
-static ConstraintTestValue *
-_copyConstraintTestValue(ConstraintTestValue *from)
+static FromExpr *
+_copyFromExpr(FromExpr *from)
 {
-       ConstraintTestValue *newnode = makeNode(ConstraintTestValue);
-
-       /*
-        * copy remainder of node
-        */
-       newnode->typeId = from->typeId;
-       newnode->typeMod = from->typeMod;
-
-       return newnode;
-}
+       FromExpr   *newnode = makeNode(FromExpr);
 
-static DomainConstraintValue *
-_copyDomainConstraintValue(DomainConstraintValue *from)
-{
-       DomainConstraintValue *newnode = makeNode(DomainConstraintValue);
+       COPY_NODE_FIELD(fromlist);
+       COPY_NODE_FIELD(quals);
 
        return newnode;
 }
@@ -1090,130 +920,112 @@ _copyArrayRef(ArrayRef *from)
 {
        ArrayRef   *newnode = makeNode(ArrayRef);
 
-       /*
-        * copy remainder of node
-        */
-       newnode->refrestype = from->refrestype;
-       newnode->refattrlength = from->refattrlength;
-       newnode->refelemlength = from->refelemlength;
-       newnode->refelembyval = from->refelembyval;
-       newnode->refelemalign = from->refelemalign;
-
-       Node_Copy(from, newnode, refupperindexpr);
-       Node_Copy(from, newnode, reflowerindexpr);
-       Node_Copy(from, newnode, refexpr);
-       Node_Copy(from, newnode, refassgnexpr);
+       COPY_SCALAR_FIELD(refrestype);
+       COPY_SCALAR_FIELD(refattrlength);
+       COPY_SCALAR_FIELD(refelemlength);
+       COPY_SCALAR_FIELD(refelembyval);
+       COPY_SCALAR_FIELD(refelemalign);
+       COPY_NODE_FIELD(refupperindexpr);
+       COPY_NODE_FIELD(reflowerindexpr);
+       COPY_NODE_FIELD(refexpr);
+       COPY_NODE_FIELD(refassgnexpr);
 
        return newnode;
 }
 
 /* ****************************************************************
  *                                             relation.h copy functions
+ *
+ * XXX the code to copy RelOptInfo and Path nodes is really completely bogus,
+ * because it makes no attempt to deal with multiple links from RelOptInfo
+ * to Paths, nor with back-links from Paths to their parent RelOptInfo.
+ * Currently, since we never actually try to copy a RelOptInfo, this is okay.
  * ****************************************************************
  */
 
-/* ----------------
- *             _copyRelOptInfo
- * ----------------
+/*
+ * _copyRelOptInfo
  */
 static RelOptInfo *
 _copyRelOptInfo(RelOptInfo *from)
 {
        RelOptInfo *newnode = makeNode(RelOptInfo);
 
-       newnode->reloptkind = from->reloptkind;
-
-       newnode->relids = listCopy(from->relids);
-
-       newnode->rows = from->rows;
-       newnode->width = from->width;
-
-       Node_Copy(from, newnode, targetlist);
-       Node_Copy(from, newnode, pathlist);
+       COPY_SCALAR_FIELD(reloptkind);
+       COPY_INTLIST_FIELD(relids);
+       COPY_SCALAR_FIELD(rows);
+       COPY_SCALAR_FIELD(width);
+       COPY_NODE_FIELD(targetlist);
+       COPY_NODE_FIELD(pathlist);
        /* XXX cheapest-path fields should point to members of pathlist? */
-       Node_Copy(from, newnode, cheapest_startup_path);
-       Node_Copy(from, newnode, cheapest_total_path);
-       newnode->pruneable = from->pruneable;
-
-       newnode->rtekind = from->rtekind;
-       Node_Copy(from, newnode, indexlist);
-       newnode->pages = from->pages;
-       newnode->tuples = from->tuples;
-       Node_Copy(from, newnode, subplan);
-
-       newnode->joinrti = from->joinrti;
-       newnode->joinrteids = listCopy(from->joinrteids);
-
-       Node_Copy(from, newnode, baserestrictinfo);
-       newnode->baserestrictcost = from->baserestrictcost;
-       newnode->outerjoinset = listCopy(from->outerjoinset);
-       Node_Copy(from, newnode, joininfo);
-
-       newnode->index_outer_relids = listCopy(from->index_outer_relids);
-       Node_Copy(from, newnode, index_inner_paths);
+       COPY_NODE_FIELD(cheapest_startup_path);
+       COPY_NODE_FIELD(cheapest_total_path);
+       COPY_SCALAR_FIELD(pruneable);
+       COPY_SCALAR_FIELD(rtekind);
+       COPY_NODE_FIELD(indexlist);
+       COPY_SCALAR_FIELD(pages);
+       COPY_SCALAR_FIELD(tuples);
+       COPY_NODE_FIELD(subplan);
+       COPY_SCALAR_FIELD(joinrti);
+       COPY_INTLIST_FIELD(joinrteids);
+       COPY_NODE_FIELD(baserestrictinfo);
+       COPY_SCALAR_FIELD(baserestrictcost);
+       COPY_INTLIST_FIELD(outerjoinset);
+       COPY_NODE_FIELD(joininfo);
+       COPY_INTLIST_FIELD(index_outer_relids);
+       COPY_NODE_FIELD(index_inner_paths);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyIndexOptInfo
- * ----------------
+/*
+ * _copyIndexOptInfo
  */
 static IndexOptInfo *
 _copyIndexOptInfo(IndexOptInfo *from)
 {
        IndexOptInfo *newnode = makeNode(IndexOptInfo);
-       Size            len;
-
-       newnode->indexoid = from->indexoid;
-       newnode->pages = from->pages;
-       newnode->tuples = from->tuples;
 
-       newnode->ncolumns = from->ncolumns;
-       newnode->nkeys = from->nkeys;
+       COPY_SCALAR_FIELD(indexoid);
+       COPY_SCALAR_FIELD(pages);
+       COPY_SCALAR_FIELD(tuples);
+       COPY_SCALAR_FIELD(ncolumns);
+       COPY_SCALAR_FIELD(nkeys);
 
        if (from->classlist)
        {
                /* copy the trailing zero too */
-               len = (from->ncolumns + 1) * sizeof(Oid);
-               newnode->classlist = (Oid *) palloc(len);
-               memcpy(newnode->classlist, from->classlist, len);
+               COPY_POINTER_FIELD(classlist, (from->ncolumns + 1) * sizeof(Oid));
        }
 
        if (from->indexkeys)
        {
                /* copy the trailing zero too */
-               len = (from->nkeys + 1) * sizeof(int);
-               newnode->indexkeys = (int *) palloc(len);
-               memcpy(newnode->indexkeys, from->indexkeys, len);
+               COPY_POINTER_FIELD(indexkeys, (from->nkeys + 1) * sizeof(int));
        }
 
        if (from->ordering)
        {
                /* copy the trailing zero too */
-               len = (from->ncolumns + 1) * sizeof(Oid);
-               newnode->ordering = (Oid *) palloc(len);
-               memcpy(newnode->ordering, from->ordering, len);
+               COPY_POINTER_FIELD(ordering, (from->ncolumns + 1) * sizeof(Oid));
        }
 
-       newnode->relam = from->relam;
-       newnode->amcostestimate = from->amcostestimate;
-       newnode->indproc = from->indproc;
-       Node_Copy(from, newnode, indpred);
-       newnode->unique = from->unique;
-
-       newnode->outer_relids = listCopy(from->outer_relids);
-       Node_Copy(from, newnode, inner_paths);
+       COPY_SCALAR_FIELD(relam);
+       COPY_SCALAR_FIELD(amcostestimate);
+       COPY_SCALAR_FIELD(indproc);
+       COPY_NODE_FIELD(indpred);
+       COPY_SCALAR_FIELD(unique);
+       COPY_INTLIST_FIELD(outer_relids);
+       COPY_NODE_FIELD(inner_paths);
 
        return newnode;
 }
 
-/* ----------------
- *             CopyPathFields
+/*
+ * CopyPathFields
  *
  *             This function copies the fields of the Path node.  It is used by
  *             all the copy functions for classes which inherit from Path.
- * ----------------
  */
 static void
 CopyPathFields(Path *from, Path *newnode)
@@ -1221,21 +1033,18 @@ CopyPathFields(Path *from, Path *newnode)
        /*
         * Modify the next line, since it causes the copying to cycle (i.e.
         * the parent points right back here! -- JMH, 7/7/92. Old version:
-        * Node_Copy(from, newnode, parent);
+        * COPY_NODE_FIELD(parent);
         */
-       newnode->parent = from->parent;
-
-       newnode->startup_cost = from->startup_cost;
-       newnode->total_cost = from->total_cost;
+       COPY_SCALAR_FIELD(parent);
 
-       newnode->pathtype = from->pathtype;
-
-       Node_Copy(from, newnode, pathkeys);
+       COPY_SCALAR_FIELD(startup_cost);
+       COPY_SCALAR_FIELD(total_cost);
+       COPY_SCALAR_FIELD(pathtype);
+       COPY_NODE_FIELD(pathkeys);
 }
 
-/* ----------------
- *             _copyPath
- * ----------------
+/*
+ * _copyPath
  */
 static Path *
 _copyPath(Path *from)
@@ -1247,9 +1056,8 @@ _copyPath(Path *from)
        return newnode;
 }
 
-/* ----------------
- *             _copyIndexPath
- * ----------------
+/*
+ * _copyIndexPath
  */
 static IndexPath *
 _copyIndexPath(IndexPath *from)
@@ -1257,24 +1065,23 @@ _copyIndexPath(IndexPath *from)
        IndexPath  *newnode = makeNode(IndexPath);
 
        /*
-        * copy the node superclass fields
+        * copy node superclass fields
         */
        CopyPathFields((Path *) from, (Path *) newnode);
 
        /*
         * copy remainder of node
         */
-       Node_Copy(from, newnode, indexinfo);
-       Node_Copy(from, newnode, indexqual);
-       newnode->indexscandir = from->indexscandir;
-       newnode->rows = from->rows;
+       COPY_NODE_FIELD(indexinfo);
+       COPY_NODE_FIELD(indexqual);
+       COPY_SCALAR_FIELD(indexscandir);
+       COPY_SCALAR_FIELD(rows);
 
        return newnode;
 }
 
-/* ----------------
- *                             _copyTidPath
- * ----------------
+/*
+ * _copyTidPath
  */
 static TidPath *
 _copyTidPath(TidPath *from)
@@ -1282,22 +1089,21 @@ _copyTidPath(TidPath *from)
        TidPath    *newnode = makeNode(TidPath);
 
        /*
-        * copy the node superclass fields
+        * copy node superclass fields
         */
        CopyPathFields((Path *) from, (Path *) newnode);
 
        /*
         * copy remainder of node
         */
-       Node_Copy(from, newnode, tideval);
-       newnode->unjoined_relids = listCopy(from->unjoined_relids);
+       COPY_NODE_FIELD(tideval);
+       COPY_INTLIST_FIELD(unjoined_relids);
 
        return newnode;
 }
 
-/* ----------------
- *                             _copyAppendPath
- * ----------------
+/*
+ * _copyAppendPath
  */
 static AppendPath *
 _copyAppendPath(AppendPath *from)
@@ -1305,21 +1111,20 @@ _copyAppendPath(AppendPath *from)
        AppendPath *newnode = makeNode(AppendPath);
 
        /*
-        * copy the node superclass fields
+        * copy node superclass fields
         */
        CopyPathFields((Path *) from, (Path *) newnode);
 
        /*
         * copy remainder of node
         */
-       Node_Copy(from, newnode, subpaths);
+       COPY_NODE_FIELD(subpaths);
 
        return newnode;
 }
 
-/* ----------------
- *                             _copyResultPath
- * ----------------
+/*
+ * _copyResultPath
  */
 static ResultPath *
 _copyResultPath(ResultPath *from)
@@ -1327,38 +1132,38 @@ _copyResultPath(ResultPath *from)
        ResultPath    *newnode = makeNode(ResultPath);
 
        /*
-        * copy the node superclass fields
+        * copy node superclass fields
         */
        CopyPathFields((Path *) from, (Path *) newnode);
 
        /*
         * copy remainder of node
         */
-       Node_Copy(from, newnode, subpath);
-       Node_Copy(from, newnode, constantqual);
+       COPY_NODE_FIELD(subpath);
+       COPY_NODE_FIELD(constantqual);
 
        return newnode;
 }
 
-/* ----------------
- *             CopyJoinPathFields
+/*
+ * CopyJoinPathFields
  *
  *             This function copies the fields of the JoinPath node.  It is used by
  *             all the copy functions for classes which inherit from JoinPath.
- * ----------------
  */
 static void
 CopyJoinPathFields(JoinPath *from, JoinPath *newnode)
 {
-       newnode->jointype = from->jointype;
-       Node_Copy(from, newnode, outerjoinpath);
-       Node_Copy(from, newnode, innerjoinpath);
-       Node_Copy(from, newnode, joinrestrictinfo);
+       CopyPathFields((Path *) from, (Path *) newnode);
+
+       COPY_SCALAR_FIELD(jointype);
+       COPY_NODE_FIELD(outerjoinpath);
+       COPY_NODE_FIELD(innerjoinpath);
+       COPY_NODE_FIELD(joinrestrictinfo);
 }
 
-/* ----------------
- *             _copyNestPath
- * ----------------
+/*
+ * _copyNestPath
  */
 static NestPath *
 _copyNestPath(NestPath *from)
@@ -1366,17 +1171,15 @@ _copyNestPath(NestPath *from)
        NestPath   *newnode = makeNode(NestPath);
 
        /*
-        * copy the node superclass fields
+        * copy node superclass fields
         */
-       CopyPathFields((Path *) from, (Path *) newnode);
        CopyJoinPathFields((JoinPath *) from, (JoinPath *) newnode);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyMergePath
- * ----------------
+/*
+ * _copyMergePath
  */
 static MergePath *
 _copyMergePath(MergePath *from)
@@ -1384,24 +1187,22 @@ _copyMergePath(MergePath *from)
        MergePath  *newnode = makeNode(MergePath);
 
        /*
-        * copy the node superclass fields
+        * copy node superclass fields
         */
-       CopyPathFields((Path *) from, (Path *) newnode);
        CopyJoinPathFields((JoinPath *) from, (JoinPath *) newnode);
 
        /*
-        * copy the remainder of the node
+        * copy remainder of node
         */
-       Node_Copy(from, newnode, path_mergeclauses);
-       Node_Copy(from, newnode, outersortkeys);
-       Node_Copy(from, newnode, innersortkeys);
+       COPY_NODE_FIELD(path_mergeclauses);
+       COPY_NODE_FIELD(outersortkeys);
+       COPY_NODE_FIELD(innersortkeys);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyHashPath
- * ----------------
+/*
+ * _copyHashPath
  */
 static HashPath *
 _copyHashPath(HashPath *from)
@@ -1409,57 +1210,48 @@ _copyHashPath(HashPath *from)
        HashPath   *newnode = makeNode(HashPath);
 
        /*
-        * copy the node superclass fields
+        * copy node superclass fields
         */
-       CopyPathFields((Path *) from, (Path *) newnode);
        CopyJoinPathFields((JoinPath *) from, (JoinPath *) newnode);
 
        /*
         * copy remainder of node
         */
-       Node_Copy(from, newnode, path_hashclauses);
+       COPY_NODE_FIELD(path_hashclauses);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyPathKeyItem
- * ----------------
+/*
+ * _copyPathKeyItem
  */
 static PathKeyItem *
 _copyPathKeyItem(PathKeyItem *from)
 {
        PathKeyItem *newnode = makeNode(PathKeyItem);
 
-       /*
-        * copy remainder of node
-        */
-       Node_Copy(from, newnode, key);
-       newnode->sortop = from->sortop;
+       COPY_NODE_FIELD(key);
+       COPY_SCALAR_FIELD(sortop);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyRestrictInfo
- * ----------------
+/*
+ * _copyRestrictInfo
  */
 static RestrictInfo *
 _copyRestrictInfo(RestrictInfo *from)
 {
        RestrictInfo *newnode = makeNode(RestrictInfo);
 
-       /*
-        * copy remainder of node
-        */
-       Node_Copy(from, newnode, clause);
-       newnode->ispusheddown = from->ispusheddown;
-       Node_Copy(from, newnode, subclauseindices);
-       newnode->eval_cost = from->eval_cost;
-       newnode->this_selec = from->this_selec;
-       newnode->mergejoinoperator = from->mergejoinoperator;
-       newnode->left_sortop = from->left_sortop;
-       newnode->right_sortop = from->right_sortop;
+       COPY_NODE_FIELD(clause);
+       COPY_SCALAR_FIELD(ispusheddown);
+       COPY_NODE_FIELD(subclauseindices); /* XXX probably bad */
+       COPY_SCALAR_FIELD(eval_cost);
+       COPY_SCALAR_FIELD(this_selec);
+       COPY_SCALAR_FIELD(mergejoinoperator);
+       COPY_SCALAR_FIELD(left_sortop);
+       COPY_SCALAR_FIELD(right_sortop);
 
        /*
         * Do not copy pathkeys, since they'd not be canonical in a copied
@@ -1467,48 +1259,41 @@ _copyRestrictInfo(RestrictInfo *from)
         */
        newnode->left_pathkey = NIL;
        newnode->right_pathkey = NIL;
-       newnode->left_mergescansel = from->left_mergescansel;
-       newnode->right_mergescansel = from->right_mergescansel;
-       newnode->hashjoinoperator = from->hashjoinoperator;
-       newnode->left_bucketsize = from->left_bucketsize;
-       newnode->right_bucketsize = from->right_bucketsize;
+
+       COPY_SCALAR_FIELD(left_mergescansel);
+       COPY_SCALAR_FIELD(right_mergescansel);
+       COPY_SCALAR_FIELD(hashjoinoperator);
+       COPY_SCALAR_FIELD(left_bucketsize);
+       COPY_SCALAR_FIELD(right_bucketsize);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyJoinInfo
- * ----------------
+/*
+ * _copyJoinInfo
  */
 static JoinInfo *
 _copyJoinInfo(JoinInfo *from)
 {
        JoinInfo   *newnode = makeNode(JoinInfo);
 
-       /*
-        * copy remainder of node
-        */
-       newnode->unjoined_relids = listCopy(from->unjoined_relids);
-       Node_Copy(from, newnode, jinfo_restrictinfo);
+       COPY_INTLIST_FIELD(unjoined_relids);
+       COPY_NODE_FIELD(jinfo_restrictinfo);
 
        return newnode;
 }
 
-/* ----------------
- *             _copyInnerIndexscanInfo
- * ----------------
+/*
+ * _copyInnerIndexscanInfo
  */
 static InnerIndexscanInfo *
 _copyInnerIndexscanInfo(InnerIndexscanInfo *from)
 {
        InnerIndexscanInfo   *newnode = makeNode(InnerIndexscanInfo);
 
-       /*
-        * copy remainder of node
-        */
-       newnode->other_relids = listCopy(from->other_relids);
-       newnode->isouterjoin = from->isouterjoin;
-       Node_Copy(from, newnode, best_innerpath);
+       COPY_INTLIST_FIELD(other_relids);
+       COPY_SCALAR_FIELD(isouterjoin);
+       COPY_NODE_FIELD(best_innerpath);
 
        return newnode;
 }
@@ -1523,9 +1308,10 @@ _copyTargetEntry(TargetEntry *from)
 {
        TargetEntry *newnode = makeNode(TargetEntry);
 
-       Node_Copy(from, newnode, resdom);
-       Node_Copy(from, newnode, fjoin);
-       Node_Copy(from, newnode, expr);
+       COPY_NODE_FIELD(resdom);
+       COPY_NODE_FIELD(fjoin);
+       COPY_NODE_FIELD(expr);
+
        return newnode;
 }
 
@@ -1534,20 +1320,20 @@ _copyRangeTblEntry(RangeTblEntry *from)
 {
        RangeTblEntry *newnode = makeNode(RangeTblEntry);
 
-       newnode->rtekind = from->rtekind;
-       newnode->relid = from->relid;
-       Node_Copy(from, newnode, subquery);
-       Node_Copy(from, newnode, funcexpr);
-       Node_Copy(from, newnode, coldeflist);
-       newnode->jointype = from->jointype;
-       Node_Copy(from, newnode, joinaliasvars);
-       Node_Copy(from, newnode, alias);
-       Node_Copy(from, newnode, eref);
-       newnode->inh = from->inh;
-       newnode->inFromCl = from->inFromCl;
-       newnode->checkForRead = from->checkForRead;
-       newnode->checkForWrite = from->checkForWrite;
-       newnode->checkAsUser = from->checkAsUser;
+       COPY_SCALAR_FIELD(rtekind);
+       COPY_SCALAR_FIELD(relid);
+       COPY_NODE_FIELD(subquery);
+       COPY_NODE_FIELD(funcexpr);
+       COPY_NODE_FIELD(coldeflist);
+       COPY_SCALAR_FIELD(jointype);
+       COPY_NODE_FIELD(joinaliasvars);
+       COPY_NODE_FIELD(alias);
+       COPY_NODE_FIELD(eref);
+       COPY_SCALAR_FIELD(inh);
+       COPY_SCALAR_FIELD(inFromCl);
+       COPY_SCALAR_FIELD(checkForRead);
+       COPY_SCALAR_FIELD(checkForWrite);
+       COPY_SCALAR_FIELD(checkAsUser);
 
        return newnode;
 }
@@ -1557,17 +1343,16 @@ _copyFkConstraint(FkConstraint *from)
 {
        FkConstraint *newnode = makeNode(FkConstraint);
 
-       if (from->constr_name)
-               newnode->constr_name = pstrdup(from->constr_name);
-       Node_Copy(from, newnode, pktable);
-       Node_Copy(from, newnode, fk_attrs);
-       Node_Copy(from, newnode, pk_attrs);
-       newnode->fk_matchtype = from->fk_matchtype;
-       newnode->fk_upd_action = from->fk_upd_action;
-       newnode->fk_del_action = from->fk_del_action;
-       newnode->deferrable = from->deferrable;
-       newnode->initdeferred = from->initdeferred;
-       newnode->skip_validation = from->skip_validation;
+       COPY_STRING_FIELD(constr_name);
+       COPY_NODE_FIELD(pktable);
+       COPY_NODE_FIELD(fk_attrs);
+       COPY_NODE_FIELD(pk_attrs);
+       COPY_SCALAR_FIELD(fk_matchtype);
+       COPY_SCALAR_FIELD(fk_upd_action);
+       COPY_SCALAR_FIELD(fk_del_action);
+       COPY_SCALAR_FIELD(deferrable);
+       COPY_SCALAR_FIELD(initdeferred);
+       COPY_SCALAR_FIELD(skip_validation);
 
        return newnode;
 }
@@ -1577,8 +1362,19 @@ _copySortClause(SortClause *from)
 {
        SortClause *newnode = makeNode(SortClause);
 
-       newnode->tleSortGroupRef = from->tleSortGroupRef;
-       newnode->sortop = from->sortop;
+       COPY_SCALAR_FIELD(tleSortGroupRef);
+       COPY_SCALAR_FIELD(sortop);
+
+       return newnode;
+}
+
+static GroupClause *
+_copyGroupClause(GroupClause *from)
+{
+       GroupClause *newnode = makeNode(GroupClause);
+
+       COPY_SCALAR_FIELD(tleSortGroupRef);
+       COPY_SCALAR_FIELD(sortop);
 
        return newnode;
 }
@@ -1588,10 +1384,10 @@ _copyAExpr(A_Expr *from)
 {
        A_Expr     *newnode = makeNode(A_Expr);
 
-       newnode->oper = from->oper;
-       Node_Copy(from, newnode, name);
-       Node_Copy(from, newnode, lexpr);
-       Node_Copy(from, newnode, rexpr);
+       COPY_SCALAR_FIELD(oper);
+       COPY_NODE_FIELD(name);
+       COPY_NODE_FIELD(lexpr);
+       COPY_NODE_FIELD(rexpr);
 
        return newnode;
 }
@@ -1601,8 +1397,8 @@ _copyColumnRef(ColumnRef *from)
 {
        ColumnRef  *newnode = makeNode(ColumnRef);
 
-       Node_Copy(from, newnode, fields);
-       Node_Copy(from, newnode, indirection);
+       COPY_NODE_FIELD(fields);
+       COPY_NODE_FIELD(indirection);
 
        return newnode;
 }
@@ -1612,9 +1408,9 @@ _copyParamRef(ParamRef *from)
 {
        ParamRef   *newnode = makeNode(ParamRef);
 
-       newnode->number = from->number;
-       Node_Copy(from, newnode, fields);
-       Node_Copy(from, newnode, indirection);
+       COPY_SCALAR_FIELD(number);
+       COPY_NODE_FIELD(fields);
+       COPY_NODE_FIELD(indirection);
 
        return newnode;
 }
@@ -1625,16 +1421,16 @@ _copyAConst(A_Const *from)
        A_Const    *newnode = makeNode(A_Const);
 
        /* This part must duplicate _copyValue */
-       newnode->val.type = from->val.type;
+       COPY_SCALAR_FIELD(val.type);
        switch (from->val.type)
        {
                case T_Integer:
-                       newnode->val.val.ival = from->val.val.ival;
+                       COPY_SCALAR_FIELD(val.val.ival);
                        break;
                case T_Float:
                case T_String:
                case T_BitString:
-                       newnode->val.val.str = pstrdup(from->val.val.str);
+                       COPY_STRING_FIELD(val.val.str);
                        break;
                case T_Null:
                        /* nothing to do */
@@ -1644,7 +1440,7 @@ _copyAConst(A_Const *from)
                        break;
        }
 
-       Node_Copy(from, newnode, typename);
+       COPY_NODE_FIELD(typename);
 
        return newnode;
 }
@@ -1654,10 +1450,10 @@ _copyFuncCall(FuncCall *from)
 {
        FuncCall   *newnode = makeNode(FuncCall);
 
-       Node_Copy(from, newnode, funcname);
-       Node_Copy(from, newnode, args);
-       newnode->agg_star = from->agg_star;
-       newnode->agg_distinct = from->agg_distinct;
+       COPY_NODE_FIELD(funcname);
+       COPY_NODE_FIELD(args);
+       COPY_SCALAR_FIELD(agg_star);
+       COPY_SCALAR_FIELD(agg_distinct);
 
        return newnode;
 }
@@ -1667,8 +1463,8 @@ _copyAIndices(A_Indices *from)
 {
        A_Indices  *newnode = makeNode(A_Indices);
 
-       Node_Copy(from, newnode, lidx);
-       Node_Copy(from, newnode, uidx);
+       COPY_NODE_FIELD(lidx);
+       COPY_NODE_FIELD(uidx);
 
        return newnode;
 }
@@ -1678,9 +1474,9 @@ _copyExprFieldSelect(ExprFieldSelect *from)
 {
        ExprFieldSelect *newnode = makeNode(ExprFieldSelect);
 
-       Node_Copy(from, newnode, arg);
-       Node_Copy(from, newnode, fields);
-       Node_Copy(from, newnode, indirection);
+       COPY_NODE_FIELD(arg);
+       COPY_NODE_FIELD(fields);
+       COPY_NODE_FIELD(indirection);
 
        return newnode;
 }
@@ -1690,10 +1486,9 @@ _copyResTarget(ResTarget *from)
 {
        ResTarget  *newnode = makeNode(ResTarget);
 
-       if (from->name)
-               newnode->name = pstrdup(from->name);
-       Node_Copy(from, newnode, indirection);
-       Node_Copy(from, newnode, val);
+       COPY_STRING_FIELD(name);
+       COPY_NODE_FIELD(indirection);
+       COPY_NODE_FIELD(val);
 
        return newnode;
 }
@@ -1703,13 +1498,13 @@ _copyTypeName(TypeName *from)
 {
        TypeName   *newnode = makeNode(TypeName);
 
-       Node_Copy(from, newnode, names);
-       newnode->typeid = from->typeid;
-       newnode->timezone = from->timezone;
-       newnode->setof = from->setof;
-       newnode->pct_type = from->pct_type;
-       newnode->typmod = from->typmod;
-       Node_Copy(from, newnode, arrayBounds);
+       COPY_NODE_FIELD(names);
+       COPY_SCALAR_FIELD(typeid);
+       COPY_SCALAR_FIELD(timezone);
+       COPY_SCALAR_FIELD(setof);
+       COPY_SCALAR_FIELD(pct_type);
+       COPY_SCALAR_FIELD(typmod);
+       COPY_NODE_FIELD(arrayBounds);
 
        return newnode;
 }
@@ -1719,38 +1514,8 @@ _copySortGroupBy(SortGroupBy *from)
 {
        SortGroupBy *newnode = makeNode(SortGroupBy);
 
-       Node_Copy(from, newnode, useOp);
-       Node_Copy(from, newnode, node);
-
-       return newnode;
-}
-
-static Alias *
-_copyAlias(Alias *from)
-{
-       Alias      *newnode = makeNode(Alias);
-
-       if (from->aliasname)
-               newnode->aliasname = pstrdup(from->aliasname);
-       Node_Copy(from, newnode, colnames);
-
-       return newnode;
-}
-
-static RangeVar *
-_copyRangeVar(RangeVar *from)
-{
-       RangeVar   *newnode = makeNode(RangeVar);
-
-       if (from->catalogname)
-               newnode->catalogname = pstrdup(from->catalogname);
-       if (from->schemaname)
-               newnode->schemaname = pstrdup(from->schemaname);
-       if (from->relname)
-               newnode->relname = pstrdup(from->relname);
-       newnode->inhOpt = from->inhOpt;
-       newnode->istemp = from->istemp;
-       Node_Copy(from, newnode, alias);
+       COPY_NODE_FIELD(useOp);
+       COPY_NODE_FIELD(node);
 
        return newnode;
 }
@@ -1760,8 +1525,8 @@ _copyRangeSubselect(RangeSubselect *from)
 {
        RangeSubselect *newnode = makeNode(RangeSubselect);
 
-       Node_Copy(from, newnode, subquery);
-       Node_Copy(from, newnode, alias);
+       COPY_NODE_FIELD(subquery);
+       COPY_NODE_FIELD(alias);
 
        return newnode;
 }
@@ -1771,9 +1536,9 @@ _copyRangeFunction(RangeFunction *from)
 {
        RangeFunction *newnode = makeNode(RangeFunction);
 
-       Node_Copy(from, newnode, funccallnode);
-       Node_Copy(from, newnode, alias);
-       Node_Copy(from, newnode, coldeflist);
+       COPY_NODE_FIELD(funccallnode);
+       COPY_NODE_FIELD(alias);
+       COPY_NODE_FIELD(coldeflist);
 
        return newnode;
 }
@@ -1783,8 +1548,8 @@ _copyTypeCast(TypeCast *from)
 {
        TypeCast   *newnode = makeNode(TypeCast);
 
-       Node_Copy(from, newnode, arg);
-       Node_Copy(from, newnode, typename);
+       COPY_NODE_FIELD(arg);
+       COPY_NODE_FIELD(typename);
 
        return newnode;
 }
@@ -1794,11 +1559,10 @@ _copyIndexElem(IndexElem *from)
 {
        IndexElem  *newnode = makeNode(IndexElem);
 
-       if (from->name)
-               newnode->name = pstrdup(from->name);
-       Node_Copy(from, newnode, funcname);
-       Node_Copy(from, newnode, args);
-       Node_Copy(from, newnode, opclass);
+       COPY_STRING_FIELD(name);
+       COPY_NODE_FIELD(funcname);
+       COPY_NODE_FIELD(args);
+       COPY_NODE_FIELD(opclass);
 
        return newnode;
 }
@@ -1808,17 +1572,15 @@ _copyColumnDef(ColumnDef *from)
 {
        ColumnDef  *newnode = makeNode(ColumnDef);
 
-       if (from->colname)
-               newnode->colname = pstrdup(from->colname);
-       Node_Copy(from, newnode, typename);
-       newnode->inhcount = from->inhcount;
-       newnode->is_local = from->is_local;
-       newnode->is_not_null = from->is_not_null;
-       Node_Copy(from, newnode, raw_default);
-       if (from->cooked_default)
-               newnode->cooked_default = pstrdup(from->cooked_default);
-       Node_Copy(from, newnode, constraints);
-       Node_Copy(from, newnode, support);
+       COPY_STRING_FIELD(colname);
+       COPY_NODE_FIELD(typename);
+       COPY_SCALAR_FIELD(inhcount);
+       COPY_SCALAR_FIELD(is_local);
+       COPY_SCALAR_FIELD(is_not_null);
+       COPY_NODE_FIELD(raw_default);
+       COPY_STRING_FIELD(cooked_default);
+       COPY_NODE_FIELD(constraints);
+       COPY_NODE_FIELD(support);
 
        return newnode;
 }
@@ -1828,62 +1590,131 @@ _copyConstraint(Constraint *from)
 {
        Constraint *newnode = makeNode(Constraint);
 
-       newnode->contype = from->contype;
-       if (from->name)
-               newnode->name = pstrdup(from->name);
-       Node_Copy(from, newnode, raw_expr);
-       if (from->cooked_expr)
-               newnode->cooked_expr = pstrdup(from->cooked_expr);
-       Node_Copy(from, newnode, keys);
+       COPY_SCALAR_FIELD(contype);
+       COPY_STRING_FIELD(name);
+       COPY_NODE_FIELD(raw_expr);
+       COPY_STRING_FIELD(cooked_expr);
+       COPY_NODE_FIELD(keys);
 
        return newnode;
 }
 
-static DefElem *
-_copyDefElem(DefElem *from)
+static CaseExpr *
+_copyCaseExpr(CaseExpr *from)
 {
-       DefElem    *newnode = makeNode(DefElem);
+       CaseExpr   *newnode = makeNode(CaseExpr);
 
-       if (from->defname)
-               newnode->defname = pstrdup(from->defname);
-       Node_Copy(from, newnode, arg);
+       COPY_SCALAR_FIELD(casetype);
+       COPY_NODE_FIELD(arg);
+       COPY_NODE_FIELD(args);
+       COPY_NODE_FIELD(defresult);
 
        return newnode;
 }
 
-static Query *
-_copyQuery(Query *from)
+static CaseWhen *
+_copyCaseWhen(CaseWhen *from)
 {
-       Query      *newnode = makeNode(Query);
+       CaseWhen   *newnode = makeNode(CaseWhen);
 
-       newnode->commandType = from->commandType;
-       newnode->querySource = from->querySource;
-       Node_Copy(from, newnode, utilityStmt);
-       newnode->resultRelation = from->resultRelation;
-       Node_Copy(from, newnode, into);
-       newnode->isPortal = from->isPortal;
-       newnode->isBinary = from->isBinary;
-       newnode->hasAggs = from->hasAggs;
-       newnode->hasSubLinks = from->hasSubLinks;
+       COPY_NODE_FIELD(expr);
+       COPY_NODE_FIELD(result);
 
-       Node_Copy(from, newnode, rtable);
-       Node_Copy(from, newnode, jointree);
+       return newnode;
+}
 
-       newnode->rowMarks = listCopy(from->rowMarks);
+static NullTest *
+_copyNullTest(NullTest *from)
+{
+       NullTest   *newnode = makeNode(NullTest);
 
-       Node_Copy(from, newnode, targetList);
+       COPY_NODE_FIELD(arg);
+       COPY_SCALAR_FIELD(nulltesttype);
 
-       Node_Copy(from, newnode, groupClause);
-       Node_Copy(from, newnode, havingQual);
-       Node_Copy(from, newnode, distinctClause);
-       Node_Copy(from, newnode, sortClause);
+       return newnode;
+}
 
-       Node_Copy(from, newnode, limitOffset);
-       Node_Copy(from, newnode, limitCount);
+static BooleanTest *
+_copyBooleanTest(BooleanTest *from)
+{
+       BooleanTest *newnode = makeNode(BooleanTest);
 
-       Node_Copy(from, newnode, setOperations);
+       COPY_NODE_FIELD(arg);
+       COPY_SCALAR_FIELD(booltesttype);
+
+       return newnode;
+}
+
+static ConstraintTest *
+_copyConstraintTest(ConstraintTest *from)
+{
+       ConstraintTest *newnode = makeNode(ConstraintTest);
+
+       COPY_NODE_FIELD(arg);
+       COPY_SCALAR_FIELD(testtype);
+       COPY_STRING_FIELD(name);
+       COPY_STRING_FIELD(domname);
+       COPY_NODE_FIELD(check_expr);
+
+       return newnode;
+}
+
+static DomainConstraintValue *
+_copyDomainConstraintValue(DomainConstraintValue *from)
+{
+       DomainConstraintValue *newnode = makeNode(DomainConstraintValue);
+
+       return newnode;
+}
+
+static ConstraintTestValue *
+_copyConstraintTestValue(ConstraintTestValue *from)
+{
+       ConstraintTestValue *newnode = makeNode(ConstraintTestValue);
 
-       newnode->resultRelations = listCopy(from->resultRelations);
+       COPY_SCALAR_FIELD(typeId);
+       COPY_SCALAR_FIELD(typeMod);
+
+       return newnode;
+}
+
+static DefElem *
+_copyDefElem(DefElem *from)
+{
+       DefElem    *newnode = makeNode(DefElem);
+
+       COPY_STRING_FIELD(defname);
+       COPY_NODE_FIELD(arg);
+
+       return newnode;
+}
+
+static Query *
+_copyQuery(Query *from)
+{
+       Query      *newnode = makeNode(Query);
+
+       COPY_SCALAR_FIELD(commandType);
+       COPY_SCALAR_FIELD(querySource);
+       COPY_NODE_FIELD(utilityStmt);
+       COPY_SCALAR_FIELD(resultRelation);
+       COPY_NODE_FIELD(into);
+       COPY_SCALAR_FIELD(isPortal);
+       COPY_SCALAR_FIELD(isBinary);
+       COPY_SCALAR_FIELD(hasAggs);
+       COPY_SCALAR_FIELD(hasSubLinks);
+       COPY_NODE_FIELD(rtable);
+       COPY_NODE_FIELD(jointree);
+       COPY_INTLIST_FIELD(rowMarks);
+       COPY_NODE_FIELD(targetList);
+       COPY_NODE_FIELD(groupClause);
+       COPY_NODE_FIELD(havingQual);
+       COPY_NODE_FIELD(distinctClause);
+       COPY_NODE_FIELD(sortClause);
+       COPY_NODE_FIELD(limitOffset);
+       COPY_NODE_FIELD(limitCount);
+       COPY_NODE_FIELD(setOperations);
+       COPY_INTLIST_FIELD(resultRelations);
 
        /*
         * We do not copy the planner internal fields: base_rel_list,
@@ -1899,10 +1730,10 @@ _copyInsertStmt(InsertStmt *from)
 {
        InsertStmt *newnode = makeNode(InsertStmt);
 
-       Node_Copy(from, newnode, relation);
-       Node_Copy(from, newnode, cols);
-       Node_Copy(from, newnode, targetList);
-       Node_Copy(from, newnode, selectStmt);
+       COPY_NODE_FIELD(relation);
+       COPY_NODE_FIELD(cols);
+       COPY_NODE_FIELD(targetList);
+       COPY_NODE_FIELD(selectStmt);
 
        return newnode;
 }
@@ -1912,8 +1743,8 @@ _copyDeleteStmt(DeleteStmt *from)
 {
        DeleteStmt *newnode = makeNode(DeleteStmt);
 
-       Node_Copy(from, newnode, relation);
-       Node_Copy(from, newnode, whereClause);
+       COPY_NODE_FIELD(relation);
+       COPY_NODE_FIELD(whereClause);
 
        return newnode;
 }
@@ -1923,10 +1754,10 @@ _copyUpdateStmt(UpdateStmt *from)
 {
        UpdateStmt *newnode = makeNode(UpdateStmt);
 
-       Node_Copy(from, newnode, relation);
-       Node_Copy(from, newnode, targetList);
-       Node_Copy(from, newnode, whereClause);
-       Node_Copy(from, newnode, fromClause);
+       COPY_NODE_FIELD(relation);
+       COPY_NODE_FIELD(targetList);
+       COPY_NODE_FIELD(whereClause);
+       COPY_NODE_FIELD(fromClause);
 
        return newnode;
 }
@@ -1936,25 +1767,24 @@ _copySelectStmt(SelectStmt *from)
 {
        SelectStmt *newnode = makeNode(SelectStmt);
 
-       Node_Copy(from, newnode, distinctClause);
-       Node_Copy(from, newnode, into);
-       Node_Copy(from, newnode, intoColNames);
-       Node_Copy(from, newnode, targetList);
-       Node_Copy(from, newnode, fromClause);
-       Node_Copy(from, newnode, whereClause);
-       Node_Copy(from, newnode, groupClause);
-       Node_Copy(from, newnode, havingClause);
-       Node_Copy(from, newnode, sortClause);
-       if (from->portalname)
-               newnode->portalname = pstrdup(from->portalname);
-       newnode->binary = from->binary;
-       Node_Copy(from, newnode, limitOffset);
-       Node_Copy(from, newnode, limitCount);
-       Node_Copy(from, newnode, forUpdate);
-       newnode->op = from->op;
-       newnode->all = from->all;
-       Node_Copy(from, newnode, larg);
-       Node_Copy(from, newnode, rarg);
+       COPY_NODE_FIELD(distinctClause);
+       COPY_NODE_FIELD(into);
+       COPY_NODE_FIELD(intoColNames);
+       COPY_NODE_FIELD(targetList);
+       COPY_NODE_FIELD(fromClause);
+       COPY_NODE_FIELD(whereClause);
+       COPY_NODE_FIELD(groupClause);
+       COPY_NODE_FIELD(havingClause);
+       COPY_NODE_FIELD(sortClause);
+       COPY_STRING_FIELD(portalname);
+       COPY_SCALAR_FIELD(binary);
+       COPY_NODE_FIELD(limitOffset);
+       COPY_NODE_FIELD(limitCount);
+       COPY_NODE_FIELD(forUpdate);
+       COPY_SCALAR_FIELD(op);
+       COPY_SCALAR_FIELD(all);
+       COPY_NODE_FIELD(larg);
+       COPY_NODE_FIELD(rarg);
 
        return newnode;
 }
@@ -1964,11 +1794,11 @@ _copySetOperationStmt(SetOperationStmt *from)
 {
        SetOperationStmt *newnode = makeNode(SetOperationStmt);
 
-       newnode->op = from->op;
-       newnode->all = from->all;
-       Node_Copy(from, newnode, larg);
-       Node_Copy(from, newnode, rarg);
-       newnode->colTypes = listCopy(from->colTypes);
+       COPY_SCALAR_FIELD(op);
+       COPY_SCALAR_FIELD(all);
+       COPY_NODE_FIELD(larg);
+       COPY_NODE_FIELD(rarg);
+       COPY_INTLIST_FIELD(colTypes);
 
        return newnode;
 }
@@ -1978,12 +1808,11 @@ _copyAlterTableStmt(AlterTableStmt *from)
 {
        AlterTableStmt *newnode = makeNode(AlterTableStmt);
 
-       newnode->subtype = from->subtype;
-       Node_Copy(from, newnode, relation);
-       if (from->name)
-               newnode->name = pstrdup(from->name);
-       Node_Copy(from, newnode, def);
-       newnode->behavior = from->behavior;
+       COPY_SCALAR_FIELD(subtype);
+       COPY_NODE_FIELD(relation);
+       COPY_STRING_FIELD(name);
+       COPY_NODE_FIELD(def);
+       COPY_SCALAR_FIELD(behavior);
 
        return newnode;
 }
@@ -1993,11 +1822,11 @@ _copyGrantStmt(GrantStmt *from)
 {
        GrantStmt  *newnode = makeNode(GrantStmt);
 
-       newnode->is_grant = from->is_grant;
-       newnode->objtype = from->objtype;
-       Node_Copy(from, newnode, objects);
-       newnode->privileges = listCopy(from->privileges);
-       Node_Copy(from, newnode, grantees);
+       COPY_SCALAR_FIELD(is_grant);
+       COPY_SCALAR_FIELD(objtype);
+       COPY_NODE_FIELD(objects);
+       COPY_INTLIST_FIELD(privileges);
+       COPY_NODE_FIELD(grantees);
 
        return newnode;
 }
@@ -2007,10 +1836,8 @@ _copyPrivGrantee(PrivGrantee *from)
 {
        PrivGrantee *newnode = makeNode(PrivGrantee);
 
-       if (from->username)
-               newnode->username = pstrdup(from->username);
-       if (from->groupname)
-               newnode->groupname = pstrdup(from->groupname);
+       COPY_STRING_FIELD(username);
+       COPY_STRING_FIELD(groupname);
 
        return newnode;
 }
@@ -2020,8 +1847,8 @@ _copyFuncWithArgs(FuncWithArgs *from)
 {
        FuncWithArgs *newnode = makeNode(FuncWithArgs);
 
-       Node_Copy(from, newnode, funcname);
-       Node_Copy(from, newnode, funcargs);
+       COPY_NODE_FIELD(funcname);
+       COPY_NODE_FIELD(funcargs);
 
        return newnode;
 }
@@ -2040,8 +1867,7 @@ _copyClosePortalStmt(ClosePortalStmt *from)
 {
        ClosePortalStmt *newnode = makeNode(ClosePortalStmt);
 
-       if (from->portalname)
-               newnode->portalname = pstrdup(from->portalname);
+       COPY_STRING_FIELD(portalname);
 
        return newnode;
 }
@@ -2051,9 +1877,8 @@ _copyClusterStmt(ClusterStmt *from)
 {
        ClusterStmt *newnode = makeNode(ClusterStmt);
 
-       Node_Copy(from, newnode, relation);
-       if (from->indexname)
-               newnode->indexname = pstrdup(from->indexname);
+       COPY_NODE_FIELD(relation);
+       COPY_STRING_FIELD(indexname);
 
        return newnode;
 }
@@ -2063,12 +1888,11 @@ _copyCopyStmt(CopyStmt *from)
 {
        CopyStmt   *newnode = makeNode(CopyStmt);
 
-       Node_Copy(from, newnode, relation);
-       Node_Copy(from, newnode, attlist);
-       newnode->is_from = from->is_from;
-       if (from->filename)
-               newnode->filename = pstrdup(from->filename);
-       Node_Copy(from, newnode, options);
+       COPY_NODE_FIELD(relation);
+       COPY_NODE_FIELD(attlist);
+       COPY_SCALAR_FIELD(is_from);
+       COPY_STRING_FIELD(filename);
+       COPY_NODE_FIELD(options);
 
        return newnode;
 }
@@ -2078,12 +1902,12 @@ _copyCreateStmt(CreateStmt *from)
 {
        CreateStmt *newnode = makeNode(CreateStmt);
 
-       Node_Copy(from, newnode, relation);
-       Node_Copy(from, newnode, tableElts);
-       Node_Copy(from, newnode, inhRelations);
-       Node_Copy(from, newnode, constraints);
-       newnode->hasoids = from->hasoids;
-       newnode->oncommit = from->oncommit;
+       COPY_NODE_FIELD(relation);
+       COPY_NODE_FIELD(tableElts);
+       COPY_NODE_FIELD(inhRelations);
+       COPY_NODE_FIELD(constraints);
+       COPY_SCALAR_FIELD(hasoids);
+       COPY_SCALAR_FIELD(oncommit);
 
        return newnode;
 }
@@ -2093,9 +1917,9 @@ _copyDefineStmt(DefineStmt *from)
 {
        DefineStmt *newnode = makeNode(DefineStmt);
 
-       newnode->defType = from->defType;
-       Node_Copy(from, newnode, defnames);
-       Node_Copy(from, newnode, definition);
+       COPY_SCALAR_FIELD(defType);
+       COPY_NODE_FIELD(defnames);
+       COPY_NODE_FIELD(definition);
 
        return newnode;
 }
@@ -2105,9 +1929,9 @@ _copyDropStmt(DropStmt *from)
 {
        DropStmt   *newnode = makeNode(DropStmt);
 
-       Node_Copy(from, newnode, objects);
-       newnode->removeType = from->removeType;
-       newnode->behavior = from->behavior;
+       COPY_NODE_FIELD(objects);
+       COPY_SCALAR_FIELD(removeType);
+       COPY_SCALAR_FIELD(behavior);
 
        return newnode;
 }
@@ -2117,7 +1941,7 @@ _copyTruncateStmt(TruncateStmt *from)
 {
        TruncateStmt *newnode = makeNode(TruncateStmt);
 
-       Node_Copy(from, newnode, relation);
+       COPY_NODE_FIELD(relation);
 
        return newnode;
 }
@@ -2127,11 +1951,10 @@ _copyCommentStmt(CommentStmt *from)
 {
        CommentStmt *newnode = makeNode(CommentStmt);
 
-       newnode->objtype = from->objtype;
-       Node_Copy(from, newnode, objname);
-       Node_Copy(from, newnode, objargs);
-       if (from->comment)
-               newnode->comment = pstrdup(from->comment);
+       COPY_SCALAR_FIELD(objtype);
+       COPY_NODE_FIELD(objname);
+       COPY_NODE_FIELD(objargs);
+       COPY_STRING_FIELD(comment);
 
        return newnode;
 }
@@ -2141,10 +1964,10 @@ _copyFetchStmt(FetchStmt *from)
 {
        FetchStmt  *newnode = makeNode(FetchStmt);
 
-       newnode->direction = from->direction;
-       newnode->howMany = from->howMany;
-       newnode->portalname = pstrdup(from->portalname);
-       newnode->ismove = from->ismove;
+       COPY_SCALAR_FIELD(direction);
+       COPY_SCALAR_FIELD(howMany);
+       COPY_STRING_FIELD(portalname);
+       COPY_SCALAR_FIELD(ismove);
 
        return newnode;
 }
@@ -2154,15 +1977,15 @@ _copyIndexStmt(IndexStmt *from)
 {
        IndexStmt  *newnode = makeNode(IndexStmt);
 
-       newnode->idxname = pstrdup(from->idxname);
-       Node_Copy(from, newnode, relation);
-       newnode->accessMethod = pstrdup(from->accessMethod);
-       Node_Copy(from, newnode, indexParams);
-       Node_Copy(from, newnode, whereClause);
-       Node_Copy(from, newnode, rangetable);
-       newnode->unique = from->unique;
-       newnode->primary = from->primary;
-       newnode->isconstraint = from->isconstraint;
+       COPY_STRING_FIELD(idxname);
+       COPY_NODE_FIELD(relation);
+       COPY_STRING_FIELD(accessMethod);
+       COPY_NODE_FIELD(indexParams);
+       COPY_NODE_FIELD(whereClause);
+       COPY_NODE_FIELD(rangetable);
+       COPY_SCALAR_FIELD(unique);
+       COPY_SCALAR_FIELD(primary);
+       COPY_SCALAR_FIELD(isconstraint);
 
        return newnode;
 }
@@ -2172,12 +1995,12 @@ _copyCreateFunctionStmt(CreateFunctionStmt *from)
 {
        CreateFunctionStmt *newnode = makeNode(CreateFunctionStmt);
 
-       newnode->replace = from->replace;
-       Node_Copy(from, newnode, funcname);
-       Node_Copy(from, newnode, argTypes);
-       Node_Copy(from, newnode, returnType);
-       Node_Copy(from, newnode, options);
-       Node_Copy(from, newnode, withClause);
+       COPY_SCALAR_FIELD(replace);
+       COPY_NODE_FIELD(funcname);
+       COPY_NODE_FIELD(argTypes);
+       COPY_NODE_FIELD(returnType);
+       COPY_NODE_FIELD(options);
+       COPY_NODE_FIELD(withClause);
 
        return newnode;
 }
@@ -2187,9 +2010,9 @@ _copyRemoveAggrStmt(RemoveAggrStmt *from)
 {
        RemoveAggrStmt *newnode = makeNode(RemoveAggrStmt);
 
-       Node_Copy(from, newnode, aggname);
-       Node_Copy(from, newnode, aggtype);
-       newnode->behavior = from->behavior;
+       COPY_NODE_FIELD(aggname);
+       COPY_NODE_FIELD(aggtype);
+       COPY_SCALAR_FIELD(behavior);
 
        return newnode;
 }
@@ -2199,9 +2022,9 @@ _copyRemoveFuncStmt(RemoveFuncStmt *from)
 {
        RemoveFuncStmt *newnode = makeNode(RemoveFuncStmt);
 
-       Node_Copy(from, newnode, funcname);
-       Node_Copy(from, newnode, args);
-       newnode->behavior = from->behavior;
+       COPY_NODE_FIELD(funcname);
+       COPY_NODE_FIELD(args);
+       COPY_SCALAR_FIELD(behavior);
 
        return newnode;
 }
@@ -2211,9 +2034,9 @@ _copyRemoveOperStmt(RemoveOperStmt *from)
 {
        RemoveOperStmt *newnode = makeNode(RemoveOperStmt);
 
-       Node_Copy(from, newnode, opname);
-       Node_Copy(from, newnode, args);
-       newnode->behavior = from->behavior;
+       COPY_NODE_FIELD(opname);
+       COPY_NODE_FIELD(args);
+       COPY_SCALAR_FIELD(behavior);
 
        return newnode;
 }
@@ -2223,10 +2046,9 @@ _copyRemoveOpClassStmt(RemoveOpClassStmt *from)
 {
        RemoveOpClassStmt *newnode = makeNode(RemoveOpClassStmt);
 
-       Node_Copy(from, newnode, opclassname);
-       if (from->amname)
-               newnode->amname = pstrdup(from->amname);
-       newnode->behavior = from->behavior;
+       COPY_NODE_FIELD(opclassname);
+       COPY_STRING_FIELD(amname);
+       COPY_SCALAR_FIELD(behavior);
 
        return newnode;
 }
@@ -2236,12 +2058,10 @@ _copyRenameStmt(RenameStmt *from)
 {
        RenameStmt *newnode = makeNode(RenameStmt);
 
-       Node_Copy(from, newnode, relation);
-       if (from->oldname)
-               newnode->oldname = pstrdup(from->oldname);
-       if (from->newname)
-               newnode->newname = pstrdup(from->newname);
-       newnode->renameType = from->renameType;
+       COPY_NODE_FIELD(relation);
+       COPY_STRING_FIELD(oldname);
+       COPY_STRING_FIELD(newname);
+       COPY_SCALAR_FIELD(renameType);
 
        return newnode;
 }
@@ -2251,13 +2071,13 @@ _copyRuleStmt(RuleStmt *from)
 {
        RuleStmt   *newnode = makeNode(RuleStmt);
 
-       Node_Copy(from, newnode, relation);
-       newnode->rulename = pstrdup(from->rulename);
-       Node_Copy(from, newnode, whereClause);
-       newnode->event = from->event;
-       newnode->instead = from->instead;
-       newnode->replace = from->replace;
-       Node_Copy(from, newnode, actions);
+       COPY_NODE_FIELD(relation);
+       COPY_STRING_FIELD(rulename);
+       COPY_NODE_FIELD(whereClause);
+       COPY_SCALAR_FIELD(event);
+       COPY_SCALAR_FIELD(instead);
+       COPY_NODE_FIELD(actions);
+       COPY_SCALAR_FIELD(replace);
 
        return newnode;
 }
@@ -2267,7 +2087,7 @@ _copyNotifyStmt(NotifyStmt *from)
 {
        NotifyStmt *newnode = makeNode(NotifyStmt);
 
-       Node_Copy(from, newnode, relation);
+       COPY_NODE_FIELD(relation);
 
        return newnode;
 }
@@ -2277,7 +2097,7 @@ _copyListenStmt(ListenStmt *from)
 {
        ListenStmt *newnode = makeNode(ListenStmt);
 
-       Node_Copy(from, newnode, relation);
+       COPY_NODE_FIELD(relation);
 
        return newnode;
 }
@@ -2287,7 +2107,7 @@ _copyUnlistenStmt(UnlistenStmt *from)
 {
        UnlistenStmt *newnode = makeNode(UnlistenStmt);
 
-       Node_Copy(from, newnode, relation);
+       COPY_NODE_FIELD(relation);
 
        return newnode;
 }
@@ -2297,8 +2117,8 @@ _copyTransactionStmt(TransactionStmt *from)
 {
        TransactionStmt *newnode = makeNode(TransactionStmt);
 
-       newnode->command = from->command;
-       Node_Copy(from, newnode, options);
+       COPY_SCALAR_FIELD(command);
+       COPY_NODE_FIELD(options);
 
        return newnode;
 }
@@ -2308,8 +2128,8 @@ _copyCompositeTypeStmt(CompositeTypeStmt *from)
 {
        CompositeTypeStmt *newnode = makeNode(CompositeTypeStmt);
 
-       Node_Copy(from, newnode, typevar);
-       Node_Copy(from, newnode, coldeflist);
+       COPY_NODE_FIELD(typevar);
+       COPY_NODE_FIELD(coldeflist);
 
        return newnode;
 }
@@ -2319,10 +2139,10 @@ _copyViewStmt(ViewStmt *from)
 {
        ViewStmt   *newnode = makeNode(ViewStmt);
 
-       Node_Copy(from, newnode, view);
-       Node_Copy(from, newnode, aliases);
-       Node_Copy(from, newnode, query);
-       newnode->replace = from->replace;
+       COPY_NODE_FIELD(view);
+       COPY_NODE_FIELD(aliases);
+       COPY_NODE_FIELD(query);
+       COPY_SCALAR_FIELD(replace);
 
        return newnode;
 }
@@ -2332,8 +2152,7 @@ _copyLoadStmt(LoadStmt *from)
 {
        LoadStmt   *newnode = makeNode(LoadStmt);
 
-       if (from->filename)
-               newnode->filename = pstrdup(from->filename);
+       COPY_STRING_FIELD(filename);
 
        return newnode;
 }
@@ -2343,9 +2162,9 @@ _copyCreateDomainStmt(CreateDomainStmt *from)
 {
        CreateDomainStmt *newnode = makeNode(CreateDomainStmt);
 
-       Node_Copy(from, newnode, domainname);
-       Node_Copy(from, newnode, typename);
-       Node_Copy(from, newnode, constraints);
+       COPY_NODE_FIELD(domainname);
+       COPY_NODE_FIELD(typename);
+       COPY_NODE_FIELD(constraints);
 
        return newnode;
 }
@@ -2355,12 +2174,11 @@ _copyCreateOpClassStmt(CreateOpClassStmt *from)
 {
        CreateOpClassStmt *newnode = makeNode(CreateOpClassStmt);
 
-       Node_Copy(from, newnode, opclassname);
-       if (from->amname)
-               newnode->amname = pstrdup(from->amname);
-       Node_Copy(from, newnode, datatype);
-       Node_Copy(from, newnode, items);
-       newnode->isDefault = from->isDefault;
+       COPY_NODE_FIELD(opclassname);
+       COPY_STRING_FIELD(amname);
+       COPY_NODE_FIELD(datatype);
+       COPY_NODE_FIELD(items);
+       COPY_SCALAR_FIELD(isDefault);
 
        return newnode;
 }
@@ -2370,12 +2188,12 @@ _copyCreateOpClassItem(CreateOpClassItem *from)
 {
        CreateOpClassItem *newnode = makeNode(CreateOpClassItem);
 
-       newnode->itemtype = from->itemtype;
-       Node_Copy(from, newnode, name);
-       Node_Copy(from, newnode, args);
-       newnode->number = from->number;
-       newnode->recheck = from->recheck;
-       Node_Copy(from, newnode, storedtype);
+       COPY_SCALAR_FIELD(itemtype);
+       COPY_NODE_FIELD(name);
+       COPY_NODE_FIELD(args);
+       COPY_SCALAR_FIELD(number);
+       COPY_SCALAR_FIELD(recheck);
+       COPY_NODE_FIELD(storedtype);
 
        return newnode;
 }
@@ -2385,9 +2203,8 @@ _copyCreatedbStmt(CreatedbStmt *from)
 {
        CreatedbStmt *newnode = makeNode(CreatedbStmt);
 
-       if (from->dbname)
-               newnode->dbname = pstrdup(from->dbname);
-       Node_Copy(from, newnode, options);
+       COPY_STRING_FIELD(dbname);
+       COPY_NODE_FIELD(options);
 
        return newnode;
 }
@@ -2397,11 +2214,9 @@ _copyAlterDatabaseSetStmt(AlterDatabaseSetStmt *from)
 {
        AlterDatabaseSetStmt *newnode = makeNode(AlterDatabaseSetStmt);
 
-       if (from->dbname)
-               newnode->dbname = pstrdup(from->dbname);
-       if (from->variable)
-               newnode->variable = pstrdup(from->variable);
-       Node_Copy(from, newnode, value);
+       COPY_STRING_FIELD(dbname);
+       COPY_STRING_FIELD(variable);
+       COPY_NODE_FIELD(value);
 
        return newnode;
 }
@@ -2411,8 +2226,7 @@ _copyDropdbStmt(DropdbStmt *from)
 {
        DropdbStmt *newnode = makeNode(DropdbStmt);
 
-       if (from->dbname)
-               newnode->dbname = pstrdup(from->dbname);
+       COPY_STRING_FIELD(dbname);
 
        return newnode;
 }
@@ -2422,13 +2236,13 @@ _copyVacuumStmt(VacuumStmt *from)
 {
        VacuumStmt *newnode = makeNode(VacuumStmt);
 
-       newnode->vacuum = from->vacuum;
-       newnode->full = from->full;
-       newnode->analyze = from->analyze;
-       newnode->freeze = from->freeze;
-       newnode->verbose = from->verbose;
-       Node_Copy(from, newnode, relation);
-       Node_Copy(from, newnode, va_cols);
+       COPY_SCALAR_FIELD(vacuum);
+       COPY_SCALAR_FIELD(full);
+       COPY_SCALAR_FIELD(analyze);
+       COPY_SCALAR_FIELD(freeze);
+       COPY_SCALAR_FIELD(verbose);
+       COPY_NODE_FIELD(relation);
+       COPY_NODE_FIELD(va_cols);
 
        return newnode;
 }
@@ -2438,9 +2252,9 @@ _copyExplainStmt(ExplainStmt *from)
 {
        ExplainStmt *newnode = makeNode(ExplainStmt);
 
-       Node_Copy(from, newnode, query);
-       newnode->verbose = from->verbose;
-       newnode->analyze = from->analyze;
+       COPY_NODE_FIELD(query);
+       COPY_SCALAR_FIELD(verbose);
+       COPY_SCALAR_FIELD(analyze);
 
        return newnode;
 }
@@ -2450,8 +2264,8 @@ _copyCreateSeqStmt(CreateSeqStmt *from)
 {
        CreateSeqStmt *newnode = makeNode(CreateSeqStmt);
 
-       Node_Copy(from, newnode, sequence);
-       Node_Copy(from, newnode, options);
+       COPY_NODE_FIELD(sequence);
+       COPY_NODE_FIELD(options);
 
        return newnode;
 }
@@ -2461,10 +2275,9 @@ _copyVariableSetStmt(VariableSetStmt *from)
 {
        VariableSetStmt *newnode = makeNode(VariableSetStmt);
 
-       if (from->name)
-               newnode->name = pstrdup(from->name);
-       Node_Copy(from, newnode, args);
-       newnode->is_local = from->is_local;
+       COPY_STRING_FIELD(name);
+       COPY_NODE_FIELD(args);
+       COPY_SCALAR_FIELD(is_local);
 
        return newnode;
 }
@@ -2474,8 +2287,7 @@ _copyVariableShowStmt(VariableShowStmt *from)
 {
        VariableShowStmt *newnode = makeNode(VariableShowStmt);
 
-       if (from->name)
-               newnode->name = pstrdup(from->name);
+       COPY_STRING_FIELD(name);
 
        return newnode;
 }
@@ -2485,8 +2297,7 @@ _copyVariableResetStmt(VariableResetStmt *from)
 {
        VariableResetStmt *newnode = makeNode(VariableResetStmt);
 
-       if (from->name)
-               newnode->name = pstrdup(from->name);
+       COPY_STRING_FIELD(name);
 
        return newnode;
 }
@@ -2496,18 +2307,17 @@ _copyCreateTrigStmt(CreateTrigStmt *from)
 {
        CreateTrigStmt *newnode = makeNode(CreateTrigStmt);
 
-       if (from->trigname)
-               newnode->trigname = pstrdup(from->trigname);
-       Node_Copy(from, newnode, relation);
-       Node_Copy(from, newnode, funcname);
-       Node_Copy(from, newnode, args);
-       newnode->before = from->before;
-       newnode->row = from->row;
-       memcpy(newnode->actions, from->actions, sizeof(from->actions));
-       newnode->isconstraint = from->isconstraint;
-       newnode->deferrable = from->deferrable;
-       newnode->initdeferred = from->initdeferred;
-       Node_Copy(from, newnode, constrrel);
+       COPY_STRING_FIELD(trigname);
+       COPY_NODE_FIELD(relation);
+       COPY_NODE_FIELD(funcname);
+       COPY_NODE_FIELD(args);
+       COPY_SCALAR_FIELD(before);
+       COPY_SCALAR_FIELD(row);
+       strcpy(newnode->actions, from->actions); /* in-line string field */
+       COPY_SCALAR_FIELD(isconstraint);
+       COPY_SCALAR_FIELD(deferrable);
+       COPY_SCALAR_FIELD(initdeferred);
+       COPY_NODE_FIELD(constrrel);
 
        return newnode;
 }
@@ -2517,11 +2327,10 @@ _copyDropPropertyStmt(DropPropertyStmt *from)
 {
        DropPropertyStmt *newnode = makeNode(DropPropertyStmt);
 
-       Node_Copy(from, newnode, relation);
-       if (from->property)
-               newnode->property = pstrdup(from->property);
-       newnode->removeType = from->removeType;
-       newnode->behavior = from->behavior;
+       COPY_NODE_FIELD(relation);
+       COPY_STRING_FIELD(property);
+       COPY_SCALAR_FIELD(removeType);
+       COPY_SCALAR_FIELD(behavior);
 
        return newnode;
 }
@@ -2531,11 +2340,10 @@ _copyCreatePLangStmt(CreatePLangStmt *from)
 {
        CreatePLangStmt *newnode = makeNode(CreatePLangStmt);
 
-       if (from->plname)
-               newnode->plname = pstrdup(from->plname);
-       Node_Copy(from, newnode, plhandler);
-       Node_Copy(from, newnode, plvalidator);
-       newnode->pltrusted = from->pltrusted;
+       COPY_STRING_FIELD(plname);
+       COPY_NODE_FIELD(plhandler);
+       COPY_NODE_FIELD(plvalidator);
+       COPY_SCALAR_FIELD(pltrusted);
 
        return newnode;
 }
@@ -2545,9 +2353,8 @@ _copyDropPLangStmt(DropPLangStmt *from)
 {
        DropPLangStmt *newnode = makeNode(DropPLangStmt);
 
-       if (from->plname)
-               newnode->plname = pstrdup(from->plname);
-       newnode->behavior = from->behavior;
+       COPY_STRING_FIELD(plname);
+       COPY_SCALAR_FIELD(behavior);
 
        return newnode;
 }
@@ -2557,9 +2364,8 @@ _copyCreateUserStmt(CreateUserStmt *from)
 {
        CreateUserStmt *newnode = makeNode(CreateUserStmt);
 
-       if (from->user)
-               newnode->user = pstrdup(from->user);
-       Node_Copy(from, newnode, options);
+       COPY_STRING_FIELD(user);
+       COPY_NODE_FIELD(options);
 
        return newnode;
 }
@@ -2569,9 +2375,8 @@ _copyAlterUserStmt(AlterUserStmt *from)
 {
        AlterUserStmt *newnode = makeNode(AlterUserStmt);
 
-       if (from->user)
-               newnode->user = pstrdup(from->user);
-       Node_Copy(from, newnode, options);
+       COPY_STRING_FIELD(user);
+       COPY_NODE_FIELD(options);
 
        return newnode;
 }
@@ -2581,11 +2386,9 @@ _copyAlterUserSetStmt(AlterUserSetStmt *from)
 {
        AlterUserSetStmt *newnode = makeNode(AlterUserSetStmt);
 
-       if (from->user)
-               newnode->user = pstrdup(from->user);
-       if (from->variable)
-               newnode->variable = pstrdup(from->variable);
-       Node_Copy(from, newnode, value);
+       COPY_STRING_FIELD(user);
+       COPY_STRING_FIELD(variable);
+       COPY_NODE_FIELD(value);
 
        return newnode;
 }
@@ -2595,7 +2398,7 @@ _copyDropUserStmt(DropUserStmt *from)
 {
        DropUserStmt *newnode = makeNode(DropUserStmt);
 
-       Node_Copy(from, newnode, users);
+       COPY_NODE_FIELD(users);
 
        return newnode;
 }
@@ -2605,9 +2408,8 @@ _copyLockStmt(LockStmt *from)
 {
        LockStmt   *newnode = makeNode(LockStmt);
 
-       Node_Copy(from, newnode, relations);
-
-       newnode->mode = from->mode;
+       COPY_NODE_FIELD(relations);
+       COPY_SCALAR_FIELD(mode);
 
        return newnode;
 }
@@ -2617,8 +2419,8 @@ _copyConstraintsSetStmt(ConstraintsSetStmt *from)
 {
        ConstraintsSetStmt *newnode = makeNode(ConstraintsSetStmt);
 
-       Node_Copy(from, newnode, constraints);
-       newnode->deferred = from->deferred;
+       COPY_NODE_FIELD(constraints);
+       COPY_SCALAR_FIELD(deferred);
 
        return newnode;
 }
@@ -2628,9 +2430,8 @@ _copyCreateGroupStmt(CreateGroupStmt *from)
 {
        CreateGroupStmt *newnode = makeNode(CreateGroupStmt);
 
-       if (from->name)
-               newnode->name = pstrdup(from->name);
-       Node_Copy(from, newnode, options);
+       COPY_STRING_FIELD(name);
+       COPY_NODE_FIELD(options);
 
        return newnode;
 }
@@ -2640,10 +2441,9 @@ _copyAlterGroupStmt(AlterGroupStmt *from)
 {
        AlterGroupStmt *newnode = makeNode(AlterGroupStmt);
 
-       if (from->name)
-               newnode->name = pstrdup(from->name);
-       newnode->action = from->action;
-       Node_Copy(from, newnode, listUsers);
+       COPY_STRING_FIELD(name);
+       COPY_SCALAR_FIELD(action);
+       COPY_NODE_FIELD(listUsers);
 
        return newnode;
 }
@@ -2653,8 +2453,7 @@ _copyDropGroupStmt(DropGroupStmt *from)
 {
        DropGroupStmt *newnode = makeNode(DropGroupStmt);
 
-       if (from->name)
-               newnode->name = pstrdup(from->name);
+       COPY_STRING_FIELD(name);
 
        return newnode;
 }
@@ -2664,12 +2463,11 @@ _copyReindexStmt(ReindexStmt *from)
 {
        ReindexStmt *newnode = makeNode(ReindexStmt);
 
-       newnode->reindexType = from->reindexType;
-       Node_Copy(from, newnode, relation);
-       if (from->name)
-               newnode->name = pstrdup(from->name);
-       newnode->force = from->force;
-       newnode->all = from->all;
+       COPY_SCALAR_FIELD(reindexType);
+       COPY_NODE_FIELD(relation);
+       COPY_STRING_FIELD(name);
+       COPY_SCALAR_FIELD(force);
+       COPY_SCALAR_FIELD(all);
 
        return newnode;
 }
@@ -2679,10 +2477,9 @@ _copyCreateSchemaStmt(CreateSchemaStmt *from)
 {
        CreateSchemaStmt *newnode = makeNode(CreateSchemaStmt);
 
-       newnode->schemaname = pstrdup(from->schemaname);
-       if (from->authid)
-               newnode->authid = pstrdup(from->authid);
-       Node_Copy(from, newnode, schemaElts);
+       COPY_STRING_FIELD(schemaname);
+       COPY_STRING_FIELD(authid);
+       COPY_NODE_FIELD(schemaElts);
 
        return newnode;
 }
@@ -2692,11 +2489,11 @@ _copyCreateConversionStmt(CreateConversionStmt *from)
 {
        CreateConversionStmt *newnode = makeNode(CreateConversionStmt);
 
-       Node_Copy(from, newnode, conversion_name);
-       newnode->for_encoding_name = pstrdup(from->for_encoding_name);
-       newnode->to_encoding_name = pstrdup(from->to_encoding_name);
-       Node_Copy(from, newnode, func_name);
-       newnode->def = from->def;
+       COPY_NODE_FIELD(conversion_name);
+       COPY_STRING_FIELD(for_encoding_name);
+       COPY_STRING_FIELD(to_encoding_name);
+       COPY_NODE_FIELD(func_name);
+       COPY_SCALAR_FIELD(def);
 
        return newnode;
 }
@@ -2706,10 +2503,10 @@ _copyCreateCastStmt(CreateCastStmt *from)
 {
        CreateCastStmt *newnode = makeNode(CreateCastStmt);
 
-       Node_Copy(from, newnode, sourcetype);
-       Node_Copy(from, newnode, targettype);
-       Node_Copy(from, newnode, func);
-       newnode->context = from->context;
+       COPY_NODE_FIELD(sourcetype);
+       COPY_NODE_FIELD(targettype);
+       COPY_NODE_FIELD(func);
+       COPY_SCALAR_FIELD(context);
 
        return newnode;
 }
@@ -2719,9 +2516,9 @@ _copyDropCastStmt(DropCastStmt *from)
 {
        DropCastStmt *newnode = makeNode(DropCastStmt);
 
-       Node_Copy(from, newnode, sourcetype);
-       Node_Copy(from, newnode, targettype);
-       newnode->behavior = from->behavior;
+       COPY_NODE_FIELD(sourcetype);
+       COPY_NODE_FIELD(targettype);
+       COPY_SCALAR_FIELD(behavior);
 
        return newnode;
 }
@@ -2731,10 +2528,10 @@ _copyPrepareStmt(PrepareStmt *from)
 {
        PrepareStmt *newnode = makeNode(PrepareStmt);
 
-       newnode->name = pstrdup(from->name);
-       Node_Copy(from, newnode, argtypes);
-       newnode->argtype_oids = listCopy(from->argtype_oids);
-       Node_Copy(from, newnode, query);
+       COPY_STRING_FIELD(name);
+       COPY_NODE_FIELD(argtypes);
+       COPY_INTLIST_FIELD(argtype_oids);
+       COPY_NODE_FIELD(query);
 
        return newnode;
 }
@@ -2744,9 +2541,9 @@ _copyExecuteStmt(ExecuteStmt *from)
 {
        ExecuteStmt *newnode = makeNode(ExecuteStmt);
 
-       newnode->name = pstrdup(from->name);
-       Node_Copy(from, newnode, into);
-       Node_Copy(from, newnode, params);
+       COPY_STRING_FIELD(name);
+       COPY_NODE_FIELD(into);
+       COPY_NODE_FIELD(params);
 
        return newnode;
 }
@@ -2756,7 +2553,7 @@ _copyDeallocateStmt(DeallocateStmt *from)
 {
        DeallocateStmt *newnode = makeNode(DeallocateStmt);
 
-       newnode->name = pstrdup(from->name);
+       COPY_STRING_FIELD(name);
 
        return newnode;
 }
@@ -2774,16 +2571,16 @@ _copyValue(Value *from)
 
        /* See also _copyAConst when changing this code! */
 
-       newnode->type = from->type;
+       COPY_SCALAR_FIELD(type);
        switch (from->type)
        {
                case T_Integer:
-                       newnode->val.ival = from->val.ival;
+                       COPY_SCALAR_FIELD(val.ival);
                        break;
                case T_Float:
                case T_String:
                case T_BitString:
-                       newnode->val.str = pstrdup(from->val.str);
+                       COPY_STRING_FIELD(val.str);
                        break;
                case T_Null:
                        /* nothing to do */
@@ -2795,10 +2592,11 @@ _copyValue(Value *from)
        return newnode;
 }
 
-/* ----------------
- *             copyObject returns a copy of the node or list. If it is a list, it
- *             recursively copies its items.
- * ----------------
+/*
+ * copyObject
+ *
+ * Create a copy of a Node tree or list.  This is a "deep" copy: all
+ * substructure is copied too, recursively.
  */
 void *
 copyObject(void *from)
@@ -2889,6 +2687,12 @@ copyObject(void *from)
                case T_Fjoin:
                        retval = _copyFjoin(from);
                        break;
+               case T_Alias:
+                       retval = _copyAlias(from);
+                       break;
+               case T_RangeVar:
+                       retval = _copyRangeVar(from);
+                       break;
                case T_Expr:
                        retval = _copyExpr(from);
                        break;
@@ -2904,18 +2708,15 @@ copyObject(void *from)
                case T_Param:
                        retval = _copyParam(from);
                        break;
+               case T_Func:
+                       retval = _copyFunc(from);
+                       break;
                case T_Aggref:
                        retval = _copyAggref(from);
                        break;
                case T_SubLink:
                        retval = _copySubLink(from);
                        break;
-               case T_Func:
-                       retval = _copyFunc(from);
-                       break;
-               case T_ArrayRef:
-                       retval = _copyArrayRef(from);
-                       break;
                case T_FieldSelect:
                        retval = _copyFieldSelect(from);
                        break;
@@ -2925,11 +2726,14 @@ copyObject(void *from)
                case T_RangeTblRef:
                        retval = _copyRangeTblRef(from);
                        break;
+               case T_JoinExpr:
+                       retval = _copyJoinExpr(from);
+                       break;
                case T_FromExpr:
                        retval = _copyFromExpr(from);
                        break;
-               case T_JoinExpr:
-                       retval = _copyJoinExpr(from);
+               case T_ArrayRef:
+                       retval = _copyArrayRef(from);
                        break;
 
                        /*
@@ -3239,12 +3043,6 @@ copyObject(void *from)
                case T_SortGroupBy:
                        retval = _copySortGroupBy(from);
                        break;
-               case T_Alias:
-                       retval = _copyAlias(from);
-                       break;
-               case T_RangeVar:
-                       retval = _copyRangeVar(from);
-                       break;
                case T_RangeSubselect:
                        retval = _copyRangeSubselect(from);
                        break;
@@ -3318,5 +3116,6 @@ copyObject(void *from)
                        retval = from;          /* keep compiler quiet */
                        break;
        }
+
        return retval;
 }
index 3e0ea75d2518deda2cfe37ddfcad0def960e6c3d..f417dec4886ce546320034639c90892e8f6214b2 100644 (file)
@@ -20,7 +20,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.167 2002/11/24 21:52:13 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.168 2002/11/25 03:33:27 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #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 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(reskey);
+       COMPARE_SCALAR_FIELD(reskeyop);
+       COMPARE_SCALAR_FIELD(resjunk);
 
        return true;
 }
@@ -66,20 +101,33 @@ _equalResdom(Resdom *a, Resdom *b)
 static bool
 _equalFjoin(Fjoin *a, Fjoin *b)
 {
-       int                     nNodes;
+       COMPARE_SCALAR_FIELD(fj_initialized);
+       COMPARE_SCALAR_FIELD(fj_nNodes);
+       COMPARE_NODE_FIELD(fj_innerNode);
+       COMPARE_POINTER_FIELD(fj_results, a->fj_nNodes * sizeof(Datum));
+       COMPARE_POINTER_FIELD(fj_alwaysDone, a->fj_nNodes * sizeof(bool));
 
-       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;
+       return true;
+}
 
-       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;
+static bool
+_equalAlias(Alias *a, Alias *b)
+{
+       COMPARE_STRING_FIELD(aliasname);
+       COMPARE_NODE_FIELD(colnames);
+
+       return true;
+}
+
+static bool
+_equalRangeVar(RangeVar *a, RangeVar *b)
+{
+       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;
 }
@@ -92,12 +140,9 @@ _equalExpr(Expr *a, Expr *b)
         * 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_SCALAR_FIELD(opType);
+       COMPARE_NODE_FIELD(oper);
+       COMPARE_NODE_FIELD(args);
 
        return true;
 }
@@ -105,20 +150,13 @@ _equalExpr(Expr *a, Expr *b)
 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;
+       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;
 }
@@ -126,12 +164,9 @@ _equalVar(Var *a, Var *b)
 static bool
 _equalOper(Oper *a, Oper *b)
 {
-       if (a->opno != b->opno)
-               return false;
-       if (a->opresulttype != b->opresulttype)
-               return false;
-       if (a->opretset != b->opretset)
-               return false;
+       COMPARE_SCALAR_FIELD(opno);
+       COMPARE_SCALAR_FIELD(opresulttype);
+       COMPARE_SCALAR_FIELD(opretset);
 
        /*
         * We do not examine opid or op_fcache, since these are logically
@@ -151,14 +186,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;
+       COMPARE_SCALAR_FIELD(consttype);
+       COMPARE_SCALAR_FIELD(constlen);
+       COMPARE_SCALAR_FIELD(constisnull);
+       COMPARE_SCALAR_FIELD(constbyval);
        /* XXX What about constisset and constiscast? */
 
        /*
@@ -175,30 +206,24 @@ _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;
+                       COMPARE_SCALAR_FIELD(paramid);
                        break;
                case PARAM_INVALID:
-
                        /*
                         * XXX: Hmmm... What are we supposed to return in this case ??
                         */
-                       return true;
                        break;
                default:
                        elog(ERROR, "_equalParam: Invalid paramkind value: %d",
@@ -211,12 +236,9 @@ _equalParam(Param *a, Param *b)
 static bool
 _equalFunc(Func *a, Func *b)
 {
-       if (a->funcid != b->funcid)
-               return false;
-       if (a->funcresulttype != b->funcresulttype)
-               return false;
-       if (a->funcretset != b->funcretset)
-               return false;
+       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.
@@ -234,83 +256,45 @@ _equalFunc(Func *a, Func *b)
 static bool
 _equalAggref(Aggref *a, Aggref *b)
 {
-       if (a->aggfnoid != b->aggfnoid)
-               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;
+       COMPARE_SCALAR_FIELD(aggfnoid);
+       COMPARE_SCALAR_FIELD(aggtype);
+       COMPARE_NODE_FIELD(target);
+       COMPARE_SCALAR_FIELD(aggstar);
+       COMPARE_SCALAR_FIELD(aggdistinct);
        /* ignore aggno, which is only a private field for the executor */
+
        return true;
 }
 
 static bool
 _equalSubLink(SubLink *a, SubLink *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))
-               return false;
-       return true;
-}
+       COMPARE_SCALAR_FIELD(subLinkType);
+       COMPARE_SCALAR_FIELD(useor);
+       COMPARE_NODE_FIELD(lefthand);
+       COMPARE_NODE_FIELD(oper);
+       COMPARE_NODE_FIELD(subselect);
 
-static bool
-_equalArrayRef(ArrayRef *a, ArrayRef *b)
-{
-       if (a->refrestype != b->refrestype)
-               return false;
-       if (a->refattrlength != b->refattrlength)
-               return false;
-       if (a->refelemlength != b->refelemlength)
-               return false;
-       if (a->refelembyval != b->refelembyval)
-               return false;
-       if (a->refelemalign != b->refelemalign)
-               return false;
-       if (!equal(a->refupperindexpr, b->refupperindexpr))
-               return false;
-       if (!equal(a->reflowerindexpr, b->reflowerindexpr))
-               return false;
-       if (!equal(a->refexpr, b->refexpr))
-               return false;
-       if (!equal(a->refassgnexpr, b->refassgnexpr))
-               return false;
        return true;
 }
 
 static bool
 _equalFieldSelect(FieldSelect *a, FieldSelect *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)
-               return false;
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_SCALAR_FIELD(fieldnum);
+       COMPARE_SCALAR_FIELD(resulttype);
+       COMPARE_SCALAR_FIELD(resulttypmod);
+
        return true;
 }
 
 static bool
 _equalRelabelType(RelabelType *a, RelabelType *b)
 {
-       if (!equal(a->arg, b->arg))
-               return false;
-       if (a->resulttype != b->resulttype)
-               return false;
-       if (a->resulttypmod != b->resulttypmod)
-               return false;
+       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.
@@ -319,14 +303,29 @@ _equalRelabelType(RelabelType *a, RelabelType *b)
                a->relabelformat != COERCE_DONTCARE &&
                b->relabelformat != COERCE_DONTCARE)
                return false;
+
        return true;
 }
 
 static bool
 _equalRangeTblRef(RangeTblRef *a, RangeTblRef *b)
 {
-       if (a->rtindex != b->rtindex)
-               return false;
+       COMPARE_SCALAR_FIELD(rtindex);
+
+       return true;
+}
+
+static bool
+_equalJoinExpr(JoinExpr *a, JoinExpr *b)
+{
+       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;
 }
@@ -334,37 +333,46 @@ _equalRangeTblRef(RangeTblRef *a, RangeTblRef *b)
 static bool
 _equalFromExpr(FromExpr *a, FromExpr *b)
 {
-       if (!equal(a->fromlist, b->fromlist))
-               return false;
-       if (!equal(a->quals, b->quals))
-               return false;
+       COMPARE_NODE_FIELD(fromlist);
+       COMPARE_NODE_FIELD(quals);
 
        return true;
 }
 
 static bool
-_equalJoinExpr(JoinExpr *a, JoinExpr *b)
+_equalArrayRef(ArrayRef *a, ArrayRef *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 (a->rtindex != b->rtindex)
-               return false;
+       COMPARE_SCALAR_FIELD(refrestype);
+       COMPARE_SCALAR_FIELD(refattrlength);
+       COMPARE_SCALAR_FIELD(refelemlength);
+       COMPARE_SCALAR_FIELD(refelembyval);
+       COMPARE_SCALAR_FIELD(refelemalign);
+       COMPARE_NODE_FIELD(refupperindexpr);
+       COMPARE_NODE_FIELD(reflowerindexpr);
+       COMPARE_NODE_FIELD(refexpr);
+       COMPARE_NODE_FIELD(refassgnexpr);
 
        return true;
 }
 
+
+/*
+ * Stuff from plannodes.h
+ */
+
+static bool
+_equalSubPlan(SubPlan *a, SubPlan *b)
+{
+       /* should compare plans, but have to settle for comparing plan IDs */
+       COMPARE_SCALAR_FIELD(plan_id);
+
+       COMPARE_NODE_FIELD(rtable);
+       COMPARE_NODE_FIELD(sublink);
+
+       return true;
+}
+
+
 /*
  * Stuff from relation.h
  */
@@ -376,7 +384,9 @@ _equalRelOptInfo(RelOptInfo *a, RelOptInfo *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_INTLIST_FIELD(relids);
+
+       return true;
 }
 
 static bool
@@ -386,35 +396,23 @@ _equalIndexOptInfo(IndexOptInfo *a, IndexOptInfo *b)
         * We treat IndexOptInfos as equal if they refer to the same index. Is
         * this sufficient?
         */
-       if (a->indexoid != b->indexoid)
-               return false;
-       return true;
-}
+       COMPARE_SCALAR_FIELD(indexoid);
 
-static bool
-_equalPathKeyItem(PathKeyItem *a, PathKeyItem *b)
-{
-       if (a->sortop != b->sortop)
-               return false;
-       if (!equal(a->key, b->key))
-               return false;
        return true;
 }
 
 static bool
 _equalPath(Path *a, Path *b)
 {
-       if (a->pathtype != b->pathtype)
-               return false;
-       if (!equal(a->parent, b->parent))
-               return false;
-
+       /* This is safe only because _equalRelOptInfo is incomplete... */
+       COMPARE_NODE_FIELD(parent);
        /*
         * 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;
+       COMPARE_SCALAR_FIELD(pathtype);
+       COMPARE_NODE_FIELD(pathkeys);
+
        return true;
 }
 
@@ -423,12 +421,9 @@ _equalIndexPath(IndexPath *a, IndexPath *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;
+       COMPARE_NODE_FIELD(indexinfo);
+       COMPARE_NODE_FIELD(indexqual);
+       COMPARE_SCALAR_FIELD(indexscandir);
 
        /*
         * Skip 'rows' because of possibility of floating-point roundoff
@@ -442,10 +437,9 @@ _equalTidPath(TidPath *a, TidPath *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_NODE_FIELD(tideval);
+       COMPARE_INTLIST_FIELD(unjoined_relids);
+
        return true;
 }
 
@@ -454,8 +448,8 @@ _equalAppendPath(AppendPath *a, AppendPath *b)
 {
        if (!_equalPath((Path *) a, (Path *) b))
                return false;
-       if (!equal(a->subpaths, b->subpaths))
-               return false;
+       COMPARE_NODE_FIELD(subpaths);
+
        return true;
 }
 
@@ -464,10 +458,9 @@ _equalResultPath(ResultPath *a, ResultPath *b)
 {
        if (!_equalPath((Path *) a, (Path *) b))
                return false;
-       if (!equal(a->subpath, b->subpath))
-               return false;
-       if (!equal(a->constantqual, b->constantqual))
-               return false;
+       COMPARE_NODE_FIELD(subpath);
+       COMPARE_NODE_FIELD(constantqual);
+
        return true;
 }
 
@@ -476,14 +469,11 @@ _equalJoinPath(JoinPath *a, JoinPath *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_SCALAR_FIELD(jointype);
+       COMPARE_NODE_FIELD(outerjoinpath);
+       COMPARE_NODE_FIELD(innerjoinpath);
+       COMPARE_NODE_FIELD(joinrestrictinfo);
+
        return true;
 }
 
@@ -492,6 +482,7 @@ _equalNestPath(NestPath *a, NestPath *b)
 {
        if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
                return false;
+
        return true;
 }
 
@@ -500,12 +491,10 @@ _equalMergePath(MergePath *a, MergePath *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))
-               return false;
+       COMPARE_NODE_FIELD(path_mergeclauses);
+       COMPARE_NODE_FIELD(outersortkeys);
+       COMPARE_NODE_FIELD(innersortkeys);
+
        return true;
 }
 
@@ -514,23 +503,16 @@ _equalHashPath(HashPath *a, HashPath *b)
 {
        if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
                return false;
-       if (!equal(a->path_hashclauses, b->path_hashclauses))
-               return false;
+       COMPARE_NODE_FIELD(path_hashclauses);
+
        return true;
 }
 
 static bool
-_equalSubPlan(SubPlan *a, SubPlan *b)
+_equalPathKeyItem(PathKeyItem *a, PathKeyItem *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_NODE_FIELD(key);
+       COMPARE_SCALAR_FIELD(sortop);
 
        return true;
 }
@@ -538,50 +520,42 @@ _equalSubPlan(SubPlan *a, SubPlan *b)
 static bool
 _equalRestrictInfo(RestrictInfo *a, RestrictInfo *b)
 {
-       if (!equal(a->clause, b->clause))
-               return false;
-       if (a->ispusheddown != b->ispusheddown)
-               return false;
-
+       COMPARE_NODE_FIELD(clause);
+       COMPARE_SCALAR_FIELD(ispusheddown);
        /*
         * We ignore subclauseindices, 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 (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;
+       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)
 {
-       if (!equali(a->unjoined_relids, b->unjoined_relids))
-               return false;
-       if (!equal(a->jinfo_restrictinfo, b->jinfo_restrictinfo))
-               return false;
+       COMPARE_INTLIST_FIELD(unjoined_relids);
+       COMPARE_NODE_FIELD(jinfo_restrictinfo);
+
        return true;
 }
 
 static bool
 _equalInnerIndexscanInfo(InnerIndexscanInfo *a, InnerIndexscanInfo *b)
 {
-       if (!equali(a->other_relids, b->other_relids))
-               return false;
-       if (a->isouterjoin != b->isouterjoin)
-               return false;
-       if (!equal(a->best_innerpath, b->best_innerpath))
-               return false;
+       COMPARE_INTLIST_FIELD(other_relids);
+       COMPARE_SCALAR_FIELD(isouterjoin);
+       COMPARE_NODE_FIELD(best_innerpath);
+
        return true;
 }
 
+
 /*
  * Stuff from parsenodes.h
  */
@@ -589,48 +563,27 @@ _equalInnerIndexscanInfo(InnerIndexscanInfo *a, InnerIndexscanInfo *b)
 static bool
 _equalQuery(Query *a, Query *b)
 {
-       if (a->commandType != b->commandType)
-               return false;
-       if (a->querySource != b->querySource)
-               return false;
-       if (!equal(a->utilityStmt, b->utilityStmt))
-               return false;
-       if (a->resultRelation != b->resultRelation)
-               return false;
-       if (!equal(a->into, b->into))
-               return false;
-       if (a->isPortal != b->isPortal)
-               return false;
-       if (a->isBinary != b->isBinary)
-               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_SCALAR_FIELD(commandType);
+       COMPARE_SCALAR_FIELD(querySource);
+       COMPARE_NODE_FIELD(utilityStmt);
+       COMPARE_SCALAR_FIELD(resultRelation);
+       COMPARE_NODE_FIELD(into);
+       COMPARE_SCALAR_FIELD(isPortal);
+       COMPARE_SCALAR_FIELD(isBinary);
+       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);
 
        /*
         * We do not check the internal-to-the-planner fields: base_rel_list,
@@ -644,14 +597,10 @@ _equalQuery(Query *a, Query *b)
 static bool
 _equalInsertStmt(InsertStmt *a, InsertStmt *b)
 {
-       if (!equal(a->relation, b->relation))
-               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;
 }
@@ -659,10 +608,8 @@ _equalInsertStmt(InsertStmt *a, InsertStmt *b)
 static bool
 _equalDeleteStmt(DeleteStmt *a, DeleteStmt *b)
 {
-       if (!equal(a->relation, b->relation))
-               return false;
-       if (!equal(a->whereClause, b->whereClause))
-               return false;
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_NODE_FIELD(whereClause);
 
        return true;
 }
@@ -670,14 +617,10 @@ _equalDeleteStmt(DeleteStmt *a, DeleteStmt *b)
 static bool
 _equalUpdateStmt(UpdateStmt *a, UpdateStmt *b)
 {
-       if (!equal(a->relation, b->relation))
-               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;
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_NODE_FIELD(targetList);
+       COMPARE_NODE_FIELD(whereClause);
+       COMPARE_NODE_FIELD(fromClause);
 
        return true;
 }
@@ -685,42 +628,24 @@ _equalUpdateStmt(UpdateStmt *a, UpdateStmt *b)
 static bool
 _equalSelectStmt(SelectStmt *a, SelectStmt *b)
 {
-       if (!equal(a->distinctClause, b->distinctClause))
-               return false;
-       if (!equal(a->into, b->into))
-               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_STRING_FIELD(portalname);
+       COMPARE_SCALAR_FIELD(binary);
+       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;
 }
@@ -728,16 +653,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_INTLIST_FIELD(colTypes);
 
        return true;
 }
@@ -745,16 +665,11 @@ _equalSetOperationStmt(SetOperationStmt *a, SetOperationStmt *b)
 static bool
 _equalAlterTableStmt(AlterTableStmt *a, AlterTableStmt *b)
 {
-       if (a->subtype != b->subtype)
-               return false;
-       if (!equal(a->relation, b->relation))
-               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;
 }
@@ -762,16 +677,11 @@ _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 (!equali(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);
 
        return true;
 }
@@ -779,15 +689,19 @@ _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 equal(a->funcname, b->funcname)
-               && equal(a->funcargs, b->funcargs);
+       COMPARE_NODE_FIELD(funcname);
+       COMPARE_NODE_FIELD(funcargs);
+
+       return true;
 }
 
 static bool
@@ -799,8 +713,7 @@ _equalInsertDefault(InsertDefault *a, InsertDefault *b)
 static bool
 _equalClosePortalStmt(ClosePortalStmt *a, ClosePortalStmt *b)
 {
-       if (!equalstr(a->portalname, b->portalname))
-               return false;
+       COMPARE_STRING_FIELD(portalname);
 
        return true;
 }
@@ -808,10 +721,8 @@ _equalClosePortalStmt(ClosePortalStmt *a, ClosePortalStmt *b)
 static bool
 _equalClusterStmt(ClusterStmt *a, ClusterStmt *b)
 {
-       if (!equal(a->relation, b->relation))
-               return false;
-       if (!equalstr(a->indexname, b->indexname))
-               return false;
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_STRING_FIELD(indexname);
 
        return true;
 }
@@ -819,16 +730,11 @@ _equalClusterStmt(ClusterStmt *a, ClusterStmt *b)
 static bool
 _equalCopyStmt(CopyStmt *a, CopyStmt *b)
 {
-       if (!equal(a->relation, b->relation))
-               return false;
-       if (!equal(a->attlist, b->attlist))
-               return false;
-       if (a->is_from != b->is_from)
-               return false;
-       if (!equalstr(a->filename, b->filename))
-               return false;
-       if (!equal(a->options, b->options))
-               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;
 }
@@ -836,18 +742,12 @@ _equalCopyStmt(CopyStmt *a, CopyStmt *b)
 static bool
 _equalCreateStmt(CreateStmt *a, CreateStmt *b)
 {
-       if (!equal(a->relation, b->relation))
-               return false;
-       if (!equal(a->tableElts, b->tableElts))
-               return false;
-       if (!equal(a->inhRelations, b->inhRelations))
-               return false;
-       if (!equal(a->constraints, b->constraints))
-               return false;
-       if (a->hasoids != b->hasoids)
-               return false;
-       if (a->oncommit != b->oncommit)
-               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;
 }
@@ -855,12 +755,9 @@ _equalCreateStmt(CreateStmt *a, CreateStmt *b)
 static bool
 _equalDefineStmt(DefineStmt *a, DefineStmt *b)
 {
-       if (a->defType != b->defType)
-               return false;
-       if (!equal(a->defnames, b->defnames))
-               return false;
-       if (!equal(a->definition, b->definition))
-               return false;
+       COMPARE_SCALAR_FIELD(defType);
+       COMPARE_NODE_FIELD(defnames);
+       COMPARE_NODE_FIELD(definition);
 
        return true;
 }
@@ -868,12 +765,9 @@ _equalDefineStmt(DefineStmt *a, DefineStmt *b)
 static bool
 _equalDropStmt(DropStmt *a, DropStmt *b)
 {
-       if (!equal(a->objects, b->objects))
-               return false;
-       if (a->removeType != b->removeType)
-               return false;
-       if (a->behavior != b->behavior)
-               return false;
+       COMPARE_NODE_FIELD(objects);
+       COMPARE_SCALAR_FIELD(removeType);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
@@ -881,8 +775,7 @@ _equalDropStmt(DropStmt *a, DropStmt *b)
 static bool
 _equalTruncateStmt(TruncateStmt *a, TruncateStmt *b)
 {
-       if (!equal(a->relation, b->relation))
-               return false;
+       COMPARE_NODE_FIELD(relation);
 
        return true;
 }
@@ -890,14 +783,10 @@ _equalTruncateStmt(TruncateStmt *a, TruncateStmt *b)
 static bool
 _equalCommentStmt(CommentStmt *a, CommentStmt *b)
 {
-       if (a->objtype != b->objtype)
-               return false;
-       if (!equal(a->objname, b->objname))
-               return false;
-       if (!equal(a->objargs, b->objargs))
-               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;
 }
@@ -905,14 +794,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;
 }
@@ -920,24 +805,15 @@ _equalFetchStmt(FetchStmt *a, FetchStmt *b)
 static bool
 _equalIndexStmt(IndexStmt *a, IndexStmt *b)
 {
-       if (!equalstr(a->idxname, b->idxname))
-               return false;
-       if (!equal(a->relation, b->relation))
-               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;
-       if (a->isconstraint != b->isconstraint)
-               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;
 }
@@ -945,18 +821,12 @@ _equalIndexStmt(IndexStmt *a, IndexStmt *b)
 static bool
 _equalCreateFunctionStmt(CreateFunctionStmt *a, CreateFunctionStmt *b)
 {
-       if (a->replace != b->replace)
-               return false;
-       if (!equal(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->options, b->options))
-               return false;
-       if (!equal(a->withClause, b->withClause))
-               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;
 }
@@ -964,12 +834,9 @@ _equalCreateFunctionStmt(CreateFunctionStmt *a, CreateFunctionStmt *b)
 static bool
 _equalRemoveAggrStmt(RemoveAggrStmt *a, RemoveAggrStmt *b)
 {
-       if (!equal(a->aggname, b->aggname))
-               return false;
-       if (!equal(a->aggtype, b->aggtype))
-               return false;
-       if (a->behavior != b->behavior)
-               return false;
+       COMPARE_NODE_FIELD(aggname);
+       COMPARE_NODE_FIELD(aggtype);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
@@ -977,12 +844,9 @@ _equalRemoveAggrStmt(RemoveAggrStmt *a, RemoveAggrStmt *b)
 static bool
 _equalRemoveFuncStmt(RemoveFuncStmt *a, RemoveFuncStmt *b)
 {
-       if (!equal(a->funcname, b->funcname))
-               return false;
-       if (!equal(a->args, b->args))
-               return false;
-       if (a->behavior != b->behavior)
-               return false;
+       COMPARE_NODE_FIELD(funcname);
+       COMPARE_NODE_FIELD(args);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
@@ -990,12 +854,9 @@ _equalRemoveFuncStmt(RemoveFuncStmt *a, RemoveFuncStmt *b)
 static bool
 _equalRemoveOperStmt(RemoveOperStmt *a, RemoveOperStmt *b)
 {
-       if (!equal(a->opname, b->opname))
-               return false;
-       if (!equal(a->args, b->args))
-               return false;
-       if (a->behavior != b->behavior)
-               return false;
+       COMPARE_NODE_FIELD(opname);
+       COMPARE_NODE_FIELD(args);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
@@ -1003,12 +864,9 @@ _equalRemoveOperStmt(RemoveOperStmt *a, RemoveOperStmt *b)
 static bool
 _equalRemoveOpClassStmt(RemoveOpClassStmt *a, RemoveOpClassStmt *b)
 {
-       if (!equal(a->opclassname, b->opclassname))
-               return false;
-       if (!equalstr(a->amname, b->amname))
-               return false;
-       if (a->behavior != b->behavior)
-               return false;
+       COMPARE_NODE_FIELD(opclassname);
+       COMPARE_STRING_FIELD(amname);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
@@ -1016,14 +874,10 @@ _equalRemoveOpClassStmt(RemoveOpClassStmt *a, RemoveOpClassStmt *b)
 static bool
 _equalRenameStmt(RenameStmt *a, RenameStmt *b)
 {
-       if (!equal(a->relation, b->relation))
-               return false;
-       if (!equalstr(a->oldname, b->oldname))
-               return false;
-       if (!equalstr(a->newname, b->newname))
-               return false;
-       if (a->renameType != b->renameType)
-               return false;
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_STRING_FIELD(oldname);
+       COMPARE_STRING_FIELD(newname);
+       COMPARE_SCALAR_FIELD(renameType);
 
        return true;
 }
@@ -1031,20 +885,13 @@ _equalRenameStmt(RenameStmt *a, RenameStmt *b)
 static bool
 _equalRuleStmt(RuleStmt *a, RuleStmt *b)
 {
-       if (!equal(a->relation, b->relation))
-               return false;
-       if (!equalstr(a->rulename, b->rulename))
-               return false;
-       if (!equal(a->whereClause, b->whereClause))
-               return false;
-       if (a->event != b->event)
-               return false;
-       if (a->instead != b->instead)
-               return false;
-       if (a->replace != b->replace)
-               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;
 }
@@ -1052,8 +899,7 @@ _equalRuleStmt(RuleStmt *a, RuleStmt *b)
 static bool
 _equalNotifyStmt(NotifyStmt *a, NotifyStmt *b)
 {
-       if (!equal(a->relation, b->relation))
-               return false;
+       COMPARE_NODE_FIELD(relation);
 
        return true;
 }
@@ -1061,8 +907,7 @@ _equalNotifyStmt(NotifyStmt *a, NotifyStmt *b)
 static bool
 _equalListenStmt(ListenStmt *a, ListenStmt *b)
 {
-       if (!equal(a->relation, b->relation))
-               return false;
+       COMPARE_NODE_FIELD(relation);
 
        return true;
 }
@@ -1070,8 +915,7 @@ _equalListenStmt(ListenStmt *a, ListenStmt *b)
 static bool
 _equalUnlistenStmt(UnlistenStmt *a, UnlistenStmt *b)
 {
-       if (!equal(a->relation, b->relation))
-               return false;
+       COMPARE_NODE_FIELD(relation);
 
        return true;
 }
@@ -1079,10 +923,8 @@ _equalUnlistenStmt(UnlistenStmt *a, UnlistenStmt *b)
 static bool
 _equalTransactionStmt(TransactionStmt *a, TransactionStmt *b)
 {
-       if (a->command != b->command)
-               return false;
-       if (!equal(a->options, b->options))
-               return false;
+       COMPARE_SCALAR_FIELD(command);
+       COMPARE_NODE_FIELD(options);
 
        return true;
 }
@@ -1090,25 +932,19 @@ _equalTransactionStmt(TransactionStmt *a, TransactionStmt *b)
 static bool
 _equalCompositeTypeStmt(CompositeTypeStmt *a, CompositeTypeStmt *b)
 {
-       if (!equal(a->typevar, b->typevar))
-               return false;
-       if (!equal(a->coldeflist, b->coldeflist))
-               return false;
+       COMPARE_NODE_FIELD(typevar);
+       COMPARE_NODE_FIELD(coldeflist);
 
        return true;
 }
 
-static bool
-_equalViewStmt(ViewStmt *a, ViewStmt *b)
-{
-       if (!equal(a->view, b->view))
-               return false;
-       if (!equal(a->aliases, b->aliases))
-               return false;
-       if (!equal(a->query, b->query))
-               return false;
-       if (a->replace != b->replace)
-               return false;
+static bool
+_equalViewStmt(ViewStmt *a, ViewStmt *b)
+{
+       COMPARE_NODE_FIELD(view);
+       COMPARE_NODE_FIELD(aliases);
+       COMPARE_NODE_FIELD(query);
+       COMPARE_SCALAR_FIELD(replace);
 
        return true;
 }
@@ -1116,8 +952,7 @@ _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;
 }
@@ -1125,12 +960,9 @@ _equalLoadStmt(LoadStmt *a, LoadStmt *b)
 static bool
 _equalCreateDomainStmt(CreateDomainStmt *a, CreateDomainStmt *b)
 {
-       if (!equal(a->domainname, b->domainname))
-               return false;
-       if (!equal(a->typename, b->typename))
-               return false;
-       if (!equal(a->constraints, b->constraints))
-               return false;
+       COMPARE_NODE_FIELD(domainname);
+       COMPARE_NODE_FIELD(typename);
+       COMPARE_NODE_FIELD(constraints);
 
        return true;
 }
@@ -1138,16 +970,11 @@ _equalCreateDomainStmt(CreateDomainStmt *a, CreateDomainStmt *b)
 static bool
 _equalCreateOpClassStmt(CreateOpClassStmt *a, CreateOpClassStmt *b)
 {
-       if (!equal(a->opclassname, b->opclassname))
-               return false;
-       if (!equalstr(a->amname, b->amname))
-               return false;
-       if (!equal(a->datatype, b->datatype))
-               return false;
-       if (!equal(a->items, b->items))
-               return false;
-       if (a->isDefault != b->isDefault)
-               return false;
+       COMPARE_NODE_FIELD(opclassname);
+       COMPARE_STRING_FIELD(amname);
+       COMPARE_NODE_FIELD(datatype);
+       COMPARE_NODE_FIELD(items);
+       COMPARE_SCALAR_FIELD(isDefault);
 
        return true;
 }
@@ -1155,18 +982,12 @@ _equalCreateOpClassStmt(CreateOpClassStmt *a, CreateOpClassStmt *b)
 static bool
 _equalCreateOpClassItem(CreateOpClassItem *a, CreateOpClassItem *b)
 {
-       if (a->itemtype != b->itemtype)
-               return false;
-       if (!equal(a->name, b->name))
-               return false;
-       if (!equal(a->args, b->args))
-               return false;
-       if (a->number != b->number)
-               return false;
-       if (a->recheck != b->recheck)
-               return false;
-       if (!equal(a->storedtype, b->storedtype))
-               return false;
+       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;
 }
@@ -1174,10 +995,8 @@ _equalCreateOpClassItem(CreateOpClassItem *a, CreateOpClassItem *b)
 static bool
 _equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b)
 {
-       if (!equalstr(a->dbname, b->dbname))
-               return false;
-       if (!equal(a->options, b->options))
-               return false;
+       COMPARE_STRING_FIELD(dbname);
+       COMPARE_NODE_FIELD(options);
 
        return true;
 }
@@ -1185,12 +1004,9 @@ _equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b)
 static bool
 _equalAlterDatabaseSetStmt(AlterDatabaseSetStmt *a, AlterDatabaseSetStmt *b)
 {
-       if (!equalstr(a->dbname, b->dbname))
-               return false;
-       if (!equalstr(a->variable, b->variable))
-               return false;
-       if (!equal(a->value, b->value))
-               return false;
+       COMPARE_STRING_FIELD(dbname);
+       COMPARE_STRING_FIELD(variable);
+       COMPARE_NODE_FIELD(value);
 
        return true;
 }
@@ -1198,8 +1014,7 @@ _equalAlterDatabaseSetStmt(AlterDatabaseSetStmt *a, AlterDatabaseSetStmt *b)
 static bool
 _equalDropdbStmt(DropdbStmt *a, DropdbStmt *b)
 {
-       if (!equalstr(a->dbname, b->dbname))
-               return false;
+       COMPARE_STRING_FIELD(dbname);
 
        return true;
 }
@@ -1207,20 +1022,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 (!equal(a->relation, b->relation))
-               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;
 }
@@ -1228,12 +1036,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;
 }
@@ -1241,10 +1046,8 @@ _equalExplainStmt(ExplainStmt *a, ExplainStmt *b)
 static bool
 _equalCreateSeqStmt(CreateSeqStmt *a, CreateSeqStmt *b)
 {
-       if (!equal(a->sequence, b->sequence))
-               return false;
-       if (!equal(a->options, b->options))
-               return false;
+       COMPARE_NODE_FIELD(sequence);
+       COMPARE_NODE_FIELD(options);
 
        return true;
 }
@@ -1252,12 +1055,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;
-       if (a->is_local != b->is_local)
-               return false;
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(args);
+       COMPARE_SCALAR_FIELD(is_local);
 
        return true;
 }
@@ -1265,8 +1065,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;
 }
@@ -1274,8 +1073,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;
 }
@@ -1283,28 +1081,18 @@ _equalVariableResetStmt(VariableResetStmt *a, VariableResetStmt *b)
 static bool
 _equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b)
 {
-       if (!equalstr(a->trigname, b->trigname))
-               return false;
-       if (!equal(a->relation, b->relation))
-               return false;
-       if (!equal(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 (a->isconstraint != b->isconstraint)
-               return false;
-       if (a->deferrable != b->deferrable)
-               return false;
-       if (a->initdeferred != b->initdeferred)
-               return false;
-       if (!equal(a->constrrel, b->constrrel))
+       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;
 }
@@ -1312,14 +1100,10 @@ _equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b)
 static bool
 _equalDropPropertyStmt(DropPropertyStmt *a, DropPropertyStmt *b)
 {
-       if (!equal(a->relation, b->relation))
-               return false;
-       if (!equalstr(a->property, b->property))
-               return false;
-       if (a->removeType != b->removeType)
-               return false;
-       if (a->behavior != b->behavior)
-               return false;
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_STRING_FIELD(property);
+       COMPARE_SCALAR_FIELD(removeType);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
@@ -1327,14 +1111,10 @@ _equalDropPropertyStmt(DropPropertyStmt *a, DropPropertyStmt *b)
 static bool
 _equalCreatePLangStmt(CreatePLangStmt *a, CreatePLangStmt *b)
 {
-       if (!equalstr(a->plname, b->plname))
-               return false;
-       if (!equal(a->plhandler, b->plhandler))
-               return false;
-       if (!equal(a->plvalidator, b->plvalidator))
-               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;
 }
@@ -1342,10 +1122,8 @@ _equalCreatePLangStmt(CreatePLangStmt *a, CreatePLangStmt *b)
 static bool
 _equalDropPLangStmt(DropPLangStmt *a, DropPLangStmt *b)
 {
-       if (!equalstr(a->plname, b->plname))
-               return false;
-       if (a->behavior != b->behavior)
-               return false;
+       COMPARE_STRING_FIELD(plname);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
@@ -1353,10 +1131,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;
 }
@@ -1364,10 +1140,8 @@ _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;
 }
@@ -1375,12 +1149,9 @@ _equalAlterUserStmt(AlterUserStmt *a, AlterUserStmt *b)
 static bool
 _equalAlterUserSetStmt(AlterUserSetStmt *a, AlterUserSetStmt *b)
 {
-       if (!equalstr(a->user, b->user))
-               return false;
-       if (!equalstr(a->variable, b->variable))
-               return false;
-       if (!equal(a->value, b->value))
-               return false;
+       COMPARE_STRING_FIELD(user);
+       COMPARE_STRING_FIELD(variable);
+       COMPARE_NODE_FIELD(value);
 
        return true;
 }
@@ -1388,8 +1159,7 @@ _equalAlterUserSetStmt(AlterUserSetStmt *a, AlterUserSetStmt *b)
 static bool
 _equalDropUserStmt(DropUserStmt *a, DropUserStmt *b)
 {
-       if (!equal(a->users, b->users))
-               return false;
+       COMPARE_NODE_FIELD(users);
 
        return true;
 }
@@ -1397,10 +1167,8 @@ _equalDropUserStmt(DropUserStmt *a, DropUserStmt *b)
 static bool
 _equalLockStmt(LockStmt *a, LockStmt *b)
 {
-       if (!equal(a->relations, b->relations))
-               return false;
-       if (a->mode != b->mode)
-               return false;
+       COMPARE_NODE_FIELD(relations);
+       COMPARE_SCALAR_FIELD(mode);
 
        return true;
 }
@@ -1408,10 +1176,8 @@ _equalLockStmt(LockStmt *a, LockStmt *b)
 static bool
 _equalConstraintsSetStmt(ConstraintsSetStmt *a, ConstraintsSetStmt *b)
 {
-       if (!equal(a->constraints, b->constraints))
-               return false;
-       if (a->deferred != b->deferred)
-               return false;
+       COMPARE_NODE_FIELD(constraints);
+       COMPARE_SCALAR_FIELD(deferred);
 
        return true;
 }
@@ -1419,10 +1185,8 @@ _equalConstraintsSetStmt(ConstraintsSetStmt *a, ConstraintsSetStmt *b)
 static bool
 _equalCreateGroupStmt(CreateGroupStmt *a, CreateGroupStmt *b)
 {
-       if (!equalstr(a->name, b->name))
-               return false;
-       if (!equal(a->options, b->options))
-               return false;
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(options);
 
        return true;
 }
@@ -1430,12 +1194,9 @@ _equalCreateGroupStmt(CreateGroupStmt *a, CreateGroupStmt *b)
 static bool
 _equalAlterGroupStmt(AlterGroupStmt *a, AlterGroupStmt *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_STRING_FIELD(name);
+       COMPARE_SCALAR_FIELD(action);
+       COMPARE_NODE_FIELD(listUsers);
 
        return true;
 }
@@ -1443,8 +1204,7 @@ _equalAlterGroupStmt(AlterGroupStmt *a, AlterGroupStmt *b)
 static bool
 _equalDropGroupStmt(DropGroupStmt *a, DropGroupStmt *b)
 {
-       if (!equalstr(a->name, b->name))
-               return false;
+       COMPARE_STRING_FIELD(name);
 
        return true;
 }
@@ -1452,16 +1212,11 @@ _equalDropGroupStmt(DropGroupStmt *a, DropGroupStmt *b)
 static bool
 _equalReindexStmt(ReindexStmt *a, ReindexStmt *b)
 {
-       if (a->reindexType != b->reindexType)
-               return false;
-       if (!equal(a->relation, b->relation))
-               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_SCALAR_FIELD(reindexType);
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_STRING_FIELD(name);
+       COMPARE_SCALAR_FIELD(force);
+       COMPARE_SCALAR_FIELD(all);
 
        return true;
 }
@@ -1469,12 +1224,9 @@ _equalReindexStmt(ReindexStmt *a, ReindexStmt *b)
 static bool
 _equalCreateSchemaStmt(CreateSchemaStmt *a, CreateSchemaStmt *b)
 {
-       if (!equalstr(a->schemaname, b->schemaname))
-               return false;
-       if (!equalstr(a->authid, b->authid))
-               return false;
-       if (!equal(a->schemaElts, b->schemaElts))
-               return false;
+       COMPARE_STRING_FIELD(schemaname);
+       COMPARE_STRING_FIELD(authid);
+       COMPARE_NODE_FIELD(schemaElts);
 
        return true;
 }
@@ -1482,16 +1234,11 @@ _equalCreateSchemaStmt(CreateSchemaStmt *a, CreateSchemaStmt *b)
 static bool
 _equalCreateConversionStmt(CreateConversionStmt *a, CreateConversionStmt *b)
 {
-       if (!equal(a->conversion_name, b->conversion_name))
-               return false;
-       if (!equalstr(a->for_encoding_name, b->for_encoding_name))
-               return false;
-       if (!equalstr(a->to_encoding_name, b->to_encoding_name))
-               return false;
-       if (!equal(a->func_name, b->func_name))
-               return false;
-       if (a->def != b->def)
-               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;
 }
@@ -1499,14 +1246,10 @@ _equalCreateConversionStmt(CreateConversionStmt *a, CreateConversionStmt *b)
 static bool
 _equalCreateCastStmt(CreateCastStmt *a, CreateCastStmt *b)
 {
-       if (!equal(a->sourcetype, b->sourcetype))
-               return false;
-       if (!equal(a->targettype, b->targettype))
-               return false;
-       if (!equal(a->func, b->func))
-               return false;
-       if (a->context != b->context)
-               return false;
+       COMPARE_NODE_FIELD(sourcetype);
+       COMPARE_NODE_FIELD(targettype);
+       COMPARE_NODE_FIELD(func);
+       COMPARE_SCALAR_FIELD(context);
 
        return true;
 }
@@ -1514,12 +1257,9 @@ _equalCreateCastStmt(CreateCastStmt *a, CreateCastStmt *b)
 static bool
 _equalDropCastStmt(DropCastStmt *a, DropCastStmt *b)
 {
-       if (!equal(a->sourcetype, b->sourcetype))
-               return false;
-       if (!equal(a->targettype, b->targettype))
-               return false;
-       if (a->behavior != b->behavior)
-               return false;
+       COMPARE_NODE_FIELD(sourcetype);
+       COMPARE_NODE_FIELD(targettype);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
@@ -1527,14 +1267,10 @@ _equalDropCastStmt(DropCastStmt *a, DropCastStmt *b)
 static bool
 _equalPrepareStmt(PrepareStmt *a, PrepareStmt *b)
 {
-       if (!equalstr(a->name, b->name))
-               return false;
-       if (!equal(a->argtypes, b->argtypes))
-               return false;
-       if (!equali(a->argtype_oids, b->argtype_oids))
-               return false;
-       if (!equal(a->query, b->query))
-               return false;
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(argtypes);
+       COMPARE_INTLIST_FIELD(argtype_oids);
+       COMPARE_NODE_FIELD(query);
 
        return true;
 }
@@ -1542,12 +1278,9 @@ _equalPrepareStmt(PrepareStmt *a, PrepareStmt *b)
 static bool
 _equalExecuteStmt(ExecuteStmt *a, ExecuteStmt *b)
 {
-       if (!equalstr(a->name, b->name))
-               return false;
-       if (!equal(a->into, b->into))
-               return false;
-       if (!equal(a->params, b->params))
-               return false;
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(into);
+       COMPARE_NODE_FIELD(params);
 
        return true;
 }
@@ -1555,23 +1288,23 @@ _equalExecuteStmt(ExecuteStmt *a, ExecuteStmt *b)
 static bool
 _equalDeallocateStmt(DeallocateStmt *a, DeallocateStmt *b)
 {
-       if (!equalstr(a->name, b->name))
-               return false;
+       COMPARE_STRING_FIELD(name);
 
        return true;
 }
 
+
+/*
+ * stuff from parsenodes.h
+ */
+
 static bool
 _equalAExpr(A_Expr *a, A_Expr *b)
 {
-       if (a->oper != b->oper)
-               return false;
-       if (!equal(a->name, b->name))
-               return false;
-       if (!equal(a->lexpr, b->lexpr))
-               return false;
-       if (!equal(a->rexpr, b->rexpr))
-               return false;
+       COMPARE_SCALAR_FIELD(oper);
+       COMPARE_NODE_FIELD(name);
+       COMPARE_NODE_FIELD(lexpr);
+       COMPARE_NODE_FIELD(rexpr);
 
        return true;
 }
@@ -1579,10 +1312,8 @@ _equalAExpr(A_Expr *a, A_Expr *b)
 static bool
 _equalColumnRef(ColumnRef *a, ColumnRef *b)
 {
-       if (!equal(a->fields, b->fields))
-               return false;
-       if (!equal(a->indirection, b->indirection))
-               return false;
+       COMPARE_NODE_FIELD(fields);
+       COMPARE_NODE_FIELD(indirection);
 
        return true;
 }
@@ -1590,12 +1321,9 @@ _equalColumnRef(ColumnRef *a, ColumnRef *b)
 static bool
 _equalParamRef(ParamRef *a, ParamRef *b)
 {
-       if (a->number != b->number)
-               return false;
-       if (!equal(a->fields, b->fields))
-               return false;
-       if (!equal(a->indirection, b->indirection))
-               return false;
+       COMPARE_SCALAR_FIELD(number);
+       COMPARE_NODE_FIELD(fields);
+       COMPARE_NODE_FIELD(indirection);
 
        return true;
 }
@@ -1603,10 +1331,9 @@ _equalParamRef(ParamRef *a, ParamRef *b)
 static bool
 _equalAConst(A_Const *a, A_Const *b)
 {
-       if (!equal(&a->val, &b->val))
-               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;
 }
@@ -1614,14 +1341,10 @@ _equalAConst(A_Const *a, A_Const *b)
 static bool
 _equalFuncCall(FuncCall *a, FuncCall *b)
 {
-       if (!equal(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_NODE_FIELD(funcname);
+       COMPARE_NODE_FIELD(args);
+       COMPARE_SCALAR_FIELD(agg_star);
+       COMPARE_SCALAR_FIELD(agg_distinct);
 
        return true;
 }
@@ -1629,10 +1352,8 @@ _equalFuncCall(FuncCall *a, FuncCall *b)
 static bool
 _equalAIndices(A_Indices *a, A_Indices *b)
 {
-       if (!equal(a->lidx, b->lidx))
-               return false;
-       if (!equal(a->uidx, b->uidx))
-               return false;
+       COMPARE_NODE_FIELD(lidx);
+       COMPARE_NODE_FIELD(uidx);
 
        return true;
 }
@@ -1640,12 +1361,9 @@ _equalAIndices(A_Indices *a, A_Indices *b)
 static bool
 _equalExprFieldSelect(ExprFieldSelect *a, ExprFieldSelect *b)
 {
-       if (!equal(a->arg, b->arg))
-               return false;
-       if (!equal(a->fields, b->fields))
-               return false;
-       if (!equal(a->indirection, b->indirection))
-               return false;
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_NODE_FIELD(fields);
+       COMPARE_NODE_FIELD(indirection);
 
        return true;
 }
@@ -1653,64 +1371,41 @@ _equalExprFieldSelect(ExprFieldSelect *a, ExprFieldSelect *b)
 static bool
 _equalResTarget(ResTarget *a, ResTarget *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;
-
-       return true;
-}
-
-static bool
-_equalTypeCast(TypeCast *a, TypeCast *b)
-{
-       if (!equal(a->arg, b->arg))
-               return false;
-       if (!equal(a->typename, b->typename))
-               return false;
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(indirection);
+       COMPARE_NODE_FIELD(val);
 
        return true;
 }
 
 static bool
-_equalSortGroupBy(SortGroupBy *a, SortGroupBy *b)
+_equalTypeName(TypeName *a, TypeName *b)
 {
-       if (!equal(a->useOp, b->useOp))
-               return false;
-       if (!equal(a->node, b->node))
-               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
-_equalAlias(Alias *a, Alias *b)
+_equalTypeCast(TypeCast *a, TypeCast *b)
 {
-       if (!equalstr(a->aliasname, b->aliasname))
-               return false;
-       if (!equal(a->colnames, b->colnames))
-               return false;
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_NODE_FIELD(typename);
 
        return true;
 }
 
 static bool
-_equalRangeVar(RangeVar *a, RangeVar *b)
+_equalSortGroupBy(SortGroupBy *a, SortGroupBy *b)
 {
-       if (!equalstr(a->catalogname, b->catalogname))
-               return false;
-       if (!equalstr(a->schemaname, b->schemaname))
-               return false;
-       if (!equalstr(a->relname, b->relname))
-               return false;
-       if (a->inhOpt != b->inhOpt)
-               return false;
-       if (a->istemp != b->istemp)
-               return false;
-       if (!equal(a->alias, b->alias))
-               return false;
+       COMPARE_NODE_FIELD(useOp);
+       COMPARE_NODE_FIELD(node);
 
        return true;
 }
@@ -1718,10 +1413,8 @@ _equalRangeVar(RangeVar *a, RangeVar *b)
 static bool
 _equalRangeSubselect(RangeSubselect *a, RangeSubselect *b)
 {
-       if (!equal(a->subquery, b->subquery))
-               return false;
-       if (!equal(a->alias, b->alias))
-               return false;
+       COMPARE_NODE_FIELD(subquery);
+       COMPARE_NODE_FIELD(alias);
 
        return true;
 }
@@ -1729,33 +1422,9 @@ _equalRangeSubselect(RangeSubselect *a, RangeSubselect *b)
 static bool
 _equalRangeFunction(RangeFunction *a, RangeFunction *b)
 {
-       if (!equal(a->funccallnode, b->funccallnode))
-               return false;
-       if (!equal(a->alias, b->alias))
-               return false;
-       if (!equal(a->coldeflist, b->coldeflist))
-               return false;
-
-       return true;
-}
-
-static bool
-_equalTypeName(TypeName *a, TypeName *b)
-{
-       if (!equal(a->names, b->names))
-               return false;
-       if (a->typeid != b->typeid)
-               return false;
-       if (a->timezone != b->timezone)
-               return false;
-       if (a->setof != b->setof)
-               return false;
-       if (a->pct_type != b->pct_type)
-               return false;
-       if (a->typmod != b->typmod)
-               return false;
-       if (!equal(a->arrayBounds, b->arrayBounds))
-               return false;
+       COMPARE_NODE_FIELD(funccallnode);
+       COMPARE_NODE_FIELD(alias);
+       COMPARE_NODE_FIELD(coldeflist);
 
        return true;
 }
@@ -1763,14 +1432,10 @@ _equalTypeName(TypeName *a, TypeName *b)
 static bool
 _equalIndexElem(IndexElem *a, IndexElem *b)
 {
-       if (!equalstr(a->name, b->name))
-               return false;
-       if (!equal(a->funcname, b->funcname))
-               return false;
-       if (!equal(a->args, b->args))
-               return false;
-       if (!equal(a->opclass, b->opclass))
-               return false;
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(funcname);
+       COMPARE_NODE_FIELD(args);
+       COMPARE_NODE_FIELD(opclass);
 
        return true;
 }
@@ -1778,24 +1443,15 @@ _equalIndexElem(IndexElem *a, IndexElem *b)
 static bool
 _equalColumnDef(ColumnDef *a, ColumnDef *b)
 {
-       if (!equalstr(a->colname, b->colname))
-               return false;
-       if (!equal(a->typename, b->typename))
-               return false;
-       if (a->inhcount != b->inhcount)
-               return false;
-       if (a->is_local != b->is_local)
-               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;
-       if (!equal(a->support, b->support))
-               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;
 }
@@ -1803,16 +1459,11 @@ _equalColumnDef(ColumnDef *a, ColumnDef *b)
 static bool
 _equalConstraint(Constraint *a, Constraint *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_SCALAR_FIELD(contype);
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(raw_expr);
+       COMPARE_STRING_FIELD(cooked_expr);
+       COMPARE_NODE_FIELD(keys);
 
        return true;
 }
@@ -1820,10 +1471,8 @@ _equalConstraint(Constraint *a, Constraint *b)
 static bool
 _equalDefElem(DefElem *a, DefElem *b)
 {
-       if (!equalstr(a->defname, b->defname))
-               return false;
-       if (!equal(a->arg, b->arg))
-               return false;
+       COMPARE_STRING_FIELD(defname);
+       COMPARE_NODE_FIELD(arg);
 
        return true;
 }
@@ -1831,12 +1480,9 @@ _equalDefElem(DefElem *a, DefElem *b)
 static bool
 _equalTargetEntry(TargetEntry *a, TargetEntry *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(resdom);
+       COMPARE_NODE_FIELD(fjoin);
+       COMPARE_NODE_FIELD(expr);
 
        return true;
 }
@@ -1844,34 +1490,20 @@ _equalTargetEntry(TargetEntry *a, TargetEntry *b)
 static bool
 _equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
 {
-       if (a->rtekind != b->rtekind)
-               return false;
-       if (a->relid != b->relid)
-               return false;
-       if (!equal(a->subquery, b->subquery))
-               return false;
-       if (!equal(a->funcexpr, b->funcexpr))
-               return false;
-       if (!equal(a->coldeflist, b->coldeflist))
-               return false;
-       if (a->jointype != b->jointype)
-               return false;
-       if (!equal(a->joinaliasvars, b->joinaliasvars))
-               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_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;
 }
@@ -1879,10 +1511,8 @@ _equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
 static bool
 _equalSortClause(SortClause *a, SortClause *b)
 {
-       if (a->tleSortGroupRef != b->tleSortGroupRef)
-               return false;
-       if (a->sortop != b->sortop)
-               return false;
+       COMPARE_SCALAR_FIELD(tleSortGroupRef);
+       COMPARE_SCALAR_FIELD(sortop);
 
        return true;
 }
@@ -1890,26 +1520,16 @@ _equalSortClause(SortClause *a, SortClause *b)
 static bool
 _equalFkConstraint(FkConstraint *a, FkConstraint *b)
 {
-       if (!equalstr(a->constr_name, b->constr_name))
-               return false;
-       if (!equal(a->pktable, b->pktable))
-               return false;
-       if (!equal(a->fk_attrs, b->fk_attrs))
-               return false;
-       if (!equal(a->pk_attrs, b->pk_attrs))
-               return false;
-       if (a->fk_matchtype != b->fk_matchtype)
-               return false;
-       if (a->fk_upd_action != b->fk_upd_action)
-               return false;
-       if (a->fk_del_action != b->fk_del_action)
-               return false;
-       if (a->deferrable != b->deferrable)
-               return false;
-       if (a->initdeferred != b->initdeferred)
-               return false;
-       if (a->skip_validation != b->skip_validation)
-               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;
 }
@@ -1917,14 +1537,10 @@ _equalFkConstraint(FkConstraint *a, FkConstraint *b)
 static bool
 _equalCaseExpr(CaseExpr *a, CaseExpr *b)
 {
-       if (a->casetype != b->casetype)
-               return false;
-       if (!equal(a->arg, b->arg))
-               return false;
-       if (!equal(a->args, b->args))
-               return false;
-       if (!equal(a->defresult, b->defresult))
-               return false;
+       COMPARE_SCALAR_FIELD(casetype);
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_NODE_FIELD(args);
+       COMPARE_NODE_FIELD(defresult);
 
        return true;
 }
@@ -1932,10 +1548,8 @@ _equalCaseExpr(CaseExpr *a, CaseExpr *b)
 static bool
 _equalCaseWhen(CaseWhen *a, CaseWhen *b)
 {
-       if (!equal(a->expr, b->expr))
-               return false;
-       if (!equal(a->result, b->result))
-               return false;
+       COMPARE_NODE_FIELD(expr);
+       COMPARE_NODE_FIELD(result);
 
        return true;
 }
@@ -1943,72 +1557,68 @@ _equalCaseWhen(CaseWhen *a, CaseWhen *b)
 static bool
 _equalNullTest(NullTest *a, NullTest *b)
 {
-       if (!equal(a->arg, b->arg))
-               return false;
-       if (a->nulltesttype != b->nulltesttype)
-               return false;
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_SCALAR_FIELD(nulltesttype);
+
        return true;
 }
 
 static bool
 _equalBooleanTest(BooleanTest *a, BooleanTest *b)
 {
-       if (!equal(a->arg, b->arg))
-               return false;
-       if (a->booltesttype != b->booltesttype)
-               return false;
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_SCALAR_FIELD(booltesttype);
+
        return true;
 }
 
 static bool
 _equalConstraintTest(ConstraintTest *a, ConstraintTest *b)
 {
-       if (!equal(a->arg, b->arg))
-               return false;
-       if (a->testtype != b->testtype)
-               return false;
-       if (!equalstr(a->name, b->name))
-               return false;
-       if (!equalstr(a->domname, b->domname))
-               return false;
-       if (!equal(a->check_expr, b->check_expr))
-               return false;
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_SCALAR_FIELD(testtype);
+       COMPARE_STRING_FIELD(name);
+       COMPARE_STRING_FIELD(domname);
+       COMPARE_NODE_FIELD(check_expr);
+
        return true;
 }
 
 static bool
-_equalConstraintTestValue(ConstraintTestValue *a, ConstraintTestValue *b)
+_equalDomainConstraintValue(DomainConstraintValue *a, DomainConstraintValue *b)
 {
-       if (a->typeId != b->typeId)
-               return false;
-       if (a->typeMod != b->typeMod)
-               return false;
        return true;
 }
 
 static bool
-_equalDomainConstraintValue(DomainConstraintValue *a, DomainConstraintValue *b)
+_equalConstraintTestValue(ConstraintTestValue *a, ConstraintTestValue *b)
 {
+       COMPARE_SCALAR_FIELD(typeId);
+       COMPARE_SCALAR_FIELD(typeMod);
+
        return true;
 }
 
+
 /*
  * Stuff from pg_list.h
  */
+
 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;