]> granicus.if.org Git - postgresql/blobdiff - src/backend/nodes/equalfuncs.c
Support UPDATE/DELETE WHERE CURRENT OF cursor_name, per SQL standard.
[postgresql] / src / backend / nodes / equalfuncs.c
index 83c2cb4245cc8d9a33475dc624888c23438b62ca..04072c7a65422560271d422496ac86230e40f817 100644 (file)
@@ -3,38 +3,35 @@
  * equalfuncs.c
  *       Equality functions to compare node trees.
  *
- * NOTE: a general convention when copying or comparing plan nodes is
- * that we ignore the executor state subnode.  We do not need to look
- * at it because no current uses of copyObject() or equal() need to
- * deal with already-executing plan trees.     By leaving the state subnodes
- * out, we avoid needing to write copy/compare routines for all the
- * different executor state node types.
+ * NOTE: we currently support comparing all node types found in parse
+ * trees.  We do not support comparing executor state trees; there
+ * is no need for that, and no point in maintaining all the code that
+ * would be needed.  We also do not support comparing Path trees, mainly
+ * because the circular linkages between RelOptInfo and Path nodes can't
+ * be handled easily in a simple depth-first traversal.
  *
- * Currently, in fact, equal() doesn't know how to compare Plan nodes
- * at all, let alone their executor-state subnodes.  This will probably
- * need to be fixed someday, but presently there is no need to compare
- * plan trees.
+ * Currently, in fact, equal() doesn't know how to compare Plan trees
+ * either.     This might need to be fixed someday.
  *
  *
- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.169 2002/11/25 21:29:36 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.309 2007/06/11 01:16:22 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "postgres.h"
 
-#include "nodes/plannodes.h"
 #include "nodes/relation.h"
 #include "utils/datum.h"
 
 
 /*
- * Macros to simplify comparison of different kinds of fields.  Use these
- * wherever possible to reduce the chance for silly typos.  Note that these
+ * 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'.
  */
                        return false; \
        } while (0)
 
-/* Compare a field that is a pointer to a list of integers */
-#define COMPARE_INTLIST_FIELD(fldname) \
+/* Compare a field that is a pointer to a Bitmapset */
+#define COMPARE_BITMAPSET_FIELD(fldname) \
        do { \
-               if (!equali(a->fldname, b->fldname)) \
+               if (!bms_equal(a->fldname, b->fldname)) \
                        return false; \
        } while (0)
 
  *     Stuff from primnodes.h
  */
 
-static bool
-_equalResdom(Resdom *a, Resdom *b)
-{
-       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;
-}
-
-static bool
-_equalFjoin(Fjoin *a, Fjoin *b)
-{
-       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));
-
-       return true;
-}
-
 static bool
 _equalAlias(Alias *a, Alias *b)
 {
@@ -133,20 +103,24 @@ _equalRangeVar(RangeVar *a, RangeVar *b)
 }
 
 static bool
-_equalExpr(Expr *a, Expr *b)
+_equalIntoClause(IntoClause *a, IntoClause *b)
 {
-       /*
-        * We do not examine typeOid, since the optimizer often doesn't bother
-        * to set it in created nodes, and it is logically a derivative of the
-        * oper field anyway.
-        */
-       COMPARE_SCALAR_FIELD(opType);
-       COMPARE_NODE_FIELD(oper);
-       COMPARE_NODE_FIELD(args);
+       COMPARE_NODE_FIELD(rel);
+       COMPARE_NODE_FIELD(colNames);
+       COMPARE_NODE_FIELD(options);
+       COMPARE_SCALAR_FIELD(onCommit);
+       COMPARE_STRING_FIELD(tableSpaceName);
 
        return true;
 }
 
+/*
+ * We don't need an _equalExpr because Expr is an abstract supertype which
+ * should never actually get instantiated.     Also, since it has no common
+ * fields except NodeTag, there's no need for a helper routine to factor
+ * out comparing the common fields...
+ */
+
 static bool
 _equalVar(Var *a, Var *b)
 {
@@ -161,40 +135,18 @@ _equalVar(Var *a, Var *b)
        return true;
 }
 
-static bool
-_equalOper(Oper *a, Oper *b)
-{
-       COMPARE_SCALAR_FIELD(opno);
-       COMPARE_SCALAR_FIELD(opresulttype);
-       COMPARE_SCALAR_FIELD(opretset);
-
-       /*
-        * We do not examine opid or op_fcache, since these are logically
-        * derived from opno, and they may not be set yet depending on how far
-        * along the node is in the parse/plan pipeline.
-        *
-        * (Besides, op_fcache is executor state, which we don't check --- see
-        * notes at head of file.)
-        *
-        * It's probably not really necessary to check opresulttype or opretset,
-        * either...
-        */
-
-       return true;
-}
-
 static bool
 _equalConst(Const *a, Const *b)
 {
        COMPARE_SCALAR_FIELD(consttype);
+       COMPARE_SCALAR_FIELD(consttypmod);
        COMPARE_SCALAR_FIELD(constlen);
        COMPARE_SCALAR_FIELD(constisnull);
        COMPARE_SCALAR_FIELD(constbyval);
 
        /*
         * We treat all NULL constants of the same type as equal. Someday this
-        * might need to change?  But datumIsEqual doesn't work on nulls,
-        * so...
+        * might need to change?  But datumIsEqual doesn't work on nulls, so...
         */
        if (a->constisnull)
                return true;
@@ -206,54 +158,134 @@ static bool
 _equalParam(Param *a, Param *b)
 {
        COMPARE_SCALAR_FIELD(paramkind);
+       COMPARE_SCALAR_FIELD(paramid);
        COMPARE_SCALAR_FIELD(paramtype);
+       COMPARE_SCALAR_FIELD(paramtypmod);
 
-       switch (a->paramkind)
-       {
-               case PARAM_NAMED:
-                       COMPARE_STRING_FIELD(paramname);
-                       break;
-               case PARAM_NUM:
-               case PARAM_EXEC:
-                       COMPARE_SCALAR_FIELD(paramid);
-                       break;
-               default:
-                       elog(ERROR, "_equalParam: Invalid paramkind value: %d",
-                                a->paramkind);
-       }
+       return true;
+}
+
+static bool
+_equalAggref(Aggref *a, Aggref *b)
+{
+       COMPARE_SCALAR_FIELD(aggfnoid);
+       COMPARE_SCALAR_FIELD(aggtype);
+       COMPARE_NODE_FIELD(args);
+       COMPARE_SCALAR_FIELD(agglevelsup);
+       COMPARE_SCALAR_FIELD(aggstar);
+       COMPARE_SCALAR_FIELD(aggdistinct);
+
+       return true;
+}
+
+static bool
+_equalArrayRef(ArrayRef *a, ArrayRef *b)
+{
+       COMPARE_SCALAR_FIELD(refarraytype);
+       COMPARE_SCALAR_FIELD(refelemtype);
+       COMPARE_SCALAR_FIELD(reftypmod);
+       COMPARE_NODE_FIELD(refupperindexpr);
+       COMPARE_NODE_FIELD(reflowerindexpr);
+       COMPARE_NODE_FIELD(refexpr);
+       COMPARE_NODE_FIELD(refassgnexpr);
 
        return true;
 }
 
 static bool
-_equalFunc(Func *a, Func *b)
+_equalFuncExpr(FuncExpr *a, FuncExpr *b)
 {
        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.
+        * Special-case COERCE_DONTCARE, so that planner can build coercion nodes
+        * that are equal() to both explicit and implicit coercions.
         */
        if (a->funcformat != b->funcformat &&
                a->funcformat != COERCE_DONTCARE &&
                b->funcformat != COERCE_DONTCARE)
                return false;
 
-       /* Note we do not look at func_fcache; see notes for _equalOper */
+       COMPARE_NODE_FIELD(args);
 
        return true;
 }
 
 static bool
-_equalAggref(Aggref *a, Aggref *b)
+_equalOpExpr(OpExpr *a, OpExpr *b)
 {
-       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 */
+       COMPARE_SCALAR_FIELD(opno);
+
+       /*
+        * Special-case opfuncid: it is allowable for it to differ if one node
+        * contains zero and the other doesn't.  This just means that the one node
+        * isn't as far along in the parse/plan pipeline and hasn't had the
+        * opfuncid cache filled yet.
+        */
+       if (a->opfuncid != b->opfuncid &&
+               a->opfuncid != 0 &&
+               b->opfuncid != 0)
+               return false;
+
+       COMPARE_SCALAR_FIELD(opresulttype);
+       COMPARE_SCALAR_FIELD(opretset);
+       COMPARE_NODE_FIELD(args);
+
+       return true;
+}
+
+static bool
+_equalDistinctExpr(DistinctExpr *a, DistinctExpr *b)
+{
+       COMPARE_SCALAR_FIELD(opno);
+
+       /*
+        * Special-case opfuncid: it is allowable for it to differ if one node
+        * contains zero and the other doesn't.  This just means that the one node
+        * isn't as far along in the parse/plan pipeline and hasn't had the
+        * opfuncid cache filled yet.
+        */
+       if (a->opfuncid != b->opfuncid &&
+               a->opfuncid != 0 &&
+               b->opfuncid != 0)
+               return false;
+
+       COMPARE_SCALAR_FIELD(opresulttype);
+       COMPARE_SCALAR_FIELD(opretset);
+       COMPARE_NODE_FIELD(args);
+
+       return true;
+}
+
+static bool
+_equalScalarArrayOpExpr(ScalarArrayOpExpr *a, ScalarArrayOpExpr *b)
+{
+       COMPARE_SCALAR_FIELD(opno);
+
+       /*
+        * Special-case opfuncid: it is allowable for it to differ if one node
+        * contains zero and the other doesn't.  This just means that the one node
+        * isn't as far along in the parse/plan pipeline and hasn't had the
+        * opfuncid cache filled yet.
+        */
+       if (a->opfuncid != b->opfuncid &&
+               a->opfuncid != 0 &&
+               b->opfuncid != 0)
+               return false;
+
+       COMPARE_SCALAR_FIELD(useOr);
+       COMPARE_NODE_FIELD(args);
+
+       return true;
+}
+
+static bool
+_equalBoolExpr(BoolExpr *a, BoolExpr *b)
+{
+       COMPARE_SCALAR_FIELD(boolop);
+       COMPARE_NODE_FIELD(args);
 
        return true;
 }
@@ -262,14 +294,30 @@ static bool
 _equalSubLink(SubLink *a, SubLink *b)
 {
        COMPARE_SCALAR_FIELD(subLinkType);
-       COMPARE_SCALAR_FIELD(useor);
-       COMPARE_NODE_FIELD(lefthand);
-       COMPARE_NODE_FIELD(oper);
+       COMPARE_NODE_FIELD(testexpr);
+       COMPARE_NODE_FIELD(operName);
        COMPARE_NODE_FIELD(subselect);
 
        return true;
 }
 
+static bool
+_equalSubPlan(SubPlan *a, SubPlan *b)
+{
+       COMPARE_SCALAR_FIELD(subLinkType);
+       COMPARE_NODE_FIELD(testexpr);
+       COMPARE_NODE_FIELD(paramIds);
+       COMPARE_SCALAR_FIELD(plan_id);
+       COMPARE_SCALAR_FIELD(firstColType);
+       COMPARE_SCALAR_FIELD(useHashTable);
+       COMPARE_SCALAR_FIELD(unknownEqFalse);
+       COMPARE_NODE_FIELD(setParam);
+       COMPARE_NODE_FIELD(parParam);
+       COMPARE_NODE_FIELD(args);
+
+       return true;
+}
+
 static bool
 _equalFieldSelect(FieldSelect *a, FieldSelect *b)
 {
@@ -281,15 +329,27 @@ _equalFieldSelect(FieldSelect *a, FieldSelect *b)
        return true;
 }
 
+static bool
+_equalFieldStore(FieldStore *a, FieldStore *b)
+{
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_NODE_FIELD(newvals);
+       COMPARE_NODE_FIELD(fieldnums);
+       COMPARE_SCALAR_FIELD(resulttype);
+
+       return true;
+}
+
 static bool
 _equalRelabelType(RelabelType *a, RelabelType *b)
 {
        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.
+        * Special-case COERCE_DONTCARE, so that planner can build coercion nodes
+        * that are equal() to both explicit and implicit coercions.
         */
        if (a->relabelformat != b->relabelformat &&
                a->relabelformat != COERCE_DONTCARE &&
@@ -300,211 +360,326 @@ _equalRelabelType(RelabelType *a, RelabelType *b)
 }
 
 static bool
-_equalRangeTblRef(RangeTblRef *a, RangeTblRef *b)
+_equalCoerceViaIO(CoerceViaIO *a, CoerceViaIO *b)
 {
-       COMPARE_SCALAR_FIELD(rtindex);
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_SCALAR_FIELD(resulttype);
+
+       /*
+        * Special-case COERCE_DONTCARE, so that planner can build coercion nodes
+        * that are equal() to both explicit and implicit coercions.
+        */
+       if (a->coerceformat != b->coerceformat &&
+               a->coerceformat != COERCE_DONTCARE &&
+               b->coerceformat != COERCE_DONTCARE)
+               return false;
 
        return true;
 }
 
 static bool
-_equalJoinExpr(JoinExpr *a, JoinExpr *b)
+_equalArrayCoerceExpr(ArrayCoerceExpr *a, ArrayCoerceExpr *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);
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_SCALAR_FIELD(elemfuncid);
+       COMPARE_SCALAR_FIELD(resulttype);
+       COMPARE_SCALAR_FIELD(resulttypmod);
+       COMPARE_SCALAR_FIELD(isExplicit);
+
+       /*
+        * Special-case COERCE_DONTCARE, so that planner can build coercion nodes
+        * that are equal() to both explicit and implicit coercions.
+        */
+       if (a->coerceformat != b->coerceformat &&
+               a->coerceformat != COERCE_DONTCARE &&
+               b->coerceformat != COERCE_DONTCARE)
+               return false;
 
        return true;
 }
 
 static bool
-_equalFromExpr(FromExpr *a, FromExpr *b)
+_equalConvertRowtypeExpr(ConvertRowtypeExpr *a, ConvertRowtypeExpr *b)
 {
-       COMPARE_NODE_FIELD(fromlist);
-       COMPARE_NODE_FIELD(quals);
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_SCALAR_FIELD(resulttype);
+
+       /*
+        * Special-case COERCE_DONTCARE, so that planner can build coercion nodes
+        * that are equal() to both explicit and implicit coercions.
+        */
+       if (a->convertformat != b->convertformat &&
+               a->convertformat != COERCE_DONTCARE &&
+               b->convertformat != COERCE_DONTCARE)
+               return false;
 
        return true;
 }
 
 static bool
-_equalArrayRef(ArrayRef *a, ArrayRef *b)
+_equalCaseExpr(CaseExpr *a, CaseExpr *b)
 {
-       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);
+       COMPARE_SCALAR_FIELD(casetype);
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_NODE_FIELD(args);
+       COMPARE_NODE_FIELD(defresult);
 
        return true;
 }
 
+static bool
+_equalCaseWhen(CaseWhen *a, CaseWhen *b)
+{
+       COMPARE_NODE_FIELD(expr);
+       COMPARE_NODE_FIELD(result);
 
-/*
- * Stuff from plannodes.h
- */
+       return true;
+}
 
 static bool
-_equalSubPlan(SubPlan *a, SubPlan *b)
+_equalCaseTestExpr(CaseTestExpr *a, CaseTestExpr *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);
+       COMPARE_SCALAR_FIELD(typeId);
+       COMPARE_SCALAR_FIELD(typeMod);
 
        return true;
 }
 
+static bool
+_equalArrayExpr(ArrayExpr *a, ArrayExpr *b)
+{
+       COMPARE_SCALAR_FIELD(array_typeid);
+       COMPARE_SCALAR_FIELD(element_typeid);
+       COMPARE_NODE_FIELD(elements);
+       COMPARE_SCALAR_FIELD(multidims);
 
-/*
- * Stuff from relation.h
- */
+       return true;
+}
 
 static bool
-_equalRelOptInfo(RelOptInfo *a, RelOptInfo *b)
+_equalRowExpr(RowExpr *a, RowExpr *b)
 {
+       COMPARE_NODE_FIELD(args);
+       COMPARE_SCALAR_FIELD(row_typeid);
+
        /*
-        * We treat RelOptInfos as equal if they refer to the same base rels
-        * joined in the same order.  Is this appropriate/sufficient?
+        * Special-case COERCE_DONTCARE, so that planner can build coercion nodes
+        * that are equal() to both explicit and implicit coercions.
         */
-       COMPARE_INTLIST_FIELD(relids);
+       if (a->row_format != b->row_format &&
+               a->row_format != COERCE_DONTCARE &&
+               b->row_format != COERCE_DONTCARE)
+               return false;
 
        return true;
 }
 
 static bool
-_equalIndexOptInfo(IndexOptInfo *a, IndexOptInfo *b)
+_equalRowCompareExpr(RowCompareExpr *a, RowCompareExpr *b)
 {
-       /*
-        * We treat IndexOptInfos as equal if they refer to the same index. Is
-        * this sufficient?
-        */
-       COMPARE_SCALAR_FIELD(indexoid);
+       COMPARE_SCALAR_FIELD(rctype);
+       COMPARE_NODE_FIELD(opnos);
+       COMPARE_NODE_FIELD(opfamilies);
+       COMPARE_NODE_FIELD(largs);
+       COMPARE_NODE_FIELD(rargs);
+
+       return true;
+}
+
+static bool
+_equalCoalesceExpr(CoalesceExpr *a, CoalesceExpr *b)
+{
+       COMPARE_SCALAR_FIELD(coalescetype);
+       COMPARE_NODE_FIELD(args);
+
+       return true;
+}
+
+static bool
+_equalMinMaxExpr(MinMaxExpr *a, MinMaxExpr *b)
+{
+       COMPARE_SCALAR_FIELD(minmaxtype);
+       COMPARE_SCALAR_FIELD(op);
+       COMPARE_NODE_FIELD(args);
+
+       return true;
+}
+
+static bool
+_equalXmlExpr(XmlExpr *a, XmlExpr *b)
+{
+       COMPARE_SCALAR_FIELD(op);
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(named_args);
+       COMPARE_NODE_FIELD(arg_names);
+       COMPARE_NODE_FIELD(args);
+       COMPARE_SCALAR_FIELD(xmloption);
+       COMPARE_SCALAR_FIELD(type);
+       COMPARE_SCALAR_FIELD(typmod);
 
        return true;
 }
 
 static bool
-_equalPath(Path *a, Path *b)
+_equalNullIfExpr(NullIfExpr *a, NullIfExpr *b)
 {
-       /* This is safe only because _equalRelOptInfo is incomplete... */
-       COMPARE_NODE_FIELD(parent);
+       COMPARE_SCALAR_FIELD(opno);
+
        /*
-        * do not check path costs, since they may not be set yet, and being
-        * float values there are roundoff error issues anyway...
+        * Special-case opfuncid: it is allowable for it to differ if one node
+        * contains zero and the other doesn't.  This just means that the one node
+        * isn't as far along in the parse/plan pipeline and hasn't had the
+        * opfuncid cache filled yet.
         */
-       COMPARE_SCALAR_FIELD(pathtype);
-       COMPARE_NODE_FIELD(pathkeys);
+       if (a->opfuncid != b->opfuncid &&
+               a->opfuncid != 0 &&
+               b->opfuncid != 0)
+               return false;
+
+       COMPARE_SCALAR_FIELD(opresulttype);
+       COMPARE_SCALAR_FIELD(opretset);
+       COMPARE_NODE_FIELD(args);
 
        return true;
 }
 
 static bool
-_equalIndexPath(IndexPath *a, IndexPath *b)
+_equalNullTest(NullTest *a, NullTest *b)
 {
-       if (!_equalPath((Path *) a, (Path *) b))
-               return false;
-       COMPARE_NODE_FIELD(indexinfo);
-       COMPARE_NODE_FIELD(indexqual);
-       COMPARE_SCALAR_FIELD(indexscandir);
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_SCALAR_FIELD(nulltesttype);
+
+       return true;
+}
+
+static bool
+_equalBooleanTest(BooleanTest *a, BooleanTest *b)
+{
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_SCALAR_FIELD(booltesttype);
+
+       return true;
+}
+
+static bool
+_equalCoerceToDomain(CoerceToDomain *a, CoerceToDomain *b)
+{
+       COMPARE_NODE_FIELD(arg);
+       COMPARE_SCALAR_FIELD(resulttype);
+       COMPARE_SCALAR_FIELD(resulttypmod);
 
        /*
-        * Skip 'rows' because of possibility of floating-point roundoff
-        * error. It should be derivable from the other fields anyway.
+        * Special-case COERCE_DONTCARE, so that planner can build coercion nodes
+        * that are equal() to both explicit and implicit coercions.
         */
+       if (a->coercionformat != b->coercionformat &&
+               a->coercionformat != COERCE_DONTCARE &&
+               b->coercionformat != COERCE_DONTCARE)
+               return false;
+
        return true;
 }
 
 static bool
-_equalTidPath(TidPath *a, TidPath *b)
+_equalCoerceToDomainValue(CoerceToDomainValue *a, CoerceToDomainValue *b)
 {
-       if (!_equalPath((Path *) a, (Path *) b))
-               return false;
-       COMPARE_NODE_FIELD(tideval);
-       COMPARE_INTLIST_FIELD(unjoined_relids);
+       COMPARE_SCALAR_FIELD(typeId);
+       COMPARE_SCALAR_FIELD(typeMod);
 
        return true;
 }
 
 static bool
-_equalAppendPath(AppendPath *a, AppendPath *b)
+_equalSetToDefault(SetToDefault *a, SetToDefault *b)
 {
-       if (!_equalPath((Path *) a, (Path *) b))
-               return false;
-       COMPARE_NODE_FIELD(subpaths);
+       COMPARE_SCALAR_FIELD(typeId);
+       COMPARE_SCALAR_FIELD(typeMod);
 
        return true;
 }
 
 static bool
-_equalResultPath(ResultPath *a, ResultPath *b)
+_equalCurrentOfExpr(CurrentOfExpr *a, CurrentOfExpr *b)
 {
-       if (!_equalPath((Path *) a, (Path *) b))
-               return false;
-       COMPARE_NODE_FIELD(subpath);
-       COMPARE_NODE_FIELD(constantqual);
+       COMPARE_SCALAR_FIELD(cvarno);
+       COMPARE_STRING_FIELD(cursor_name);
 
        return true;
 }
 
 static bool
-_equalJoinPath(JoinPath *a, JoinPath *b)
+_equalTargetEntry(TargetEntry *a, TargetEntry *b)
 {
-       if (!_equalPath((Path *) a, (Path *) b))
-               return false;
-       COMPARE_SCALAR_FIELD(jointype);
-       COMPARE_NODE_FIELD(outerjoinpath);
-       COMPARE_NODE_FIELD(innerjoinpath);
-       COMPARE_NODE_FIELD(joinrestrictinfo);
+       COMPARE_NODE_FIELD(expr);
+       COMPARE_SCALAR_FIELD(resno);
+       COMPARE_STRING_FIELD(resname);
+       COMPARE_SCALAR_FIELD(ressortgroupref);
+       COMPARE_SCALAR_FIELD(resorigtbl);
+       COMPARE_SCALAR_FIELD(resorigcol);
+       COMPARE_SCALAR_FIELD(resjunk);
 
        return true;
 }
 
 static bool
-_equalNestPath(NestPath *a, NestPath *b)
+_equalRangeTblRef(RangeTblRef *a, RangeTblRef *b)
 {
-       if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
-               return false;
+       COMPARE_SCALAR_FIELD(rtindex);
 
        return true;
 }
 
 static bool
-_equalMergePath(MergePath *a, MergePath *b)
+_equalJoinExpr(JoinExpr *a, JoinExpr *b)
 {
-       if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
-               return false;
-       COMPARE_NODE_FIELD(path_mergeclauses);
-       COMPARE_NODE_FIELD(outersortkeys);
-       COMPARE_NODE_FIELD(innersortkeys);
+       COMPARE_SCALAR_FIELD(jointype);
+       COMPARE_SCALAR_FIELD(isNatural);
+       COMPARE_NODE_FIELD(larg);
+       COMPARE_NODE_FIELD(rarg);
+       COMPARE_NODE_FIELD(using);
+       COMPARE_NODE_FIELD(quals);
+       COMPARE_NODE_FIELD(alias);
+       COMPARE_SCALAR_FIELD(rtindex);
 
        return true;
 }
 
 static bool
-_equalHashPath(HashPath *a, HashPath *b)
+_equalFromExpr(FromExpr *a, FromExpr *b)
 {
-       if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
-               return false;
-       COMPARE_NODE_FIELD(path_hashclauses);
+       COMPARE_NODE_FIELD(fromlist);
+       COMPARE_NODE_FIELD(quals);
 
        return true;
 }
 
+
+/*
+ * Stuff from relation.h
+ */
+
 static bool
-_equalPathKeyItem(PathKeyItem *a, PathKeyItem *b)
+_equalPathKey(PathKey *a, PathKey *b)
 {
-       COMPARE_NODE_FIELD(key);
-       COMPARE_SCALAR_FIELD(sortop);
+       /*
+        * This is normally used on non-canonicalized PathKeys, so must chase
+        * up to the topmost merged EquivalenceClass and see if those are the
+        * same (by pointer equality).
+        */
+       EquivalenceClass *a_eclass;
+       EquivalenceClass *b_eclass;
+
+       a_eclass = a->pk_eclass;
+       while (a_eclass->ec_merged)
+               a_eclass = a_eclass->ec_merged;
+       b_eclass = b->pk_eclass;
+       while (b_eclass->ec_merged)
+               b_eclass = b_eclass->ec_merged;
+       if (a_eclass != b_eclass)
+               return false;
+       COMPARE_SCALAR_FIELD(pk_opfamily);
+       COMPARE_SCALAR_FIELD(pk_strategy);
+       COMPARE_SCALAR_FIELD(pk_nulls_first);
 
        return true;
 }
@@ -513,36 +688,51 @@ static bool
 _equalRestrictInfo(RestrictInfo *a, RestrictInfo *b)
 {
        COMPARE_NODE_FIELD(clause);
-       COMPARE_SCALAR_FIELD(ispusheddown);
+       COMPARE_SCALAR_FIELD(is_pushed_down);
+       COMPARE_SCALAR_FIELD(outerjoin_delayed);
+       COMPARE_BITMAPSET_FIELD(required_relids);
+
        /*
-        * 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 ...
+        * We ignore all the remaining fields, since they may not be set yet, and
+        * should be derivable from the clause anyway.
         */
-       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)
+_equalOuterJoinInfo(OuterJoinInfo *a, OuterJoinInfo *b)
+{
+       COMPARE_BITMAPSET_FIELD(min_lefthand);
+       COMPARE_BITMAPSET_FIELD(min_righthand);
+       COMPARE_SCALAR_FIELD(is_full_join);
+       COMPARE_SCALAR_FIELD(lhs_strict);
+       COMPARE_SCALAR_FIELD(delay_upper_joins);
+
+       return true;
+}
+
+static bool
+_equalInClauseInfo(InClauseInfo *a, InClauseInfo *b)
 {
-       COMPARE_INTLIST_FIELD(unjoined_relids);
-       COMPARE_NODE_FIELD(jinfo_restrictinfo);
+       COMPARE_BITMAPSET_FIELD(lefthand);
+       COMPARE_BITMAPSET_FIELD(righthand);
+       COMPARE_NODE_FIELD(sub_targetlist);
+       COMPARE_NODE_FIELD(in_operators);
 
        return true;
 }
 
 static bool
-_equalInnerIndexscanInfo(InnerIndexscanInfo *a, InnerIndexscanInfo *b)
+_equalAppendRelInfo(AppendRelInfo *a, AppendRelInfo *b)
 {
-       COMPARE_INTLIST_FIELD(other_relids);
-       COMPARE_SCALAR_FIELD(isouterjoin);
-       COMPARE_NODE_FIELD(best_innerpath);
+       COMPARE_SCALAR_FIELD(parent_relid);
+       COMPARE_SCALAR_FIELD(child_relid);
+       COMPARE_SCALAR_FIELD(parent_reltype);
+       COMPARE_SCALAR_FIELD(child_reltype);
+       COMPARE_NODE_FIELD(col_mappings);
+       COMPARE_NODE_FIELD(translated_vars);
+       COMPARE_SCALAR_FIELD(parent_reloid);
 
        return true;
 }
@@ -557,32 +747,25 @@ _equalQuery(Query *a, Query *b)
 {
        COMPARE_SCALAR_FIELD(commandType);
        COMPARE_SCALAR_FIELD(querySource);
+       COMPARE_SCALAR_FIELD(canSetTag);
        COMPARE_NODE_FIELD(utilityStmt);
        COMPARE_SCALAR_FIELD(resultRelation);
-       COMPARE_NODE_FIELD(into);
-       COMPARE_SCALAR_FIELD(isPortal);
-       COMPARE_SCALAR_FIELD(isBinary);
+       COMPARE_NODE_FIELD(intoClause);
        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(returningList);
        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(rowMarks);
        COMPARE_NODE_FIELD(setOperations);
-       COMPARE_INTLIST_FIELD(resultRelations);
 
-       /*
-        * We do not check the internal-to-the-planner fields: base_rel_list,
-        * other_rel_list, join_rel_list, equi_key_list, query_pathkeys,
-        * hasJoinRTEs.  They might not be set yet, and in any case they should
-        * be derivable from the other fields.
-        */
        return true;
 }
 
@@ -591,8 +774,8 @@ _equalInsertStmt(InsertStmt *a, InsertStmt *b)
 {
        COMPARE_NODE_FIELD(relation);
        COMPARE_NODE_FIELD(cols);
-       COMPARE_NODE_FIELD(targetList);
        COMPARE_NODE_FIELD(selectStmt);
+       COMPARE_NODE_FIELD(returningList);
 
        return true;
 }
@@ -601,7 +784,9 @@ static bool
 _equalDeleteStmt(DeleteStmt *a, DeleteStmt *b)
 {
        COMPARE_NODE_FIELD(relation);
+       COMPARE_NODE_FIELD(usingClause);
        COMPARE_NODE_FIELD(whereClause);
+       COMPARE_NODE_FIELD(returningList);
 
        return true;
 }
@@ -613,6 +798,7 @@ _equalUpdateStmt(UpdateStmt *a, UpdateStmt *b)
        COMPARE_NODE_FIELD(targetList);
        COMPARE_NODE_FIELD(whereClause);
        COMPARE_NODE_FIELD(fromClause);
+       COMPARE_NODE_FIELD(returningList);
 
        return true;
 }
@@ -621,19 +807,17 @@ static bool
 _equalSelectStmt(SelectStmt *a, SelectStmt *b)
 {
        COMPARE_NODE_FIELD(distinctClause);
-       COMPARE_NODE_FIELD(into);
-       COMPARE_NODE_FIELD(intoColNames);
+       COMPARE_NODE_FIELD(intoClause);
        COMPARE_NODE_FIELD(targetList);
        COMPARE_NODE_FIELD(fromClause);
        COMPARE_NODE_FIELD(whereClause);
        COMPARE_NODE_FIELD(groupClause);
        COMPARE_NODE_FIELD(havingClause);
+       COMPARE_NODE_FIELD(valuesLists);
        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_NODE_FIELD(lockingClause);
        COMPARE_SCALAR_FIELD(op);
        COMPARE_SCALAR_FIELD(all);
        COMPARE_NODE_FIELD(larg);
@@ -649,7 +833,8 @@ _equalSetOperationStmt(SetOperationStmt *a, SetOperationStmt *b)
        COMPARE_SCALAR_FIELD(all);
        COMPARE_NODE_FIELD(larg);
        COMPARE_NODE_FIELD(rarg);
-       COMPARE_INTLIST_FIELD(colTypes);
+       COMPARE_NODE_FIELD(colTypes);
+       COMPARE_NODE_FIELD(colTypmods);
 
        return true;
 }
@@ -657,8 +842,30 @@ _equalSetOperationStmt(SetOperationStmt *a, SetOperationStmt *b)
 static bool
 _equalAlterTableStmt(AlterTableStmt *a, AlterTableStmt *b)
 {
-       COMPARE_SCALAR_FIELD(subtype);
        COMPARE_NODE_FIELD(relation);
+       COMPARE_NODE_FIELD(cmds);
+       COMPARE_SCALAR_FIELD(relkind);
+
+       return true;
+}
+
+static bool
+_equalAlterTableCmd(AlterTableCmd *a, AlterTableCmd *b)
+{
+       COMPARE_SCALAR_FIELD(subtype);
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(def);
+       COMPARE_NODE_FIELD(transform);
+       COMPARE_SCALAR_FIELD(behavior);
+
+       return true;
+}
+
+static bool
+_equalAlterDomainStmt(AlterDomainStmt *a, AlterDomainStmt *b)
+{
+       COMPARE_SCALAR_FIELD(subtype);
+       COMPARE_NODE_FIELD(typename);
        COMPARE_STRING_FIELD(name);
        COMPARE_NODE_FIELD(def);
        COMPARE_SCALAR_FIELD(behavior);
@@ -672,8 +879,10 @@ _equalGrantStmt(GrantStmt *a, GrantStmt *b)
        COMPARE_SCALAR_FIELD(is_grant);
        COMPARE_SCALAR_FIELD(objtype);
        COMPARE_NODE_FIELD(objects);
-       COMPARE_INTLIST_FIELD(privileges);
+       COMPARE_NODE_FIELD(privileges);
        COMPARE_NODE_FIELD(grantees);
+       COMPARE_SCALAR_FIELD(grant_option);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
@@ -681,8 +890,7 @@ _equalGrantStmt(GrantStmt *a, GrantStmt *b)
 static bool
 _equalPrivGrantee(PrivGrantee *a, PrivGrantee *b)
 {
-       COMPARE_STRING_FIELD(username);
-       COMPARE_STRING_FIELD(groupname);
+       COMPARE_STRING_FIELD(rolname);
 
        return true;
 }
@@ -697,8 +905,25 @@ _equalFuncWithArgs(FuncWithArgs *a, FuncWithArgs *b)
 }
 
 static bool
-_equalInsertDefault(InsertDefault *a, InsertDefault *b)
+_equalGrantRoleStmt(GrantRoleStmt *a, GrantRoleStmt *b)
 {
+       COMPARE_NODE_FIELD(granted_roles);
+       COMPARE_NODE_FIELD(grantee_roles);
+       COMPARE_SCALAR_FIELD(is_grant);
+       COMPARE_SCALAR_FIELD(admin_opt);
+       COMPARE_STRING_FIELD(grantor);
+       COMPARE_SCALAR_FIELD(behavior);
+
+       return true;
+}
+
+static bool
+_equalDeclareCursorStmt(DeclareCursorStmt *a, DeclareCursorStmt *b)
+{
+       COMPARE_STRING_FIELD(portalname);
+       COMPARE_SCALAR_FIELD(options);
+       COMPARE_NODE_FIELD(query);
+
        return true;
 }
 
@@ -723,6 +948,7 @@ static bool
 _equalCopyStmt(CopyStmt *a, CopyStmt *b)
 {
        COMPARE_NODE_FIELD(relation);
+       COMPARE_NODE_FIELD(query);
        COMPARE_NODE_FIELD(attlist);
        COMPARE_SCALAR_FIELD(is_from);
        COMPARE_STRING_FIELD(filename);
@@ -738,8 +964,18 @@ _equalCreateStmt(CreateStmt *a, CreateStmt *b)
        COMPARE_NODE_FIELD(tableElts);
        COMPARE_NODE_FIELD(inhRelations);
        COMPARE_NODE_FIELD(constraints);
-       COMPARE_SCALAR_FIELD(hasoids);
+       COMPARE_NODE_FIELD(options);
        COMPARE_SCALAR_FIELD(oncommit);
+       COMPARE_STRING_FIELD(tablespacename);
+
+       return true;
+}
+
+static bool
+_equalInhRelation(InhRelation *a, InhRelation *b)
+{
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_NODE_FIELD(options);
 
        return true;
 }
@@ -747,8 +983,10 @@ _equalCreateStmt(CreateStmt *a, CreateStmt *b)
 static bool
 _equalDefineStmt(DefineStmt *a, DefineStmt *b)
 {
-       COMPARE_SCALAR_FIELD(defType);
+       COMPARE_SCALAR_FIELD(kind);
+       COMPARE_SCALAR_FIELD(oldstyle);
        COMPARE_NODE_FIELD(defnames);
+       COMPARE_NODE_FIELD(args);
        COMPARE_NODE_FIELD(definition);
 
        return true;
@@ -760,6 +998,7 @@ _equalDropStmt(DropStmt *a, DropStmt *b)
        COMPARE_NODE_FIELD(objects);
        COMPARE_SCALAR_FIELD(removeType);
        COMPARE_SCALAR_FIELD(behavior);
+       COMPARE_SCALAR_FIELD(missing_ok);
 
        return true;
 }
@@ -767,7 +1006,8 @@ _equalDropStmt(DropStmt *a, DropStmt *b)
 static bool
 _equalTruncateStmt(TruncateStmt *a, TruncateStmt *b)
 {
-       COMPARE_NODE_FIELD(relation);
+       COMPARE_NODE_FIELD(relations);
+       COMPARE_SCALAR_FIELD(behavior);
 
        return true;
 }
@@ -800,12 +1040,14 @@ _equalIndexStmt(IndexStmt *a, IndexStmt *b)
        COMPARE_STRING_FIELD(idxname);
        COMPARE_NODE_FIELD(relation);
        COMPARE_STRING_FIELD(accessMethod);
+       COMPARE_STRING_FIELD(tableSpace);
        COMPARE_NODE_FIELD(indexParams);
+       COMPARE_NODE_FIELD(options);
        COMPARE_NODE_FIELD(whereClause);
-       COMPARE_NODE_FIELD(rangetable);
        COMPARE_SCALAR_FIELD(unique);
        COMPARE_SCALAR_FIELD(primary);
        COMPARE_SCALAR_FIELD(isconstraint);
+       COMPARE_SCALAR_FIELD(concurrent);
 
        return true;
 }
@@ -815,7 +1057,7 @@ _equalCreateFunctionStmt(CreateFunctionStmt *a, CreateFunctionStmt *b)
 {
        COMPARE_SCALAR_FIELD(replace);
        COMPARE_NODE_FIELD(funcname);
-       COMPARE_NODE_FIELD(argTypes);
+       COMPARE_NODE_FIELD(parameters);
        COMPARE_NODE_FIELD(returnType);
        COMPARE_NODE_FIELD(options);
        COMPARE_NODE_FIELD(withClause);
@@ -824,31 +1066,32 @@ _equalCreateFunctionStmt(CreateFunctionStmt *a, CreateFunctionStmt *b)
 }
 
 static bool
-_equalRemoveAggrStmt(RemoveAggrStmt *a, RemoveAggrStmt *b)
+_equalFunctionParameter(FunctionParameter *a, FunctionParameter *b)
 {
-       COMPARE_NODE_FIELD(aggname);
-       COMPARE_NODE_FIELD(aggtype);
-       COMPARE_SCALAR_FIELD(behavior);
+       COMPARE_STRING_FIELD(name);
+       COMPARE_NODE_FIELD(argType);
+       COMPARE_SCALAR_FIELD(mode);
 
        return true;
 }
 
 static bool
-_equalRemoveFuncStmt(RemoveFuncStmt *a, RemoveFuncStmt *b)
+_equalAlterFunctionStmt(AlterFunctionStmt *a, AlterFunctionStmt *b)
 {
-       COMPARE_NODE_FIELD(funcname);
-       COMPARE_NODE_FIELD(args);
-       COMPARE_SCALAR_FIELD(behavior);
+       COMPARE_NODE_FIELD(func);
+       COMPARE_NODE_FIELD(actions);
 
        return true;
 }
 
 static bool
-_equalRemoveOperStmt(RemoveOperStmt *a, RemoveOperStmt *b)
+_equalRemoveFuncStmt(RemoveFuncStmt *a, RemoveFuncStmt *b)
 {
-       COMPARE_NODE_FIELD(opname);
+       COMPARE_SCALAR_FIELD(kind);
+       COMPARE_NODE_FIELD(name);
        COMPARE_NODE_FIELD(args);
        COMPARE_SCALAR_FIELD(behavior);
+       COMPARE_SCALAR_FIELD(missing_ok);
 
        return true;
 }
@@ -859,6 +1102,18 @@ _equalRemoveOpClassStmt(RemoveOpClassStmt *a, RemoveOpClassStmt *b)
        COMPARE_NODE_FIELD(opclassname);
        COMPARE_STRING_FIELD(amname);
        COMPARE_SCALAR_FIELD(behavior);
+       COMPARE_SCALAR_FIELD(missing_ok);
+
+       return true;
+}
+
+static bool
+_equalRemoveOpFamilyStmt(RemoveOpFamilyStmt *a, RemoveOpFamilyStmt *b)
+{
+       COMPARE_NODE_FIELD(opfamilyname);
+       COMPARE_STRING_FIELD(amname);
+       COMPARE_SCALAR_FIELD(behavior);
+       COMPARE_SCALAR_FIELD(missing_ok);
 
        return true;
 }
@@ -866,10 +1121,38 @@ _equalRemoveOpClassStmt(RemoveOpClassStmt *a, RemoveOpClassStmt *b)
 static bool
 _equalRenameStmt(RenameStmt *a, RenameStmt *b)
 {
+       COMPARE_SCALAR_FIELD(renameType);
        COMPARE_NODE_FIELD(relation);
-       COMPARE_STRING_FIELD(oldname);
+       COMPARE_NODE_FIELD(object);
+       COMPARE_NODE_FIELD(objarg);
+       COMPARE_STRING_FIELD(subname);
        COMPARE_STRING_FIELD(newname);
-       COMPARE_SCALAR_FIELD(renameType);
+
+       return true;
+}
+
+static bool
+_equalAlterObjectSchemaStmt(AlterObjectSchemaStmt *a, AlterObjectSchemaStmt *b)
+{
+       COMPARE_SCALAR_FIELD(objectType);
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_NODE_FIELD(object);
+       COMPARE_NODE_FIELD(objarg);
+       COMPARE_STRING_FIELD(addname);
+       COMPARE_STRING_FIELD(newschema);
+
+       return true;
+}
+
+static bool
+_equalAlterOwnerStmt(AlterOwnerStmt *a, AlterOwnerStmt *b)
+{
+       COMPARE_SCALAR_FIELD(objectType);
+       COMPARE_NODE_FIELD(relation);
+       COMPARE_NODE_FIELD(object);
+       COMPARE_NODE_FIELD(objarg);
+       COMPARE_STRING_FIELD(addname);
+       COMPARE_STRING_FIELD(newowner);
 
        return true;
 }
@@ -915,8 +1198,9 @@ _equalUnlistenStmt(UnlistenStmt *a, UnlistenStmt *b)
 static bool
 _equalTransactionStmt(TransactionStmt *a, TransactionStmt *b)
 {
-       COMPARE_SCALAR_FIELD(command);
+       COMPARE_SCALAR_FIELD(kind);
        COMPARE_NODE_FIELD(options);
+       COMPARE_STRING_FIELD(gid);
 
        return true;
 }
@@ -930,6 +1214,15 @@ _equalCompositeTypeStmt(CompositeTypeStmt *a, CompositeTypeStmt *b)
        return true;
 }
 
+static bool
+_equalCreateEnumStmt(CreateEnumStmt *a, CreateEnumStmt *b)
+{
+       COMPARE_NODE_FIELD(typename);
+       COMPARE_NODE_FIELD(vals);
+
+       return true;
+}
+
 static bool
 _equalViewStmt(ViewStmt *a, ViewStmt *b)
 {
@@ -963,6 +1256,7 @@ static bool
 _equalCreateOpClassStmt(CreateOpClassStmt *a, CreateOpClassStmt *b)
 {
        COMPARE_NODE_FIELD(opclassname);
+       COMPARE_NODE_FIELD(opfamilyname);
        COMPARE_STRING_FIELD(amname);
        COMPARE_NODE_FIELD(datatype);
        COMPARE_NODE_FIELD(items);
@@ -979,11 +1273,32 @@ _equalCreateOpClassItem(CreateOpClassItem *a, CreateOpClassItem *b)
        COMPARE_NODE_FIELD(args);
        COMPARE_SCALAR_FIELD(number);
        COMPARE_SCALAR_FIELD(recheck);
+       COMPARE_NODE_FIELD(class_args);
        COMPARE_NODE_FIELD(storedtype);
 
        return true;
 }
 
+static bool
+_equalCreateOpFamilyStmt(CreateOpFamilyStmt *a, CreateOpFamilyStmt *b)
+{
+       COMPARE_NODE_FIELD(opfamilyname);
+       COMPARE_STRING_FIELD(amname);
+
+       return true;
+}
+
+static bool
+_equalAlterOpFamilyStmt(AlterOpFamilyStmt *a, AlterOpFamilyStmt *b)
+{
+       COMPARE_NODE_FIELD(opfamilyname);
+       COMPARE_STRING_FIELD(amname);
+       COMPARE_SCALAR_FIELD(isDrop);
+       COMPARE_NODE_FIELD(items);
+
+       return true;
+}
+
 static bool
 _equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b)
 {
@@ -993,6 +1308,15 @@ _equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b)
        return true;
 }
 
+static bool
+_equalAlterDatabaseStmt(AlterDatabaseStmt *a, AlterDatabaseStmt *b)
+{
+       COMPARE_STRING_FIELD(dbname);
+       COMPARE_NODE_FIELD(options);
+
+       return true;
+}
+
 static bool
 _equalAlterDatabaseSetStmt(AlterDatabaseSetStmt *a, AlterDatabaseSetStmt *b)
 {
@@ -1007,6 +1331,7 @@ static bool
 _equalDropdbStmt(DropdbStmt *a, DropdbStmt *b)
 {
        COMPARE_STRING_FIELD(dbname);
+       COMPARE_SCALAR_FIELD(missing_ok);
 
        return true;
 }
@@ -1017,8 +1342,8 @@ _equalVacuumStmt(VacuumStmt *a, VacuumStmt *b)
        COMPARE_SCALAR_FIELD(vacuum);
        COMPARE_SCALAR_FIELD(full);
        COMPARE_SCALAR_FIELD(analyze);
-       COMPARE_SCALAR_FIELD(freeze);
        COMPARE_SCALAR_FIELD(verbose);
+       COMPARE_SCALAR_FIELD(freeze_min_age);
        COMPARE_NODE_FIELD(relation);
        COMPARE_NODE_FIELD(va_cols);
 
@@ -1036,7 +1361,16 @@ _equalExplainStmt(ExplainStmt *a, ExplainStmt *b)
 }
 
 static bool
-_equalCreateSeqStmt(CreateSeqStmt *a, CreateSeqStmt *b)
+_equalCreateSeqStmt(CreateSeqStmt *a, CreateSeqStmt *b)
+{
+       COMPARE_NODE_FIELD(sequence);
+       COMPARE_NODE_FIELD(options);
+
+       return true;
+}
+
+static bool
+_equalAlterSeqStmt(AlterSeqStmt *a, AlterSeqStmt *b)
 {
        COMPARE_NODE_FIELD(sequence);
        COMPARE_NODE_FIELD(options);
@@ -1070,6 +1404,33 @@ _equalVariableResetStmt(VariableResetStmt *a, VariableResetStmt *b)
        return true;
 }
 
+static bool
+_equalDiscardStmt(DiscardStmt *a, DiscardStmt *b)
+{
+       COMPARE_SCALAR_FIELD(target);
+
+       return true;
+}
+
+static bool
+_equalCreateTableSpaceStmt(CreateTableSpaceStmt *a, CreateTableSpaceStmt *b)
+{
+       COMPARE_STRING_FIELD(tablespacename);
+       COMPARE_STRING_FIELD(owner);
+       COMPARE_STRING_FIELD(location);
+
+       return true;
+}
+
+static bool
+_equalDropTableSpaceStmt(DropTableSpaceStmt *a, DropTableSpaceStmt *b)
+{
+       COMPARE_STRING_FIELD(tablespacename);
+       COMPARE_SCALAR_FIELD(missing_ok);
+
+       return true;
+}
+
 static bool
 _equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b)
 {
@@ -1079,7 +1440,7 @@ _equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b)
        COMPARE_NODE_FIELD(args);
        COMPARE_SCALAR_FIELD(before);
        COMPARE_SCALAR_FIELD(row);
-       if (strcmp(a->actions, b->actions) != 0) /* in-line string field */
+       if (strcmp(a->actions, b->actions) != 0)        /* in-line string field */
                return false;
        COMPARE_SCALAR_FIELD(isconstraint);
        COMPARE_SCALAR_FIELD(deferrable);
@@ -1096,6 +1457,7 @@ _equalDropPropertyStmt(DropPropertyStmt *a, DropPropertyStmt *b)
        COMPARE_STRING_FIELD(property);
        COMPARE_SCALAR_FIELD(removeType);
        COMPARE_SCALAR_FIELD(behavior);
+       COMPARE_SCALAR_FIELD(missing_ok);
 
        return true;
 }
@@ -1116,32 +1478,35 @@ _equalDropPLangStmt(DropPLangStmt *a, DropPLangStmt *b)
 {
        COMPARE_STRING_FIELD(plname);
        COMPARE_SCALAR_FIELD(behavior);
+       COMPARE_SCALAR_FIELD(missing_ok);
 
        return true;
 }
 
 static bool
-_equalCreateUserStmt(CreateUserStmt *a, CreateUserStmt *b)
+_equalCreateRoleStmt(CreateRoleStmt *a, CreateRoleStmt *b)
 {
-       COMPARE_STRING_FIELD(user);
+       COMPARE_SCALAR_FIELD(stmt_type);
+       COMPARE_STRING_FIELD(role);
        COMPARE_NODE_FIELD(options);
 
        return true;
 }
 
 static bool
-_equalAlterUserStmt(AlterUserStmt *a, AlterUserStmt *b)
+_equalAlterRoleStmt(AlterRoleStmt *a, AlterRoleStmt *b)
 {
-       COMPARE_STRING_FIELD(user);
+       COMPARE_STRING_FIELD(role);
        COMPARE_NODE_FIELD(options);
+       COMPARE_SCALAR_FIELD(action);
 
        return true;
 }
 
 static bool
-_equalAlterUserSetStmt(AlterUserSetStmt *a, AlterUserSetStmt *b)
+_equalAlterRoleSetStmt(AlterRoleSetStmt *a, AlterRoleSetStmt *b)
 {
-       COMPARE_STRING_FIELD(user);
+       COMPARE_STRING_FIELD(role);
        COMPARE_STRING_FIELD(variable);
        COMPARE_NODE_FIELD(value);
 
@@ -1149,9 +1514,10 @@ _equalAlterUserSetStmt(AlterUserSetStmt *a, AlterUserSetStmt *b)
 }
 
 static bool
-_equalDropUserStmt(DropUserStmt *a, DropUserStmt *b)
+_equalDropRoleStmt(DropRoleStmt *a, DropRoleStmt *b)
 {
-       COMPARE_NODE_FIELD(users);
+       COMPARE_NODE_FIELD(roles);
+       COMPARE_SCALAR_FIELD(missing_ok);
 
        return true;
 }
@@ -1161,6 +1527,7 @@ _equalLockStmt(LockStmt *a, LockStmt *b)
 {
        COMPARE_NODE_FIELD(relations);
        COMPARE_SCALAR_FIELD(mode);
+       COMPARE_SCALAR_FIELD(nowait);
 
        return true;
 }
@@ -1174,41 +1541,14 @@ _equalConstraintsSetStmt(ConstraintsSetStmt *a, ConstraintsSetStmt *b)
        return true;
 }
 
-static bool
-_equalCreateGroupStmt(CreateGroupStmt *a, CreateGroupStmt *b)
-{
-       COMPARE_STRING_FIELD(name);
-       COMPARE_NODE_FIELD(options);
-
-       return true;
-}
-
-static bool
-_equalAlterGroupStmt(AlterGroupStmt *a, AlterGroupStmt *b)
-{
-       COMPARE_STRING_FIELD(name);
-       COMPARE_SCALAR_FIELD(action);
-       COMPARE_NODE_FIELD(listUsers);
-
-       return true;
-}
-
-static bool
-_equalDropGroupStmt(DropGroupStmt *a, DropGroupStmt *b)
-{
-       COMPARE_STRING_FIELD(name);
-
-       return true;
-}
-
 static bool
 _equalReindexStmt(ReindexStmt *a, ReindexStmt *b)
 {
-       COMPARE_SCALAR_FIELD(reindexType);
+       COMPARE_SCALAR_FIELD(kind);
        COMPARE_NODE_FIELD(relation);
        COMPARE_STRING_FIELD(name);
-       COMPARE_SCALAR_FIELD(force);
-       COMPARE_SCALAR_FIELD(all);
+       COMPARE_SCALAR_FIELD(do_system);
+       COMPARE_SCALAR_FIELD(do_user);
 
        return true;
 }
@@ -1252,6 +1592,7 @@ _equalDropCastStmt(DropCastStmt *a, DropCastStmt *b)
        COMPARE_NODE_FIELD(sourcetype);
        COMPARE_NODE_FIELD(targettype);
        COMPARE_SCALAR_FIELD(behavior);
+       COMPARE_SCALAR_FIELD(missing_ok);
 
        return true;
 }
@@ -1261,7 +1602,6 @@ _equalPrepareStmt(PrepareStmt *a, PrepareStmt *b)
 {
        COMPARE_STRING_FIELD(name);
        COMPARE_NODE_FIELD(argtypes);
-       COMPARE_INTLIST_FIELD(argtype_oids);
        COMPARE_NODE_FIELD(query);
 
        return true;
@@ -1285,18 +1625,32 @@ _equalDeallocateStmt(DeallocateStmt *a, DeallocateStmt *b)
        return true;
 }
 
+static bool
+_equalDropOwnedStmt(DropOwnedStmt *a, DropOwnedStmt *b)
+{
+       COMPARE_NODE_FIELD(roles);
+       COMPARE_SCALAR_FIELD(behavior);
+
+       return true;
+}
+
+static bool
+_equalReassignOwnedStmt(ReassignOwnedStmt *a, ReassignOwnedStmt *b)
+{
+       COMPARE_NODE_FIELD(roles);
+       COMPARE_NODE_FIELD(newrole);
 
-/*
- * stuff from parsenodes.h
- */
+       return true;
+}
 
 static bool
 _equalAExpr(A_Expr *a, A_Expr *b)
 {
-       COMPARE_SCALAR_FIELD(oper);
+       COMPARE_SCALAR_FIELD(kind);
        COMPARE_NODE_FIELD(name);
        COMPARE_NODE_FIELD(lexpr);
        COMPARE_NODE_FIELD(rexpr);
+       COMPARE_SCALAR_FIELD(location);
 
        return true;
 }
@@ -1305,7 +1659,7 @@ static bool
 _equalColumnRef(ColumnRef *a, ColumnRef *b)
 {
        COMPARE_NODE_FIELD(fields);
-       COMPARE_NODE_FIELD(indirection);
+       COMPARE_SCALAR_FIELD(location);
 
        return true;
 }
@@ -1314,8 +1668,6 @@ static bool
 _equalParamRef(ParamRef *a, ParamRef *b)
 {
        COMPARE_SCALAR_FIELD(number);
-       COMPARE_NODE_FIELD(fields);
-       COMPARE_NODE_FIELD(indirection);
 
        return true;
 }
@@ -1323,7 +1675,7 @@ _equalParamRef(ParamRef *a, ParamRef *b)
 static bool
 _equalAConst(A_Const *a, A_Const *b)
 {
-       if (!equal(&a->val, &b->val)) /* hack for in-line Value field */
+       if (!equal(&a->val, &b->val))           /* hack for in-line Value field */
                return false;
        COMPARE_NODE_FIELD(typename);
 
@@ -1337,6 +1689,7 @@ _equalFuncCall(FuncCall *a, FuncCall *b)
        COMPARE_NODE_FIELD(args);
        COMPARE_SCALAR_FIELD(agg_star);
        COMPARE_SCALAR_FIELD(agg_distinct);
+       COMPARE_SCALAR_FIELD(location);
 
        return true;
 }
@@ -1351,10 +1704,9 @@ _equalAIndices(A_Indices *a, A_Indices *b)
 }
 
 static bool
-_equalExprFieldSelect(ExprFieldSelect *a, ExprFieldSelect *b)
+_equalA_Indirection(A_Indirection *a, A_Indirection *b)
 {
        COMPARE_NODE_FIELD(arg);
-       COMPARE_NODE_FIELD(fields);
        COMPARE_NODE_FIELD(indirection);
 
        return true;
@@ -1366,6 +1718,7 @@ _equalResTarget(ResTarget *a, ResTarget *b)
        COMPARE_STRING_FIELD(name);
        COMPARE_NODE_FIELD(indirection);
        COMPARE_NODE_FIELD(val);
+       COMPARE_SCALAR_FIELD(location);
 
        return true;
 }
@@ -1378,8 +1731,10 @@ _equalTypeName(TypeName *a, TypeName *b)
        COMPARE_SCALAR_FIELD(timezone);
        COMPARE_SCALAR_FIELD(setof);
        COMPARE_SCALAR_FIELD(pct_type);
-       COMPARE_SCALAR_FIELD(typmod);
+       COMPARE_NODE_FIELD(typmods);
+       COMPARE_SCALAR_FIELD(typemod);
        COMPARE_NODE_FIELD(arrayBounds);
+       COMPARE_SCALAR_FIELD(location);
 
        return true;
 }
@@ -1394,8 +1749,10 @@ _equalTypeCast(TypeCast *a, TypeCast *b)
 }
 
 static bool
-_equalSortGroupBy(SortGroupBy *a, SortGroupBy *b)
+_equalSortBy(SortBy *a, SortBy *b)
 {
+       COMPARE_SCALAR_FIELD(sortby_dir);
+       COMPARE_SCALAR_FIELD(sortby_nulls);
        COMPARE_NODE_FIELD(useOp);
        COMPARE_NODE_FIELD(node);
 
@@ -1425,9 +1782,10 @@ static bool
 _equalIndexElem(IndexElem *a, IndexElem *b)
 {
        COMPARE_STRING_FIELD(name);
-       COMPARE_NODE_FIELD(funcname);
-       COMPARE_NODE_FIELD(args);
+       COMPARE_NODE_FIELD(expr);
        COMPARE_NODE_FIELD(opclass);
+       COMPARE_SCALAR_FIELD(ordering);
+       COMPARE_SCALAR_FIELD(nulls_ordering);
 
        return true;
 }
@@ -1443,7 +1801,6 @@ _equalColumnDef(ColumnDef *a, ColumnDef *b)
        COMPARE_NODE_FIELD(raw_default);
        COMPARE_STRING_FIELD(cooked_default);
        COMPARE_NODE_FIELD(constraints);
-       COMPARE_NODE_FIELD(support);
 
        return true;
 }
@@ -1456,6 +1813,8 @@ _equalConstraint(Constraint *a, Constraint *b)
        COMPARE_NODE_FIELD(raw_expr);
        COMPARE_STRING_FIELD(cooked_expr);
        COMPARE_NODE_FIELD(keys);
+       COMPARE_NODE_FIELD(options);
+       COMPARE_STRING_FIELD(indexspace);
 
        return true;
 }
@@ -1470,11 +1829,11 @@ _equalDefElem(DefElem *a, DefElem *b)
 }
 
 static bool
-_equalTargetEntry(TargetEntry *a, TargetEntry *b)
+_equalLockingClause(LockingClause *a, LockingClause *b)
 {
-       COMPARE_NODE_FIELD(resdom);
-       COMPARE_NODE_FIELD(fjoin);
-       COMPARE_NODE_FIELD(expr);
+       COMPARE_NODE_FIELD(lockedRels);
+       COMPARE_SCALAR_FIELD(forUpdate);
+       COMPARE_SCALAR_FIELD(noWait);
 
        return true;
 }
@@ -1486,15 +1845,16 @@ _equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
        COMPARE_SCALAR_FIELD(relid);
        COMPARE_NODE_FIELD(subquery);
        COMPARE_NODE_FIELD(funcexpr);
-       COMPARE_NODE_FIELD(coldeflist);
+       COMPARE_NODE_FIELD(funccoltypes);
+       COMPARE_NODE_FIELD(funccoltypmods);
+       COMPARE_NODE_FIELD(values_lists);
        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(requiredPerms);
        COMPARE_SCALAR_FIELD(checkAsUser);
 
        return true;
@@ -1505,6 +1865,17 @@ _equalSortClause(SortClause *a, SortClause *b)
 {
        COMPARE_SCALAR_FIELD(tleSortGroupRef);
        COMPARE_SCALAR_FIELD(sortop);
+       COMPARE_SCALAR_FIELD(nulls_first);
+
+       return true;
+}
+
+static bool
+_equalRowMarkClause(RowMarkClause *a, RowMarkClause *b)
+{
+       COMPARE_SCALAR_FIELD(rti);
+       COMPARE_SCALAR_FIELD(forUpdate);
+       COMPARE_SCALAR_FIELD(noWait);
 
        return true;
 }
@@ -1527,73 +1898,76 @@ _equalFkConstraint(FkConstraint *a, FkConstraint *b)
 }
 
 static bool
-_equalCaseExpr(CaseExpr *a, CaseExpr *b)
-{
-       COMPARE_SCALAR_FIELD(casetype);
-       COMPARE_NODE_FIELD(arg);
-       COMPARE_NODE_FIELD(args);
-       COMPARE_NODE_FIELD(defresult);
-
-       return true;
-}
-
-static bool
-_equalCaseWhen(CaseWhen *a, CaseWhen *b)
+_equalXmlSerialize(XmlSerialize *a, XmlSerialize *b)
 {
+       COMPARE_SCALAR_FIELD(xmloption);
        COMPARE_NODE_FIELD(expr);
-       COMPARE_NODE_FIELD(result);
-
-       return true;
-}
-
-static bool
-_equalNullTest(NullTest *a, NullTest *b)
-{
-       COMPARE_NODE_FIELD(arg);
-       COMPARE_SCALAR_FIELD(nulltesttype);
+       COMPARE_NODE_FIELD(typename);
 
        return true;
 }
 
-static bool
-_equalBooleanTest(BooleanTest *a, BooleanTest *b)
-{
-       COMPARE_NODE_FIELD(arg);
-       COMPARE_SCALAR_FIELD(booltesttype);
-
-       return true;
-}
+/*
+ * Stuff from pg_list.h
+ */
 
 static bool
-_equalConstraintTest(ConstraintTest *a, ConstraintTest *b)
+_equalList(List *a, List *b)
 {
-       COMPARE_NODE_FIELD(arg);
-       COMPARE_SCALAR_FIELD(testtype);
-       COMPARE_STRING_FIELD(name);
-       COMPARE_STRING_FIELD(domname);
-       COMPARE_NODE_FIELD(check_expr);
+       ListCell   *item_a;
+       ListCell   *item_b;
 
-       return true;
-}
+       /*
+        * Try to reject by simple scalar checks before grovelling through all the
+        * list elements...
+        */
+       COMPARE_SCALAR_FIELD(type);
+       COMPARE_SCALAR_FIELD(length);
 
-static bool
-_equalDomainConstraintValue(DomainConstraintValue *a, DomainConstraintValue *b)
-{
-       return true;
-}
+       /*
+        * We place the switch outside the loop for the sake of efficiency; this
+        * may not be worth doing...
+        */
+       switch (a->type)
+       {
+               case T_List:
+                       forboth(item_a, a, item_b, b)
+                       {
+                               if (!equal(lfirst(item_a), lfirst(item_b)))
+                                       return false;
+                       }
+                       break;
+               case T_IntList:
+                       forboth(item_a, a, item_b, b)
+                       {
+                               if (lfirst_int(item_a) != lfirst_int(item_b))
+                                       return false;
+                       }
+                       break;
+               case T_OidList:
+                       forboth(item_a, a, item_b, b)
+                       {
+                               if (lfirst_oid(item_a) != lfirst_oid(item_b))
+                                       return false;
+                       }
+                       break;
+               default:
+                       elog(ERROR, "unrecognized list node type: %d",
+                                (int) a->type);
+                       return false;           /* keep compiler quiet */
+       }
 
-static bool
-_equalConstraintTestValue(ConstraintTestValue *a, ConstraintTestValue *b)
-{
-       COMPARE_SCALAR_FIELD(typeId);
-       COMPARE_SCALAR_FIELD(typeMod);
+       /*
+        * If we got here, we should have run out of elements of both lists
+        */
+       Assert(item_a == NULL);
+       Assert(item_b == NULL);
 
        return true;
 }
 
-
 /*
- * Stuff from pg_list.h
+ * Stuff from value.h
  */
 
 static bool
@@ -1615,7 +1989,7 @@ _equalValue(Value *a, Value *b)
                        /* nothing to do */
                        break;
                default:
-                       elog(ERROR, "_equalValue: unknown node type %d", a->type);
+                       elog(ERROR, "unrecognized node type: %d", (int) a->type);
                        break;
        }
 
@@ -1629,7 +2003,7 @@ _equalValue(Value *a, Value *b)
 bool
 equal(void *a, void *b)
 {
-       bool            retval = false;
+       bool            retval;
 
        if (a == b)
                return true;
@@ -1648,25 +2022,21 @@ equal(void *a, void *b)
 
        switch (nodeTag(a))
        {
-               case T_SubPlan:
-                       retval = _equalSubPlan(a, b);
-                       break;
-
-               case T_Resdom:
-                       retval = _equalResdom(a, b);
+                       /*
+                        * PRIMITIVE NODES
+                        */
+               case T_Alias:
+                       retval = _equalAlias(a, b);
                        break;
-               case T_Fjoin:
-                       retval = _equalFjoin(a, b);
+               case T_RangeVar:
+                       retval = _equalRangeVar(a, b);
                        break;
-               case T_Expr:
-                       retval = _equalExpr(a, b);
+               case T_IntoClause:
+                       retval = _equalIntoClause(a, b);
                        break;
                case T_Var:
                        retval = _equalVar(a, b);
                        break;
-               case T_Oper:
-                       retval = _equalOper(a, b);
-                       break;
                case T_Const:
                        retval = _equalConst(a, b);
                        break;
@@ -1676,94 +2046,131 @@ equal(void *a, void *b)
                case T_Aggref:
                        retval = _equalAggref(a, b);
                        break;
+               case T_ArrayRef:
+                       retval = _equalArrayRef(a, b);
+                       break;
+               case T_FuncExpr:
+                       retval = _equalFuncExpr(a, b);
+                       break;
+               case T_OpExpr:
+                       retval = _equalOpExpr(a, b);
+                       break;
+               case T_DistinctExpr:
+                       retval = _equalDistinctExpr(a, b);
+                       break;
+               case T_ScalarArrayOpExpr:
+                       retval = _equalScalarArrayOpExpr(a, b);
+                       break;
+               case T_BoolExpr:
+                       retval = _equalBoolExpr(a, b);
+                       break;
                case T_SubLink:
                        retval = _equalSubLink(a, b);
                        break;
-               case T_Func:
-                       retval = _equalFunc(a, b);
+               case T_SubPlan:
+                       retval = _equalSubPlan(a, b);
                        break;
                case T_FieldSelect:
                        retval = _equalFieldSelect(a, b);
                        break;
-               case T_ArrayRef:
-                       retval = _equalArrayRef(a, b);
+               case T_FieldStore:
+                       retval = _equalFieldStore(a, b);
                        break;
                case T_RelabelType:
                        retval = _equalRelabelType(a, b);
                        break;
-               case T_RangeTblRef:
-                       retval = _equalRangeTblRef(a, b);
+               case T_CoerceViaIO:
+                       retval = _equalCoerceViaIO(a, b);
                        break;
-               case T_FromExpr:
-                       retval = _equalFromExpr(a, b);
+               case T_ArrayCoerceExpr:
+                       retval = _equalArrayCoerceExpr(a, b);
                        break;
-               case T_JoinExpr:
-                       retval = _equalJoinExpr(a, b);
+               case T_ConvertRowtypeExpr:
+                       retval = _equalConvertRowtypeExpr(a, b);
                        break;
-
-               case T_RelOptInfo:
-                       retval = _equalRelOptInfo(a, b);
+               case T_CaseExpr:
+                       retval = _equalCaseExpr(a, b);
+                       break;
+               case T_CaseWhen:
+                       retval = _equalCaseWhen(a, b);
                        break;
-               case T_Path:
-                       retval = _equalPath(a, b);
+               case T_CaseTestExpr:
+                       retval = _equalCaseTestExpr(a, b);
                        break;
-               case T_IndexPath:
-                       retval = _equalIndexPath(a, b);
+               case T_ArrayExpr:
+                       retval = _equalArrayExpr(a, b);
                        break;
-               case T_NestPath:
-                       retval = _equalNestPath(a, b);
+               case T_RowExpr:
+                       retval = _equalRowExpr(a, b);
                        break;
-               case T_MergePath:
-                       retval = _equalMergePath(a, b);
+               case T_RowCompareExpr:
+                       retval = _equalRowCompareExpr(a, b);
                        break;
-               case T_HashPath:
-                       retval = _equalHashPath(a, b);
+               case T_CoalesceExpr:
+                       retval = _equalCoalesceExpr(a, b);
                        break;
-               case T_PathKeyItem:
-                       retval = _equalPathKeyItem(a, b);
+               case T_MinMaxExpr:
+                       retval = _equalMinMaxExpr(a, b);
                        break;
-               case T_RestrictInfo:
-                       retval = _equalRestrictInfo(a, b);
+               case T_XmlExpr:
+                       retval = _equalXmlExpr(a, b);
+                       break;
+               case T_NullIfExpr:
+                       retval = _equalNullIfExpr(a, b);
+                       break;
+               case T_NullTest:
+                       retval = _equalNullTest(a, b);
+                       break;
+               case T_BooleanTest:
+                       retval = _equalBooleanTest(a, b);
+                       break;
+               case T_CoerceToDomain:
+                       retval = _equalCoerceToDomain(a, b);
+                       break;
+               case T_CoerceToDomainValue:
+                       retval = _equalCoerceToDomainValue(a, b);
                        break;
-               case T_JoinInfo:
-                       retval = _equalJoinInfo(a, b);
+               case T_SetToDefault:
+                       retval = _equalSetToDefault(a, b);
                        break;
-               case T_InnerIndexscanInfo:
-                       retval = _equalInnerIndexscanInfo(a, b);
+               case T_CurrentOfExpr:
+                       retval = _equalCurrentOfExpr(a, b);
                        break;
-               case T_TidPath:
-                       retval = _equalTidPath(a, b);
+               case T_TargetEntry:
+                       retval = _equalTargetEntry(a, b);
                        break;
-               case T_AppendPath:
-                       retval = _equalAppendPath(a, b);
+               case T_RangeTblRef:
+                       retval = _equalRangeTblRef(a, b);
                        break;
-               case T_ResultPath:
-                       retval = _equalResultPath(a, b);
+               case T_FromExpr:
+                       retval = _equalFromExpr(a, b);
                        break;
-               case T_IndexOptInfo:
-                       retval = _equalIndexOptInfo(a, b);
+               case T_JoinExpr:
+                       retval = _equalJoinExpr(a, b);
                        break;
 
+                       /*
+                        * RELATION NODES
+                        */
+               case T_PathKey:
+                       retval = _equalPathKey(a, b);
+                       break;
+               case T_RestrictInfo:
+                       retval = _equalRestrictInfo(a, b);
+                       break;
+               case T_OuterJoinInfo:
+                       retval = _equalOuterJoinInfo(a, b);
+                       break;
+               case T_InClauseInfo:
+                       retval = _equalInClauseInfo(a, b);
+                       break;
+               case T_AppendRelInfo:
+                       retval = _equalAppendRelInfo(a, b);
+                       break;
                case T_List:
-                       {
-                               List       *la = (List *) a;
-                               List       *lb = (List *) b;
-                               List       *l;
-
-                               /*
-                                * Try to reject by length check before we grovel through
-                                * all the elements...
-                                */
-                               if (length(la) != length(lb))
-                                       return false;
-                               foreach(l, la)
-                               {
-                                       if (!equal(lfirst(l), lfirst(lb)))
-                                               return false;
-                                       lb = lnext(lb);
-                               }
-                               retval = true;
-                       }
+               case T_IntList:
+               case T_OidList:
+                       retval = _equalList(a, b);
                        break;
 
                case T_Integer:
@@ -1774,6 +2181,9 @@ equal(void *a, void *b)
                        retval = _equalValue(a, b);
                        break;
 
+                       /*
+                        * PARSE NODES
+                        */
                case T_Query:
                        retval = _equalQuery(a, b);
                        break;
@@ -1795,9 +2205,21 @@ equal(void *a, void *b)
                case T_AlterTableStmt:
                        retval = _equalAlterTableStmt(a, b);
                        break;
+               case T_AlterTableCmd:
+                       retval = _equalAlterTableCmd(a, b);
+                       break;
+               case T_AlterDomainStmt:
+                       retval = _equalAlterDomainStmt(a, b);
+                       break;
                case T_GrantStmt:
                        retval = _equalGrantStmt(a, b);
                        break;
+               case T_GrantRoleStmt:
+                       retval = _equalGrantRoleStmt(a, b);
+                       break;
+               case T_DeclareCursorStmt:
+                       retval = _equalDeclareCursorStmt(a, b);
+                       break;
                case T_ClosePortalStmt:
                        retval = _equalClosePortalStmt(a, b);
                        break;
@@ -1810,6 +2232,9 @@ equal(void *a, void *b)
                case T_CreateStmt:
                        retval = _equalCreateStmt(a, b);
                        break;
+               case T_InhRelation:
+                       retval = _equalInhRelation(a, b);
+                       break;
                case T_DefineStmt:
                        retval = _equalDefineStmt(a, b);
                        break;
@@ -1831,21 +2256,30 @@ equal(void *a, void *b)
                case T_CreateFunctionStmt:
                        retval = _equalCreateFunctionStmt(a, b);
                        break;
-               case T_RemoveAggrStmt:
-                       retval = _equalRemoveAggrStmt(a, b);
+               case T_FunctionParameter:
+                       retval = _equalFunctionParameter(a, b);
+                       break;
+               case T_AlterFunctionStmt:
+                       retval = _equalAlterFunctionStmt(a, b);
                        break;
                case T_RemoveFuncStmt:
                        retval = _equalRemoveFuncStmt(a, b);
                        break;
-               case T_RemoveOperStmt:
-                       retval = _equalRemoveOperStmt(a, b);
-                       break;
                case T_RemoveOpClassStmt:
                        retval = _equalRemoveOpClassStmt(a, b);
                        break;
+               case T_RemoveOpFamilyStmt:
+                       retval = _equalRemoveOpFamilyStmt(a, b);
+                       break;
                case T_RenameStmt:
                        retval = _equalRenameStmt(a, b);
                        break;
+               case T_AlterObjectSchemaStmt:
+                       retval = _equalAlterObjectSchemaStmt(a, b);
+                       break;
+               case T_AlterOwnerStmt:
+                       retval = _equalAlterOwnerStmt(a, b);
+                       break;
                case T_RuleStmt:
                        retval = _equalRuleStmt(a, b);
                        break;
@@ -1864,6 +2298,9 @@ equal(void *a, void *b)
                case T_CompositeTypeStmt:
                        retval = _equalCompositeTypeStmt(a, b);
                        break;
+               case T_CreateEnumStmt:
+                       retval = _equalCreateEnumStmt(a, b);
+                       break;
                case T_ViewStmt:
                        retval = _equalViewStmt(a, b);
                        break;
@@ -1879,9 +2316,18 @@ equal(void *a, void *b)
                case T_CreateOpClassItem:
                        retval = _equalCreateOpClassItem(a, b);
                        break;
+               case T_CreateOpFamilyStmt:
+                       retval = _equalCreateOpFamilyStmt(a, b);
+                       break;
+               case T_AlterOpFamilyStmt:
+                       retval = _equalAlterOpFamilyStmt(a, b);
+                       break;
                case T_CreatedbStmt:
                        retval = _equalCreatedbStmt(a, b);
                        break;
+               case T_AlterDatabaseStmt:
+                       retval = _equalAlterDatabaseStmt(a, b);
+                       break;
                case T_AlterDatabaseSetStmt:
                        retval = _equalAlterDatabaseSetStmt(a, b);
                        break;
@@ -1897,6 +2343,9 @@ equal(void *a, void *b)
                case T_CreateSeqStmt:
                        retval = _equalCreateSeqStmt(a, b);
                        break;
+               case T_AlterSeqStmt:
+                       retval = _equalAlterSeqStmt(a, b);
+                       break;
                case T_VariableSetStmt:
                        retval = _equalVariableSetStmt(a, b);
                        break;
@@ -1906,6 +2355,15 @@ equal(void *a, void *b)
                case T_VariableResetStmt:
                        retval = _equalVariableResetStmt(a, b);
                        break;
+               case T_DiscardStmt:
+                       retval = _equalDiscardStmt(a, b);
+                       break;
+               case T_CreateTableSpaceStmt:
+                       retval = _equalCreateTableSpaceStmt(a, b);
+                       break;
+               case T_DropTableSpaceStmt:
+                       retval = _equalDropTableSpaceStmt(a, b);
+                       break;
                case T_CreateTrigStmt:
                        retval = _equalCreateTrigStmt(a, b);
                        break;
@@ -1918,17 +2376,17 @@ equal(void *a, void *b)
                case T_DropPLangStmt:
                        retval = _equalDropPLangStmt(a, b);
                        break;
-               case T_CreateUserStmt:
-                       retval = _equalCreateUserStmt(a, b);
+               case T_CreateRoleStmt:
+                       retval = _equalCreateRoleStmt(a, b);
                        break;
-               case T_AlterUserStmt:
-                       retval = _equalAlterUserStmt(a, b);
+               case T_AlterRoleStmt:
+                       retval = _equalAlterRoleStmt(a, b);
                        break;
-               case T_AlterUserSetStmt:
-                       retval = _equalAlterUserSetStmt(a, b);
+               case T_AlterRoleSetStmt:
+                       retval = _equalAlterRoleSetStmt(a, b);
                        break;
-               case T_DropUserStmt:
-                       retval = _equalDropUserStmt(a, b);
+               case T_DropRoleStmt:
+                       retval = _equalDropRoleStmt(a, b);
                        break;
                case T_LockStmt:
                        retval = _equalLockStmt(a, b);
@@ -1936,15 +2394,6 @@ equal(void *a, void *b)
                case T_ConstraintsSetStmt:
                        retval = _equalConstraintsSetStmt(a, b);
                        break;
-               case T_CreateGroupStmt:
-                       retval = _equalCreateGroupStmt(a, b);
-                       break;
-               case T_AlterGroupStmt:
-                       retval = _equalAlterGroupStmt(a, b);
-                       break;
-               case T_DropGroupStmt:
-                       retval = _equalDropGroupStmt(a, b);
-                       break;
                case T_ReindexStmt:
                        retval = _equalReindexStmt(a, b);
                        break;
@@ -1972,6 +2421,13 @@ equal(void *a, void *b)
                case T_DeallocateStmt:
                        retval = _equalDeallocateStmt(a, b);
                        break;
+               case T_DropOwnedStmt:
+                       retval = _equalDropOwnedStmt(a, b);
+                       break;
+
+               case T_ReassignOwnedStmt:
+                       retval = _equalReassignOwnedStmt(a, b);
+                       break;
 
                case T_A_Expr:
                        retval = _equalAExpr(a, b);
@@ -1991,8 +2447,8 @@ equal(void *a, void *b)
                case T_A_Indices:
                        retval = _equalAIndices(a, b);
                        break;
-               case T_ExprFieldSelect:
-                       retval = _equalExprFieldSelect(a, b);
+               case T_A_Indirection:
+                       retval = _equalA_Indirection(a, b);
                        break;
                case T_ResTarget:
                        retval = _equalResTarget(a, b);
@@ -2000,14 +2456,8 @@ equal(void *a, void *b)
                case T_TypeCast:
                        retval = _equalTypeCast(a, b);
                        break;
-               case T_SortGroupBy:
-                       retval = _equalSortGroupBy(a, b);
-                       break;
-               case T_Alias:
-                       retval = _equalAlias(a, b);
-                       break;
-               case T_RangeVar:
-                       retval = _equalRangeVar(a, b);
+               case T_SortBy:
+                       retval = _equalSortBy(a, b);
                        break;
                case T_RangeSubselect:
                        retval = _equalRangeSubselect(a, b);
@@ -2030,8 +2480,8 @@ equal(void *a, void *b)
                case T_DefElem:
                        retval = _equalDefElem(a, b);
                        break;
-               case T_TargetEntry:
-                       retval = _equalTargetEntry(a, b);
+               case T_LockingClause:
+                       retval = _equalLockingClause(a, b);
                        break;
                case T_RangeTblEntry:
                        retval = _equalRangeTblEntry(a, b);
@@ -2043,23 +2493,8 @@ equal(void *a, void *b)
                        /* GroupClause is equivalent to SortClause */
                        retval = _equalSortClause(a, b);
                        break;
-               case T_CaseExpr:
-                       retval = _equalCaseExpr(a, b);
-                       break;
-               case T_CaseWhen:
-                       retval = _equalCaseWhen(a, b);
-                       break;
-               case T_NullTest:
-                       retval = _equalNullTest(a, b);
-                       break;
-               case T_BooleanTest:
-                       retval = _equalBooleanTest(a, b);
-                       break;
-               case T_ConstraintTest:
-                       retval = _equalConstraintTest(a, b);
-                       break;
-               case T_ConstraintTestValue:
-                       retval = _equalConstraintTestValue(a, b);
+               case T_RowMarkClause:
+                       retval = _equalRowMarkClause(a, b);
                        break;
                case T_FkConstraint:
                        retval = _equalFkConstraint(a, b);
@@ -2070,16 +2505,14 @@ equal(void *a, void *b)
                case T_FuncWithArgs:
                        retval = _equalFuncWithArgs(a, b);
                        break;
-               case T_InsertDefault:
-                       retval = _equalInsertDefault(a, b);
-                       break;
-               case T_DomainConstraintValue:
-                       retval = _equalDomainConstraintValue(a, b);
+               case T_XmlSerialize:
+                       retval = _equalXmlSerialize(a, b);
                        break;
 
                default:
-                       elog(WARNING, "equal: don't know whether nodes of type %d are equal",
-                                nodeTag(a));
+                       elog(ERROR, "unrecognized node type: %d",
+                                (int) nodeTag(a));
+                       retval = false;         /* keep compiler quiet */
                        break;
        }