diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index da3bf7b7213d0c0542fa879d2d8d81394bb87875..0f02b5d119bb4fcd17701396f515a6bec2b9c3bc 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,11 +28,44 @@
 
 
 /*
- * 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;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 3e0ea75d2518deda2cfe37ddfcad0def960e6c3d..f417dec4886ce546320034639c90892e8f6214b2 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -32,10 +32,52 @@
 #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
@@ -44,21 +86,14 @@
 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;