]> granicus.if.org Git - postgresql/blobdiff - src/backend/nodes/readfuncs.c
Improve parse representation for MERGE
[postgresql] / src / backend / nodes / readfuncs.c
index 8136306e1e55dd9e2471ec2204df5c7860cb8ac0..37e35685956729c3bfb70e78c60c909e54d0c710 100644 (file)
@@ -3,7 +3,7 @@
  * readfuncs.c
  *       Reader functions for Postgres tree nodes.
  *
- * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
@@ -11,8 +11,8 @@
  *       src/backend/nodes/readfuncs.c
  *
  * NOTES
- *       Path and Plan nodes do not have any readfuncs support, because we
- *       never have occasion to read them in.  (There was once code here that
+ *       Path nodes do not have any readfuncs support, because we never
+ *       have occasion to read them in.  (There was once code here that
  *       claimed to read them, but it was broken as well as unused.)  We
  *       never read executor state trees, either.
  *
 
 #include <math.h>
 
+#include "fmgr.h"
+#include "nodes/extensible.h"
 #include "nodes/parsenodes.h"
+#include "nodes/plannodes.h"
 #include "nodes/readfuncs.h"
+#include "utils/builtins.h"
 
 
 /*
        token = pg_strtok(&length);             /* get field value */ \
        local_node->fldname = atoui(token)
 
+/* Read an unsigned integer field (anything written using UINT64_FORMAT) */
+#define READ_UINT64_FIELD(fldname) \
+       token = pg_strtok(&length);             /* skip :fldname */ \
+       token = pg_strtok(&length);             /* get field value */ \
+       local_node->fldname = pg_strtouint64(token, NULL, 10)
+
+/* Read a long integer field (anything written as ":fldname %ld") */
+#define READ_LONG_FIELD(fldname) \
+       token = pg_strtok(&length);             /* skip :fldname */ \
+       token = pg_strtok(&length);             /* get field value */ \
+       local_node->fldname = atol(token)
+
 /* Read an OID field (don't hard-wire assumption that OID is same as uint) */
 #define READ_OID_FIELD(fldname) \
        token = pg_strtok(&length);             /* skip :fldname */ \
@@ -77,7 +93,8 @@
 #define READ_CHAR_FIELD(fldname) \
        token = pg_strtok(&length);             /* skip :fldname */ \
        token = pg_strtok(&length);             /* get field value */ \
-       local_node->fldname = token[0]
+       /* avoid overhead of calling debackslash() for one char */ \
+       local_node->fldname = (length == 0) ? '\0' : (token[0] == '\\' ? token[1] : token[0])
 
 /* Read an enumerated-type field that was written as an integer code */
 #define READ_ENUM_FIELD(fldname, enumtype) \
        (void) token;                           /* in case not used elsewhere */ \
        local_node->fldname = _readBitmapset()
 
+/* Read an attribute number array */
+#define READ_ATTRNUMBER_ARRAY(fldname, len) \
+       token = pg_strtok(&length);             /* skip :fldname */ \
+       local_node->fldname = readAttrNumberCols(len);
+
+/* Read an oid array */
+#define READ_OID_ARRAY(fldname, len) \
+       token = pg_strtok(&length);             /* skip :fldname */ \
+       local_node->fldname = readOidCols(len);
+
+/* Read an int array */
+#define READ_INT_ARRAY(fldname, len) \
+       token = pg_strtok(&length);             /* skip :fldname */ \
+       local_node->fldname = readIntCols(len);
+
+/* Read a bool array */
+#define READ_BOOL_ARRAY(fldname, len) \
+       token = pg_strtok(&length);             /* skip :fldname */ \
+       local_node->fldname = readBoolCols(len);
+
 /* Routine exit */
 #define READ_DONE() \
        return local_node
  */
 #define atoui(x)  ((unsigned int) strtoul((x), NULL, 10))
 
-#define atooid(x)  ((Oid) strtoul((x), NULL, 10))
-
 #define strtobool(x)  ((*(x) == 't') ? true : false)
 
 #define nullable_string(token,length)  \
        ((length) == 0 ? NULL : debackslash(token, length))
 
 
-static Datum readDatum(bool typbyval);
-
 /*
  * _readBitmapset
  */
@@ -186,6 +219,14 @@ _readBitmapset(void)
        return result;
 }
 
+/*
+ * for use by extensions which define extensible nodes
+ */
+Bitmapset *
+readBitmapset(void)
+{
+       return _readBitmapset();
+}
 
 /*
  * _readQuery
@@ -197,12 +238,13 @@ _readQuery(void)
 
        READ_ENUM_FIELD(commandType, CmdType);
        READ_ENUM_FIELD(querySource, QuerySource);
-       local_node->queryId = 0;        /* not saved in output format */
+       local_node->queryId = UINT64CONST(0);   /* not saved in output format */
        READ_BOOL_FIELD(canSetTag);
        READ_NODE_FIELD(utilityStmt);
        READ_INT_FIELD(resultRelation);
        READ_BOOL_FIELD(hasAggs);
        READ_BOOL_FIELD(hasWindowFuncs);
+       READ_BOOL_FIELD(hasTargetSRFs);
        READ_BOOL_FIELD(hasSubLinks);
        READ_BOOL_FIELD(hasDistinctOn);
        READ_BOOL_FIELD(hasRecursive);
@@ -213,10 +255,11 @@ _readQuery(void)
        READ_NODE_FIELD(rtable);
        READ_NODE_FIELD(jointree);
        READ_NODE_FIELD(targetList);
-       READ_NODE_FIELD(withCheckOptions);
+       READ_ENUM_FIELD(override, OverridingKind);
        READ_NODE_FIELD(onConflict);
        READ_NODE_FIELD(returningList);
        READ_NODE_FIELD(groupClause);
+       READ_NODE_FIELD(groupingSets);
        READ_NODE_FIELD(havingQual);
        READ_NODE_FIELD(windowClause);
        READ_NODE_FIELD(distinctClause);
@@ -226,6 +269,12 @@ _readQuery(void)
        READ_NODE_FIELD(rowMarks);
        READ_NODE_FIELD(setOperations);
        READ_NODE_FIELD(constraintDeps);
+       /* withCheckOptions intentionally omitted, see comment in parsenodes.h */
+       READ_INT_FIELD(mergeTarget_relation);
+       READ_NODE_FIELD(mergeSourceTargetList);
+       READ_NODE_FIELD(mergeActionList);
+       READ_LOCATION_FIELD(stmt_location);
+       READ_LOCATION_FIELD(stmt_len);
 
        READ_DONE();
 }
@@ -269,6 +318,7 @@ _readWithCheckOption(void)
 
        READ_ENUM_FIELD(kind, WCOKind);
        READ_STRING_FIELD(relname);
+       READ_STRING_FIELD(polname);
        READ_NODE_FIELD(qual);
        READ_BOOL_FIELD(cascaded);
 
@@ -292,6 +342,21 @@ _readSortGroupClause(void)
        READ_DONE();
 }
 
+/*
+ * _readGroupingSet
+ */
+static GroupingSet *
+_readGroupingSet(void)
+{
+       READ_LOCALS(GroupingSet);
+
+       READ_ENUM_FIELD(kind, GroupingSetKind);
+       READ_NODE_FIELD(content);
+       READ_LOCATION_FIELD(location);
+
+       READ_DONE();
+}
+
 /*
  * _readWindowClause
  */
@@ -307,6 +372,11 @@ _readWindowClause(void)
        READ_INT_FIELD(frameOptions);
        READ_NODE_FIELD(startOffset);
        READ_NODE_FIELD(endOffset);
+       READ_OID_FIELD(startInRangeFunc);
+       READ_OID_FIELD(endInRangeFunc);
+       READ_OID_FIELD(inRangeColl);
+       READ_BOOL_FIELD(inRangeAsc);
+       READ_BOOL_FIELD(inRangeNullsFirst);
        READ_UINT_FIELD(winref);
        READ_BOOL_FIELD(copiedOrder);
 
@@ -392,12 +462,11 @@ _readRangeVar(void)
 {
        READ_LOCALS(RangeVar);
 
-       local_node->catalogname = NULL;         /* not currently saved in output
-                                                                                * format */
+       local_node->catalogname = NULL; /* not currently saved in output format */
 
        READ_STRING_FIELD(schemaname);
        READ_STRING_FIELD(relname);
-       READ_ENUM_FIELD(inhOpt, InhOption);
+       READ_BOOL_FIELD(inh);
        READ_CHAR_FIELD(relpersistence);
        READ_NODE_FIELD(alias);
        READ_LOCATION_FIELD(location);
@@ -405,6 +474,31 @@ _readRangeVar(void)
        READ_DONE();
 }
 
+/*
+ * _readTableFunc
+ */
+static TableFunc *
+_readTableFunc(void)
+{
+       READ_LOCALS(TableFunc);
+
+       READ_NODE_FIELD(ns_uris);
+       READ_NODE_FIELD(ns_names);
+       READ_NODE_FIELD(docexpr);
+       READ_NODE_FIELD(rowexpr);
+       READ_NODE_FIELD(colnames);
+       READ_NODE_FIELD(coltypes);
+       READ_NODE_FIELD(coltypmods);
+       READ_NODE_FIELD(colcollations);
+       READ_NODE_FIELD(colexprs);
+       READ_NODE_FIELD(coldefexprs);
+       READ_BITMAPSET_FIELD(notnulls);
+       READ_INT_FIELD(ordinalitycol);
+       READ_LOCATION_FIELD(location);
+
+       READ_DONE();
+}
+
 static IntoClause *
 _readIntoClause(void)
 {
@@ -460,7 +554,7 @@ _readConst(void)
 
        token = pg_strtok(&length); /* skip :constvalue */
        if (local_node->constisnull)
-               token = pg_strtok(&length);             /* skip "<>" */
+               token = pg_strtok(&length); /* skip "<>" */
        else
                local_node->constvalue = readDatum(local_node->constbyval);
 
@@ -497,6 +591,8 @@ _readAggref(void)
        READ_OID_FIELD(aggtype);
        READ_OID_FIELD(aggcollid);
        READ_OID_FIELD(inputcollid);
+       READ_OID_FIELD(aggtranstype);
+       READ_NODE_FIELD(aggargtypes);
        READ_NODE_FIELD(aggdirectargs);
        READ_NODE_FIELD(args);
        READ_NODE_FIELD(aggorder);
@@ -506,6 +602,24 @@ _readAggref(void)
        READ_BOOL_FIELD(aggvariadic);
        READ_CHAR_FIELD(aggkind);
        READ_UINT_FIELD(agglevelsup);
+       READ_ENUM_FIELD(aggsplit, AggSplit);
+       READ_LOCATION_FIELD(location);
+
+       READ_DONE();
+}
+
+/*
+ * _readGroupingFunc
+ */
+static GroupingFunc *
+_readGroupingFunc(void)
+{
+       READ_LOCALS(GroupingFunc);
+
+       READ_NODE_FIELD(args);
+       READ_NODE_FIELD(refs);
+       READ_NODE_FIELD(cols);
+       READ_UINT_FIELD(agglevelsup);
        READ_LOCATION_FIELD(location);
 
        READ_DONE();
@@ -600,17 +714,6 @@ _readOpExpr(void)
 
        READ_OID_FIELD(opno);
        READ_OID_FIELD(opfuncid);
-
-       /*
-        * The opfuncid is stored in the textual format primarily for debugging
-        * and documentation reasons.  We want to always read it as zero to force
-        * it to be re-looked-up in the pg_operator entry.  This ensures that
-        * stored rules don't have hidden dependencies on operators' functions.
-        * (We don't currently support an ALTER OPERATOR command, but might
-        * someday.)
-        */
-       local_node->opfuncid = InvalidOid;
-
        READ_OID_FIELD(opresulttype);
        READ_BOOL_FIELD(opretset);
        READ_OID_FIELD(opcollid);
@@ -631,17 +734,6 @@ _readDistinctExpr(void)
 
        READ_OID_FIELD(opno);
        READ_OID_FIELD(opfuncid);
-
-       /*
-        * The opfuncid is stored in the textual format primarily for debugging
-        * and documentation reasons.  We want to always read it as zero to force
-        * it to be re-looked-up in the pg_operator entry.  This ensures that
-        * stored rules don't have hidden dependencies on operators' functions.
-        * (We don't currently support an ALTER OPERATOR command, but might
-        * someday.)
-        */
-       local_node->opfuncid = InvalidOid;
-
        READ_OID_FIELD(opresulttype);
        READ_BOOL_FIELD(opretset);
        READ_OID_FIELD(opcollid);
@@ -662,17 +754,6 @@ _readNullIfExpr(void)
 
        READ_OID_FIELD(opno);
        READ_OID_FIELD(opfuncid);
-
-       /*
-        * The opfuncid is stored in the textual format primarily for debugging
-        * and documentation reasons.  We want to always read it as zero to force
-        * it to be re-looked-up in the pg_operator entry.  This ensures that
-        * stored rules don't have hidden dependencies on operators' functions.
-        * (We don't currently support an ALTER OPERATOR command, but might
-        * someday.)
-        */
-       local_node->opfuncid = InvalidOid;
-
        READ_OID_FIELD(opresulttype);
        READ_BOOL_FIELD(opretset);
        READ_OID_FIELD(opcollid);
@@ -693,17 +774,6 @@ _readScalarArrayOpExpr(void)
 
        READ_OID_FIELD(opno);
        READ_OID_FIELD(opfuncid);
-
-       /*
-        * The opfuncid is stored in the textual format primarily for debugging
-        * and documentation reasons.  We want to always read it as zero to force
-        * it to be re-looked-up in the pg_operator entry.  This ensures that
-        * stored rules don't have hidden dependencies on operators' functions.
-        * (We don't currently support an ALTER OPERATOR command, but might
-        * someday.)
-        */
-       local_node->opfuncid = InvalidOid;
-
        READ_BOOL_FIELD(useOr);
        READ_OID_FIELD(inputcollid);
        READ_NODE_FIELD(args);
@@ -837,11 +907,10 @@ _readArrayCoerceExpr(void)
        READ_LOCALS(ArrayCoerceExpr);
 
        READ_NODE_FIELD(arg);
-       READ_OID_FIELD(elemfuncid);
+       READ_NODE_FIELD(elemexpr);
        READ_OID_FIELD(resulttype);
        READ_INT_FIELD(resulttypmod);
        READ_OID_FIELD(resultcollid);
-       READ_BOOL_FIELD(isExplicit);
        READ_ENUM_FIELD(coerceformat, CoercionForm);
        READ_LOCATION_FIELD(location);
 
@@ -1014,6 +1083,22 @@ _readMinMaxExpr(void)
        READ_DONE();
 }
 
+/*
+ * _readSQLValueFunction
+ */
+static SQLValueFunction *
+_readSQLValueFunction(void)
+{
+       READ_LOCALS(SQLValueFunction);
+
+       READ_ENUM_FIELD(op, SQLValueFunctionOp);
+       READ_OID_FIELD(type);
+       READ_INT_FIELD(typmod);
+       READ_LOCATION_FIELD(location);
+
+       READ_DONE();
+}
+
 /*
  * _readXmlExpr
  */
@@ -1131,6 +1216,20 @@ _readCurrentOfExpr(void)
        READ_DONE();
 }
 
+/*
+ * _readNextValueExpr
+ */
+static NextValueExpr *
+_readNextValueExpr(void)
+{
+       READ_LOCALS(NextValueExpr);
+
+       READ_OID_FIELD(seqid);
+       READ_OID_FIELD(typeId);
+
+       READ_DONE();
+}
+
 /*
  * _readInferenceElem
  */
@@ -1141,8 +1240,7 @@ _readInferenceElem(void)
 
        READ_NODE_FIELD(expr);
        READ_OID_FIELD(infercollid);
-       READ_OID_FIELD(inferopfamily);
-       READ_OID_FIELD(inferopcinputtype);
+       READ_OID_FIELD(inferopclass);
 
        READ_DONE();
 }
@@ -1224,15 +1322,31 @@ _readOnConflictExpr(void)
        READ_ENUM_FIELD(action, OnConflictAction);
        READ_NODE_FIELD(arbiterElems);
        READ_NODE_FIELD(arbiterWhere);
+       READ_OID_FIELD(constraint);
        READ_NODE_FIELD(onConflictSet);
        READ_NODE_FIELD(onConflictWhere);
-       READ_OID_FIELD(constraint);
        READ_INT_FIELD(exclRelIndex);
        READ_NODE_FIELD(exclRelTlist);
 
        READ_DONE();
 }
 
+/*
+ * _readMergeAction
+ */
+static MergeAction *
+_readMergeAction(void)
+{
+       READ_LOCALS(MergeAction);
+
+       READ_BOOL_FIELD(matched);
+       READ_ENUM_FIELD(commandType, CmdType);
+       READ_NODE_FIELD(qual);
+       READ_NODE_FIELD(targetList);
+
+       READ_DONE();
+}
+
 /*
  *     Stuff from parsenodes.h.
  */
@@ -1255,6 +1369,7 @@ _readRangeTblEntry(void)
                case RTE_RELATION:
                        READ_OID_FIELD(relid);
                        READ_CHAR_FIELD(relkind);
+                       READ_NODE_FIELD(tablesample);
                        break;
                case RTE_SUBQUERY:
                        READ_NODE_FIELD(subquery);
@@ -1268,17 +1383,30 @@ _readRangeTblEntry(void)
                        READ_NODE_FIELD(functions);
                        READ_BOOL_FIELD(funcordinality);
                        break;
+               case RTE_TABLEFUNC:
+                       READ_NODE_FIELD(tablefunc);
+                       break;
                case RTE_VALUES:
                        READ_NODE_FIELD(values_lists);
-                       READ_NODE_FIELD(values_collations);
+                       READ_NODE_FIELD(coltypes);
+                       READ_NODE_FIELD(coltypmods);
+                       READ_NODE_FIELD(colcollations);
                        break;
                case RTE_CTE:
                        READ_STRING_FIELD(ctename);
                        READ_UINT_FIELD(ctelevelsup);
                        READ_BOOL_FIELD(self_reference);
-                       READ_NODE_FIELD(ctecoltypes);
-                       READ_NODE_FIELD(ctecoltypmods);
-                       READ_NODE_FIELD(ctecolcollations);
+                       READ_NODE_FIELD(coltypes);
+                       READ_NODE_FIELD(coltypmods);
+                       READ_NODE_FIELD(colcollations);
+                       break;
+               case RTE_NAMEDTUPLESTORE:
+                       READ_STRING_FIELD(enrname);
+                       READ_FLOAT_FIELD(enrtuples);
+                       READ_OID_FIELD(relid);
+                       READ_NODE_FIELD(coltypes);
+                       READ_NODE_FIELD(coltypmods);
+                       READ_NODE_FIELD(colcollations);
                        break;
                default:
                        elog(ERROR, "unrecognized RTE kind: %d",
@@ -1318,164 +1446,1314 @@ _readRangeTblFunction(void)
        READ_DONE();
 }
 
-
 /*
- * parseNodeString
- *
- * Given a character string representing a node tree, parseNodeString creates
- * the internal node structure.
- *
- * The string to be read must already have been loaded into pg_strtok().
+ * _readTableSampleClause
  */
-Node *
-parseNodeString(void)
+static TableSampleClause *
+_readTableSampleClause(void)
 {
-       void       *return_value;
+       READ_LOCALS(TableSampleClause);
 
-       READ_TEMP_LOCALS();
+       READ_OID_FIELD(tsmhandler);
+       READ_NODE_FIELD(args);
+       READ_NODE_FIELD(repeatable);
 
-       token = pg_strtok(&length);
+       READ_DONE();
+}
 
-#define MATCH(tokname, namelen) \
-       (length == namelen && memcmp(token, tokname, namelen) == 0)
+/*
+ * _readDefElem
+ */
+static DefElem *
+_readDefElem(void)
+{
+       READ_LOCALS(DefElem);
 
-       if (MATCH("QUERY", 5))
-               return_value = _readQuery();
-       else if (MATCH("WITHCHECKOPTION", 15))
-               return_value = _readWithCheckOption();
-       else if (MATCH("SORTGROUPCLAUSE", 15))
-               return_value = _readSortGroupClause();
-       else if (MATCH("WINDOWCLAUSE", 12))
-               return_value = _readWindowClause();
-       else if (MATCH("ROWMARKCLAUSE", 13))
-               return_value = _readRowMarkClause();
-       else if (MATCH("COMMONTABLEEXPR", 15))
-               return_value = _readCommonTableExpr();
-       else if (MATCH("SETOPERATIONSTMT", 16))
-               return_value = _readSetOperationStmt();
-       else if (MATCH("ALIAS", 5))
-               return_value = _readAlias();
-       else if (MATCH("RANGEVAR", 8))
-               return_value = _readRangeVar();
-       else if (MATCH("INTOCLAUSE", 10))
-               return_value = _readIntoClause();
-       else if (MATCH("VAR", 3))
-               return_value = _readVar();
-       else if (MATCH("CONST", 5))
-               return_value = _readConst();
-       else if (MATCH("PARAM", 5))
-               return_value = _readParam();
-       else if (MATCH("AGGREF", 6))
-               return_value = _readAggref();
-       else if (MATCH("WINDOWFUNC", 10))
-               return_value = _readWindowFunc();
-       else if (MATCH("ARRAYREF", 8))
-               return_value = _readArrayRef();
-       else if (MATCH("FUNCEXPR", 8))
-               return_value = _readFuncExpr();
-       else if (MATCH("NAMEDARGEXPR", 12))
-               return_value = _readNamedArgExpr();
-       else if (MATCH("OPEXPR", 6))
-               return_value = _readOpExpr();
-       else if (MATCH("DISTINCTEXPR", 12))
-               return_value = _readDistinctExpr();
-       else if (MATCH("NULLIFEXPR", 10))
-               return_value = _readNullIfExpr();
-       else if (MATCH("SCALARARRAYOPEXPR", 17))
-               return_value = _readScalarArrayOpExpr();
-       else if (MATCH("BOOLEXPR", 8))
-               return_value = _readBoolExpr();
-       else if (MATCH("SUBLINK", 7))
-               return_value = _readSubLink();
-       else if (MATCH("FIELDSELECT", 11))
-               return_value = _readFieldSelect();
-       else if (MATCH("FIELDSTORE", 10))
-               return_value = _readFieldStore();
-       else if (MATCH("RELABELTYPE", 11))
-               return_value = _readRelabelType();
-       else if (MATCH("COERCEVIAIO", 11))
-               return_value = _readCoerceViaIO();
-       else if (MATCH("ARRAYCOERCEEXPR", 15))
-               return_value = _readArrayCoerceExpr();
-       else if (MATCH("CONVERTROWTYPEEXPR", 18))
-               return_value = _readConvertRowtypeExpr();
-       else if (MATCH("COLLATE", 7))
-               return_value = _readCollateExpr();
-       else if (MATCH("CASE", 4))
-               return_value = _readCaseExpr();
-       else if (MATCH("WHEN", 4))
-               return_value = _readCaseWhen();
-       else if (MATCH("CASETESTEXPR", 12))
-               return_value = _readCaseTestExpr();
-       else if (MATCH("ARRAY", 5))
-               return_value = _readArrayExpr();
-       else if (MATCH("ROW", 3))
-               return_value = _readRowExpr();
-       else if (MATCH("ROWCOMPARE", 10))
-               return_value = _readRowCompareExpr();
-       else if (MATCH("COALESCE", 8))
-               return_value = _readCoalesceExpr();
-       else if (MATCH("MINMAX", 6))
-               return_value = _readMinMaxExpr();
-       else if (MATCH("XMLEXPR", 7))
-               return_value = _readXmlExpr();
-       else if (MATCH("NULLTEST", 8))
-               return_value = _readNullTest();
-       else if (MATCH("BOOLEANTEST", 11))
-               return_value = _readBooleanTest();
-       else if (MATCH("COERCETODOMAIN", 14))
-               return_value = _readCoerceToDomain();
-       else if (MATCH("COERCETODOMAINVALUE", 19))
-               return_value = _readCoerceToDomainValue();
-       else if (MATCH("SETTODEFAULT", 12))
-               return_value = _readSetToDefault();
-       else if (MATCH("CURRENTOFEXPR", 13))
-               return_value = _readCurrentOfExpr();
-       else if (MATCH("INFERENCEELEM", 13))
-               return_value = _readInferenceElem();
-       else if (MATCH("TARGETENTRY", 11))
-               return_value = _readTargetEntry();
-       else if (MATCH("RANGETBLREF", 11))
-               return_value = _readRangeTblRef();
-       else if (MATCH("JOINEXPR", 8))
-               return_value = _readJoinExpr();
-       else if (MATCH("FROMEXPR", 8))
-               return_value = _readFromExpr();
-       else if (MATCH("ONCONFLICTEXPR", 14))
-               return_value = _readOnConflictExpr();
-       else if (MATCH("RTE", 3))
-               return_value = _readRangeTblEntry();
-       else if (MATCH("RANGETBLFUNCTION", 16))
-               return_value = _readRangeTblFunction();
-       else if (MATCH("NOTIFY", 6))
-               return_value = _readNotifyStmt();
-       else if (MATCH("DECLARECURSOR", 13))
-               return_value = _readDeclareCursorStmt();
-       else
-       {
-               elog(ERROR, "badly formatted node string \"%.32s\"...", token);
-               return_value = NULL;    /* keep compiler quiet */
-       }
+       READ_STRING_FIELD(defnamespace);
+       READ_STRING_FIELD(defname);
+       READ_NODE_FIELD(arg);
+       READ_ENUM_FIELD(defaction, DefElemAction);
+       READ_LOCATION_FIELD(location);
 
-       return (Node *) return_value;
+       READ_DONE();
 }
 
-
 /*
- * readDatum
- *
- * Given a string representation of a constant, recreate the appropriate
- * Datum.  The string representation embeds length info, but not byValue,
- * so we must be told that.
+ * _readPlannedStmt
  */
-static Datum
-readDatum(bool typbyval)
+static PlannedStmt *
+_readPlannedStmt(void)
 {
-       Size            length,
-                               i;
-       int                     tokenLength;
-       char       *token;
-       Datum           res;
+       READ_LOCALS(PlannedStmt);
+
+       READ_ENUM_FIELD(commandType, CmdType);
+       READ_UINT64_FIELD(queryId);
+       READ_BOOL_FIELD(hasReturning);
+       READ_BOOL_FIELD(hasModifyingCTE);
+       READ_BOOL_FIELD(canSetTag);
+       READ_BOOL_FIELD(transientPlan);
+       READ_BOOL_FIELD(dependsOnRole);
+       READ_BOOL_FIELD(parallelModeNeeded);
+       READ_BOOL_FIELD(jitFlags);
+       READ_NODE_FIELD(planTree);
+       READ_NODE_FIELD(rtable);
+       READ_NODE_FIELD(resultRelations);
+       READ_NODE_FIELD(nonleafResultRelations);
+       READ_NODE_FIELD(rootResultRelations);
+       READ_NODE_FIELD(subplans);
+       READ_BITMAPSET_FIELD(rewindPlanIDs);
+       READ_NODE_FIELD(rowMarks);
+       READ_NODE_FIELD(relationOids);
+       READ_NODE_FIELD(invalItems);
+       READ_NODE_FIELD(paramExecTypes);
+       READ_NODE_FIELD(utilityStmt);
+       READ_LOCATION_FIELD(stmt_location);
+       READ_LOCATION_FIELD(stmt_len);
+
+       READ_DONE();
+}
+
+/*
+ * ReadCommonPlan
+ *     Assign the basic stuff of all nodes that inherit from Plan
+ */
+static void
+ReadCommonPlan(Plan *local_node)
+{
+       READ_TEMP_LOCALS();
+
+       READ_FLOAT_FIELD(startup_cost);
+       READ_FLOAT_FIELD(total_cost);
+       READ_FLOAT_FIELD(plan_rows);
+       READ_INT_FIELD(plan_width);
+       READ_BOOL_FIELD(parallel_aware);
+       READ_BOOL_FIELD(parallel_safe);
+       READ_INT_FIELD(plan_node_id);
+       READ_NODE_FIELD(targetlist);
+       READ_NODE_FIELD(qual);
+       READ_NODE_FIELD(lefttree);
+       READ_NODE_FIELD(righttree);
+       READ_NODE_FIELD(initPlan);
+       READ_BITMAPSET_FIELD(extParam);
+       READ_BITMAPSET_FIELD(allParam);
+}
+
+/*
+ * _readPlan
+ */
+static Plan *
+_readPlan(void)
+{
+       READ_LOCALS_NO_FIELDS(Plan);
+
+       ReadCommonPlan(local_node);
+
+       READ_DONE();
+}
+
+/*
+ * _readResult
+ */
+static Result *
+_readResult(void)
+{
+       READ_LOCALS(Result);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_NODE_FIELD(resconstantqual);
+
+       READ_DONE();
+}
+
+/*
+ * _readProjectSet
+ */
+static ProjectSet *
+_readProjectSet(void)
+{
+       READ_LOCALS_NO_FIELDS(ProjectSet);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_DONE();
+}
+
+/*
+ * _readModifyTable
+ */
+static ModifyTable *
+_readModifyTable(void)
+{
+       READ_LOCALS(ModifyTable);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_ENUM_FIELD(operation, CmdType);
+       READ_BOOL_FIELD(canSetTag);
+       READ_UINT_FIELD(nominalRelation);
+       READ_NODE_FIELD(partitioned_rels);
+       READ_BOOL_FIELD(partColsUpdated);
+       READ_NODE_FIELD(resultRelations);
+       READ_INT_FIELD(mergeTargetRelation);
+       READ_INT_FIELD(resultRelIndex);
+       READ_INT_FIELD(rootResultRelIndex);
+       READ_NODE_FIELD(plans);
+       READ_NODE_FIELD(withCheckOptionLists);
+       READ_NODE_FIELD(returningLists);
+       READ_NODE_FIELD(fdwPrivLists);
+       READ_BITMAPSET_FIELD(fdwDirectModifyPlans);
+       READ_NODE_FIELD(rowMarks);
+       READ_INT_FIELD(epqParam);
+       READ_ENUM_FIELD(onConflictAction, OnConflictAction);
+       READ_NODE_FIELD(arbiterIndexes);
+       READ_NODE_FIELD(onConflictSet);
+       READ_NODE_FIELD(onConflictWhere);
+       READ_UINT_FIELD(exclRelRTI);
+       READ_NODE_FIELD(exclRelTlist);
+       READ_NODE_FIELD(mergeSourceTargetList);
+       READ_NODE_FIELD(mergeActionList);
+
+       READ_DONE();
+}
+
+/*
+ * _readMergeWhenClause
+ */
+static MergeWhenClause *
+_readMergeWhenClause(void)
+{
+       READ_LOCALS(MergeWhenClause);
+
+       READ_BOOL_FIELD(matched);
+       READ_ENUM_FIELD(commandType, CmdType);
+       READ_NODE_FIELD(condition);
+       READ_NODE_FIELD(targetList);
+       READ_NODE_FIELD(cols);
+       READ_NODE_FIELD(values);
+       READ_ENUM_FIELD(override, OverridingKind);
+
+       READ_DONE();
+}
+
+/*
+ * _readAppend
+ */
+static Append *
+_readAppend(void)
+{
+       READ_LOCALS(Append);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_NODE_FIELD(partitioned_rels);
+       READ_NODE_FIELD(appendplans);
+       READ_INT_FIELD(first_partial_plan);
+
+       READ_DONE();
+}
+
+/*
+ * _readMergeAppend
+ */
+static MergeAppend *
+_readMergeAppend(void)
+{
+       READ_LOCALS(MergeAppend);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_NODE_FIELD(partitioned_rels);
+       READ_NODE_FIELD(mergeplans);
+       READ_INT_FIELD(numCols);
+       READ_ATTRNUMBER_ARRAY(sortColIdx, local_node->numCols);
+       READ_OID_ARRAY(sortOperators, local_node->numCols);
+       READ_OID_ARRAY(collations, local_node->numCols);
+       READ_BOOL_ARRAY(nullsFirst, local_node->numCols);
+
+       READ_DONE();
+}
+
+/*
+ * _readRecursiveUnion
+ */
+static RecursiveUnion *
+_readRecursiveUnion(void)
+{
+       READ_LOCALS(RecursiveUnion);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_INT_FIELD(wtParam);
+       READ_INT_FIELD(numCols);
+       READ_ATTRNUMBER_ARRAY(dupColIdx, local_node->numCols);
+       READ_OID_ARRAY(dupOperators, local_node->numCols);
+       READ_LONG_FIELD(numGroups);
+
+       READ_DONE();
+}
+
+/*
+ * _readBitmapAnd
+ */
+static BitmapAnd *
+_readBitmapAnd(void)
+{
+       READ_LOCALS(BitmapAnd);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_NODE_FIELD(bitmapplans);
+
+       READ_DONE();
+}
+
+/*
+ * _readBitmapOr
+ */
+static BitmapOr *
+_readBitmapOr(void)
+{
+       READ_LOCALS(BitmapOr);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_BOOL_FIELD(isshared);
+       READ_NODE_FIELD(bitmapplans);
+
+       READ_DONE();
+}
+
+/*
+ * ReadCommonScan
+ *     Assign the basic stuff of all nodes that inherit from Scan
+ */
+static void
+ReadCommonScan(Scan *local_node)
+{
+       READ_TEMP_LOCALS();
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_UINT_FIELD(scanrelid);
+}
+
+/*
+ * _readScan
+ */
+static Scan *
+_readScan(void)
+{
+       READ_LOCALS_NO_FIELDS(Scan);
+
+       ReadCommonScan(local_node);
+
+       READ_DONE();
+}
+
+/*
+ * _readSeqScan
+ */
+static SeqScan *
+_readSeqScan(void)
+{
+       READ_LOCALS_NO_FIELDS(SeqScan);
+
+       ReadCommonScan(local_node);
+
+       READ_DONE();
+}
+
+/*
+ * _readSampleScan
+ */
+static SampleScan *
+_readSampleScan(void)
+{
+       READ_LOCALS(SampleScan);
+
+       ReadCommonScan(&local_node->scan);
+
+       READ_NODE_FIELD(tablesample);
+
+       READ_DONE();
+}
+
+/*
+ * _readIndexScan
+ */
+static IndexScan *
+_readIndexScan(void)
+{
+       READ_LOCALS(IndexScan);
+
+       ReadCommonScan(&local_node->scan);
+
+       READ_OID_FIELD(indexid);
+       READ_NODE_FIELD(indexqual);
+       READ_NODE_FIELD(indexqualorig);
+       READ_NODE_FIELD(indexorderby);
+       READ_NODE_FIELD(indexorderbyorig);
+       READ_NODE_FIELD(indexorderbyops);
+       READ_ENUM_FIELD(indexorderdir, ScanDirection);
+
+       READ_DONE();
+}
+
+/*
+ * _readIndexOnlyScan
+ */
+static IndexOnlyScan *
+_readIndexOnlyScan(void)
+{
+       READ_LOCALS(IndexOnlyScan);
+
+       ReadCommonScan(&local_node->scan);
+
+       READ_OID_FIELD(indexid);
+       READ_NODE_FIELD(indexqual);
+       READ_NODE_FIELD(indexorderby);
+       READ_NODE_FIELD(indextlist);
+       READ_ENUM_FIELD(indexorderdir, ScanDirection);
+
+       READ_DONE();
+}
+
+/*
+ * _readBitmapIndexScan
+ */
+static BitmapIndexScan *
+_readBitmapIndexScan(void)
+{
+       READ_LOCALS(BitmapIndexScan);
+
+       ReadCommonScan(&local_node->scan);
+
+       READ_OID_FIELD(indexid);
+       READ_BOOL_FIELD(isshared);
+       READ_NODE_FIELD(indexqual);
+       READ_NODE_FIELD(indexqualorig);
+
+       READ_DONE();
+}
+
+/*
+ * _readBitmapHeapScan
+ */
+static BitmapHeapScan *
+_readBitmapHeapScan(void)
+{
+       READ_LOCALS(BitmapHeapScan);
+
+       ReadCommonScan(&local_node->scan);
+
+       READ_NODE_FIELD(bitmapqualorig);
+
+       READ_DONE();
+}
+
+/*
+ * _readTidScan
+ */
+static TidScan *
+_readTidScan(void)
+{
+       READ_LOCALS(TidScan);
+
+       ReadCommonScan(&local_node->scan);
+
+       READ_NODE_FIELD(tidquals);
+
+       READ_DONE();
+}
+
+/*
+ * _readSubqueryScan
+ */
+static SubqueryScan *
+_readSubqueryScan(void)
+{
+       READ_LOCALS(SubqueryScan);
+
+       ReadCommonScan(&local_node->scan);
+
+       READ_NODE_FIELD(subplan);
+
+       READ_DONE();
+}
+
+/*
+ * _readFunctionScan
+ */
+static FunctionScan *
+_readFunctionScan(void)
+{
+       READ_LOCALS(FunctionScan);
+
+       ReadCommonScan(&local_node->scan);
+
+       READ_NODE_FIELD(functions);
+       READ_BOOL_FIELD(funcordinality);
+
+       READ_DONE();
+}
+
+/*
+ * _readValuesScan
+ */
+static ValuesScan *
+_readValuesScan(void)
+{
+       READ_LOCALS(ValuesScan);
+
+       ReadCommonScan(&local_node->scan);
+
+       READ_NODE_FIELD(values_lists);
+
+       READ_DONE();
+}
+
+/*
+ * _readTableFuncScan
+ */
+static TableFuncScan *
+_readTableFuncScan(void)
+{
+       READ_LOCALS(TableFuncScan);
+
+       ReadCommonScan(&local_node->scan);
+
+       READ_NODE_FIELD(tablefunc);
+
+       READ_DONE();
+}
+
+/*
+ * _readCteScan
+ */
+static CteScan *
+_readCteScan(void)
+{
+       READ_LOCALS(CteScan);
+
+       ReadCommonScan(&local_node->scan);
+
+       READ_INT_FIELD(ctePlanId);
+       READ_INT_FIELD(cteParam);
+
+       READ_DONE();
+}
+
+/*
+ * _readWorkTableScan
+ */
+static WorkTableScan *
+_readWorkTableScan(void)
+{
+       READ_LOCALS(WorkTableScan);
+
+       ReadCommonScan(&local_node->scan);
+
+       READ_INT_FIELD(wtParam);
+
+       READ_DONE();
+}
+
+/*
+ * _readForeignScan
+ */
+static ForeignScan *
+_readForeignScan(void)
+{
+       READ_LOCALS(ForeignScan);
+
+       ReadCommonScan(&local_node->scan);
+
+       READ_ENUM_FIELD(operation, CmdType);
+       READ_OID_FIELD(fs_server);
+       READ_NODE_FIELD(fdw_exprs);
+       READ_NODE_FIELD(fdw_private);
+       READ_NODE_FIELD(fdw_scan_tlist);
+       READ_NODE_FIELD(fdw_recheck_quals);
+       READ_BITMAPSET_FIELD(fs_relids);
+       READ_BOOL_FIELD(fsSystemCol);
+
+       READ_DONE();
+}
+
+/*
+ * _readCustomScan
+ */
+static CustomScan *
+_readCustomScan(void)
+{
+       READ_LOCALS(CustomScan);
+       char       *custom_name;
+       const CustomScanMethods *methods;
+
+       ReadCommonScan(&local_node->scan);
+
+       READ_UINT_FIELD(flags);
+       READ_NODE_FIELD(custom_plans);
+       READ_NODE_FIELD(custom_exprs);
+       READ_NODE_FIELD(custom_private);
+       READ_NODE_FIELD(custom_scan_tlist);
+       READ_BITMAPSET_FIELD(custom_relids);
+
+       /* Lookup CustomScanMethods by CustomName */
+       token = pg_strtok(&length); /* skip methods: */
+       token = pg_strtok(&length); /* CustomName */
+       custom_name = nullable_string(token, length);
+       methods = GetCustomScanMethods(custom_name, false);
+       local_node->methods = methods;
+
+       READ_DONE();
+}
+
+/*
+ * ReadCommonJoin
+ *     Assign the basic stuff of all nodes that inherit from Join
+ */
+static void
+ReadCommonJoin(Join *local_node)
+{
+       READ_TEMP_LOCALS();
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_ENUM_FIELD(jointype, JoinType);
+       READ_BOOL_FIELD(inner_unique);
+       READ_NODE_FIELD(joinqual);
+}
+
+/*
+ * _readJoin
+ */
+static Join *
+_readJoin(void)
+{
+       READ_LOCALS_NO_FIELDS(Join);
+
+       ReadCommonJoin(local_node);
+
+       READ_DONE();
+}
+
+/*
+ * _readNestLoop
+ */
+static NestLoop *
+_readNestLoop(void)
+{
+       READ_LOCALS(NestLoop);
+
+       ReadCommonJoin(&local_node->join);
+
+       READ_NODE_FIELD(nestParams);
+
+       READ_DONE();
+}
+
+/*
+ * _readMergeJoin
+ */
+static MergeJoin *
+_readMergeJoin(void)
+{
+       int                     numCols;
+
+       READ_LOCALS(MergeJoin);
+
+       ReadCommonJoin(&local_node->join);
+
+       READ_BOOL_FIELD(skip_mark_restore);
+       READ_NODE_FIELD(mergeclauses);
+
+       numCols = list_length(local_node->mergeclauses);
+
+       READ_OID_ARRAY(mergeFamilies, numCols);
+       READ_OID_ARRAY(mergeCollations, numCols);
+       READ_INT_ARRAY(mergeStrategies, numCols);
+       READ_BOOL_ARRAY(mergeNullsFirst, numCols);
+
+       READ_DONE();
+}
+
+/*
+ * _readHashJoin
+ */
+static HashJoin *
+_readHashJoin(void)
+{
+       READ_LOCALS(HashJoin);
+
+       ReadCommonJoin(&local_node->join);
+
+       READ_NODE_FIELD(hashclauses);
+
+       READ_DONE();
+}
+
+/*
+ * _readMaterial
+ */
+static Material *
+_readMaterial(void)
+{
+       READ_LOCALS_NO_FIELDS(Material);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_DONE();
+}
+
+/*
+ * _readSort
+ */
+static Sort *
+_readSort(void)
+{
+       READ_LOCALS(Sort);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_INT_FIELD(numCols);
+       READ_ATTRNUMBER_ARRAY(sortColIdx, local_node->numCols);
+       READ_OID_ARRAY(sortOperators, local_node->numCols);
+       READ_OID_ARRAY(collations, local_node->numCols);
+       READ_BOOL_ARRAY(nullsFirst, local_node->numCols);
+
+       READ_DONE();
+}
+
+/*
+ * _readGroup
+ */
+static Group *
+_readGroup(void)
+{
+       READ_LOCALS(Group);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_INT_FIELD(numCols);
+       READ_ATTRNUMBER_ARRAY(grpColIdx, local_node->numCols);
+       READ_OID_ARRAY(grpOperators, local_node->numCols);
+
+       READ_DONE();
+}
+
+/*
+ * _readAgg
+ */
+static Agg *
+_readAgg(void)
+{
+       READ_LOCALS(Agg);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_ENUM_FIELD(aggstrategy, AggStrategy);
+       READ_ENUM_FIELD(aggsplit, AggSplit);
+       READ_INT_FIELD(numCols);
+       READ_ATTRNUMBER_ARRAY(grpColIdx, local_node->numCols);
+       READ_OID_ARRAY(grpOperators, local_node->numCols);
+       READ_LONG_FIELD(numGroups);
+       READ_BITMAPSET_FIELD(aggParams);
+       READ_NODE_FIELD(groupingSets);
+       READ_NODE_FIELD(chain);
+
+       READ_DONE();
+}
+
+/*
+ * _readWindowAgg
+ */
+static WindowAgg *
+_readWindowAgg(void)
+{
+       READ_LOCALS(WindowAgg);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_UINT_FIELD(winref);
+       READ_INT_FIELD(partNumCols);
+       READ_ATTRNUMBER_ARRAY(partColIdx, local_node->partNumCols);
+       READ_OID_ARRAY(partOperators, local_node->partNumCols);
+       READ_INT_FIELD(ordNumCols);
+       READ_ATTRNUMBER_ARRAY(ordColIdx, local_node->ordNumCols);
+       READ_OID_ARRAY(ordOperators, local_node->ordNumCols);
+       READ_INT_FIELD(frameOptions);
+       READ_NODE_FIELD(startOffset);
+       READ_NODE_FIELD(endOffset);
+       READ_OID_FIELD(startInRangeFunc);
+       READ_OID_FIELD(endInRangeFunc);
+       READ_OID_FIELD(inRangeColl);
+       READ_BOOL_FIELD(inRangeAsc);
+       READ_BOOL_FIELD(inRangeNullsFirst);
+
+       READ_DONE();
+}
+
+/*
+ * _readUnique
+ */
+static Unique *
+_readUnique(void)
+{
+       READ_LOCALS(Unique);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_INT_FIELD(numCols);
+       READ_ATTRNUMBER_ARRAY(uniqColIdx, local_node->numCols);
+       READ_OID_ARRAY(uniqOperators, local_node->numCols);
+
+       READ_DONE();
+}
+
+/*
+ * _readGather
+ */
+static Gather *
+_readGather(void)
+{
+       READ_LOCALS(Gather);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_INT_FIELD(num_workers);
+       READ_INT_FIELD(rescan_param);
+       READ_BOOL_FIELD(single_copy);
+       READ_BOOL_FIELD(invisible);
+       READ_BITMAPSET_FIELD(initParam);
+
+       READ_DONE();
+}
+
+/*
+ * _readGatherMerge
+ */
+static GatherMerge *
+_readGatherMerge(void)
+{
+       READ_LOCALS(GatherMerge);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_INT_FIELD(num_workers);
+       READ_INT_FIELD(rescan_param);
+       READ_INT_FIELD(numCols);
+       READ_ATTRNUMBER_ARRAY(sortColIdx, local_node->numCols);
+       READ_OID_ARRAY(sortOperators, local_node->numCols);
+       READ_OID_ARRAY(collations, local_node->numCols);
+       READ_BOOL_ARRAY(nullsFirst, local_node->numCols);
+       READ_BITMAPSET_FIELD(initParam);
+
+       READ_DONE();
+}
+
+/*
+ * _readHash
+ */
+static Hash *
+_readHash(void)
+{
+       READ_LOCALS(Hash);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_OID_FIELD(skewTable);
+       READ_INT_FIELD(skewColumn);
+       READ_BOOL_FIELD(skewInherit);
+       READ_FLOAT_FIELD(rows_total);
+
+       READ_DONE();
+}
+
+/*
+ * _readSetOp
+ */
+static SetOp *
+_readSetOp(void)
+{
+       READ_LOCALS(SetOp);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_ENUM_FIELD(cmd, SetOpCmd);
+       READ_ENUM_FIELD(strategy, SetOpStrategy);
+       READ_INT_FIELD(numCols);
+       READ_ATTRNUMBER_ARRAY(dupColIdx, local_node->numCols);
+       READ_OID_ARRAY(dupOperators, local_node->numCols);
+       READ_INT_FIELD(flagColIdx);
+       READ_INT_FIELD(firstFlag);
+       READ_LONG_FIELD(numGroups);
+
+       READ_DONE();
+}
+
+/*
+ * _readLockRows
+ */
+static LockRows *
+_readLockRows(void)
+{
+       READ_LOCALS(LockRows);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_NODE_FIELD(rowMarks);
+       READ_INT_FIELD(epqParam);
+
+       READ_DONE();
+}
+
+/*
+ * _readLimit
+ */
+static Limit *
+_readLimit(void)
+{
+       READ_LOCALS(Limit);
+
+       ReadCommonPlan(&local_node->plan);
+
+       READ_NODE_FIELD(limitOffset);
+       READ_NODE_FIELD(limitCount);
+
+       READ_DONE();
+}
+
+/*
+ * _readNestLoopParam
+ */
+static NestLoopParam *
+_readNestLoopParam(void)
+{
+       READ_LOCALS(NestLoopParam);
+
+       READ_INT_FIELD(paramno);
+       READ_NODE_FIELD(paramval);
+
+       READ_DONE();
+}
+
+/*
+ * _readPlanRowMark
+ */
+static PlanRowMark *
+_readPlanRowMark(void)
+{
+       READ_LOCALS(PlanRowMark);
+
+       READ_UINT_FIELD(rti);
+       READ_UINT_FIELD(prti);
+       READ_UINT_FIELD(rowmarkId);
+       READ_ENUM_FIELD(markType, RowMarkType);
+       READ_INT_FIELD(allMarkTypes);
+       READ_ENUM_FIELD(strength, LockClauseStrength);
+       READ_ENUM_FIELD(waitPolicy, LockWaitPolicy);
+       READ_BOOL_FIELD(isParent);
+
+       READ_DONE();
+}
+
+/*
+ * _readPlanInvalItem
+ */
+static PlanInvalItem *
+_readPlanInvalItem(void)
+{
+       READ_LOCALS(PlanInvalItem);
+
+       READ_INT_FIELD(cacheId);
+       READ_UINT_FIELD(hashValue);
+
+       READ_DONE();
+}
+
+/*
+ * _readSubPlan
+ */
+static SubPlan *
+_readSubPlan(void)
+{
+       READ_LOCALS(SubPlan);
+
+       READ_ENUM_FIELD(subLinkType, SubLinkType);
+       READ_NODE_FIELD(testexpr);
+       READ_NODE_FIELD(paramIds);
+       READ_INT_FIELD(plan_id);
+       READ_STRING_FIELD(plan_name);
+       READ_OID_FIELD(firstColType);
+       READ_INT_FIELD(firstColTypmod);
+       READ_OID_FIELD(firstColCollation);
+       READ_BOOL_FIELD(useHashTable);
+       READ_BOOL_FIELD(unknownEqFalse);
+       READ_BOOL_FIELD(parallel_safe);
+       READ_NODE_FIELD(setParam);
+       READ_NODE_FIELD(parParam);
+       READ_NODE_FIELD(args);
+       READ_FLOAT_FIELD(startup_cost);
+       READ_FLOAT_FIELD(per_call_cost);
+
+       READ_DONE();
+}
+
+/*
+ * _readAlternativeSubPlan
+ */
+static AlternativeSubPlan *
+_readAlternativeSubPlan(void)
+{
+       READ_LOCALS(AlternativeSubPlan);
+
+       READ_NODE_FIELD(subplans);
+
+       READ_DONE();
+}
+
+/*
+ * _readExtensibleNode
+ */
+static ExtensibleNode *
+_readExtensibleNode(void)
+{
+       const ExtensibleNodeMethods *methods;
+       ExtensibleNode *local_node;
+       const char *extnodename;
+
+       READ_TEMP_LOCALS();
+
+       token = pg_strtok(&length); /* skip :extnodename */
+       token = pg_strtok(&length); /* get extnodename */
+
+       extnodename = nullable_string(token, length);
+       if (!extnodename)
+               elog(ERROR, "extnodename has to be supplied");
+       methods = GetExtensibleNodeMethods(extnodename, false);
+
+       local_node = (ExtensibleNode *) newNode(methods->node_size,
+                                                                                       T_ExtensibleNode);
+       local_node->extnodename = extnodename;
+
+       /* deserialize the private fields */
+       methods->nodeRead(local_node);
+
+       READ_DONE();
+}
+
+/*
+ * _readPartitionBoundSpec
+ */
+static PartitionBoundSpec *
+_readPartitionBoundSpec(void)
+{
+       READ_LOCALS(PartitionBoundSpec);
+
+       READ_CHAR_FIELD(strategy);
+       READ_BOOL_FIELD(is_default);
+       READ_INT_FIELD(modulus);
+       READ_INT_FIELD(remainder);
+       READ_NODE_FIELD(listdatums);
+       READ_NODE_FIELD(lowerdatums);
+       READ_NODE_FIELD(upperdatums);
+       READ_LOCATION_FIELD(location);
+
+       READ_DONE();
+}
+
+/*
+ * _readPartitionRangeDatum
+ */
+static PartitionRangeDatum *
+_readPartitionRangeDatum(void)
+{
+       READ_LOCALS(PartitionRangeDatum);
+
+       READ_ENUM_FIELD(kind, PartitionRangeDatumKind);
+       READ_NODE_FIELD(value);
+       READ_LOCATION_FIELD(location);
+
+       READ_DONE();
+}
+
+/*
+ * parseNodeString
+ *
+ * Given a character string representing a node tree, parseNodeString creates
+ * the internal node structure.
+ *
+ * The string to be read must already have been loaded into pg_strtok().
+ */
+Node *
+parseNodeString(void)
+{
+       void       *return_value;
+
+       READ_TEMP_LOCALS();
+
+       token = pg_strtok(&length);
+
+#define MATCH(tokname, namelen) \
+       (length == namelen && memcmp(token, tokname, namelen) == 0)
+
+       if (MATCH("QUERY", 5))
+               return_value = _readQuery();
+       else if (MATCH("WITHCHECKOPTION", 15))
+               return_value = _readWithCheckOption();
+       else if (MATCH("SORTGROUPCLAUSE", 15))
+               return_value = _readSortGroupClause();
+       else if (MATCH("GROUPINGSET", 11))
+               return_value = _readGroupingSet();
+       else if (MATCH("WINDOWCLAUSE", 12))
+               return_value = _readWindowClause();
+       else if (MATCH("ROWMARKCLAUSE", 13))
+               return_value = _readRowMarkClause();
+       else if (MATCH("COMMONTABLEEXPR", 15))
+               return_value = _readCommonTableExpr();
+       else if (MATCH("SETOPERATIONSTMT", 16))
+               return_value = _readSetOperationStmt();
+       else if (MATCH("ALIAS", 5))
+               return_value = _readAlias();
+       else if (MATCH("RANGEVAR", 8))
+               return_value = _readRangeVar();
+       else if (MATCH("INTOCLAUSE", 10))
+               return_value = _readIntoClause();
+       else if (MATCH("TABLEFUNC", 9))
+               return_value = _readTableFunc();
+       else if (MATCH("VAR", 3))
+               return_value = _readVar();
+       else if (MATCH("CONST", 5))
+               return_value = _readConst();
+       else if (MATCH("PARAM", 5))
+               return_value = _readParam();
+       else if (MATCH("AGGREF", 6))
+               return_value = _readAggref();
+       else if (MATCH("GROUPINGFUNC", 12))
+               return_value = _readGroupingFunc();
+       else if (MATCH("WINDOWFUNC", 10))
+               return_value = _readWindowFunc();
+       else if (MATCH("ARRAYREF", 8))
+               return_value = _readArrayRef();
+       else if (MATCH("FUNCEXPR", 8))
+               return_value = _readFuncExpr();
+       else if (MATCH("NAMEDARGEXPR", 12))
+               return_value = _readNamedArgExpr();
+       else if (MATCH("OPEXPR", 6))
+               return_value = _readOpExpr();
+       else if (MATCH("DISTINCTEXPR", 12))
+               return_value = _readDistinctExpr();
+       else if (MATCH("NULLIFEXPR", 10))
+               return_value = _readNullIfExpr();
+       else if (MATCH("SCALARARRAYOPEXPR", 17))
+               return_value = _readScalarArrayOpExpr();
+       else if (MATCH("BOOLEXPR", 8))
+               return_value = _readBoolExpr();
+       else if (MATCH("SUBLINK", 7))
+               return_value = _readSubLink();
+       else if (MATCH("FIELDSELECT", 11))
+               return_value = _readFieldSelect();
+       else if (MATCH("FIELDSTORE", 10))
+               return_value = _readFieldStore();
+       else if (MATCH("RELABELTYPE", 11))
+               return_value = _readRelabelType();
+       else if (MATCH("COERCEVIAIO", 11))
+               return_value = _readCoerceViaIO();
+       else if (MATCH("ARRAYCOERCEEXPR", 15))
+               return_value = _readArrayCoerceExpr();
+       else if (MATCH("CONVERTROWTYPEEXPR", 18))
+               return_value = _readConvertRowtypeExpr();
+       else if (MATCH("COLLATE", 7))
+               return_value = _readCollateExpr();
+       else if (MATCH("CASE", 4))
+               return_value = _readCaseExpr();
+       else if (MATCH("WHEN", 4))
+               return_value = _readCaseWhen();
+       else if (MATCH("CASETESTEXPR", 12))
+               return_value = _readCaseTestExpr();
+       else if (MATCH("ARRAY", 5))
+               return_value = _readArrayExpr();
+       else if (MATCH("ROW", 3))
+               return_value = _readRowExpr();
+       else if (MATCH("ROWCOMPARE", 10))
+               return_value = _readRowCompareExpr();
+       else if (MATCH("COALESCE", 8))
+               return_value = _readCoalesceExpr();
+       else if (MATCH("MINMAX", 6))
+               return_value = _readMinMaxExpr();
+       else if (MATCH("SQLVALUEFUNCTION", 16))
+               return_value = _readSQLValueFunction();
+       else if (MATCH("XMLEXPR", 7))
+               return_value = _readXmlExpr();
+       else if (MATCH("NULLTEST", 8))
+               return_value = _readNullTest();
+       else if (MATCH("BOOLEANTEST", 11))
+               return_value = _readBooleanTest();
+       else if (MATCH("COERCETODOMAIN", 14))
+               return_value = _readCoerceToDomain();
+       else if (MATCH("COERCETODOMAINVALUE", 19))
+               return_value = _readCoerceToDomainValue();
+       else if (MATCH("SETTODEFAULT", 12))
+               return_value = _readSetToDefault();
+       else if (MATCH("CURRENTOFEXPR", 13))
+               return_value = _readCurrentOfExpr();
+       else if (MATCH("NEXTVALUEEXPR", 13))
+               return_value = _readNextValueExpr();
+       else if (MATCH("INFERENCEELEM", 13))
+               return_value = _readInferenceElem();
+       else if (MATCH("TARGETENTRY", 11))
+               return_value = _readTargetEntry();
+       else if (MATCH("RANGETBLREF", 11))
+               return_value = _readRangeTblRef();
+       else if (MATCH("JOINEXPR", 8))
+               return_value = _readJoinExpr();
+       else if (MATCH("FROMEXPR", 8))
+               return_value = _readFromExpr();
+       else if (MATCH("ONCONFLICTEXPR", 14))
+               return_value = _readOnConflictExpr();
+       else if (MATCH("MERGEACTION", 11))
+               return_value = _readMergeAction();
+       else if (MATCH("RTE", 3))
+               return_value = _readRangeTblEntry();
+       else if (MATCH("RANGETBLFUNCTION", 16))
+               return_value = _readRangeTblFunction();
+       else if (MATCH("TABLESAMPLECLAUSE", 17))
+               return_value = _readTableSampleClause();
+       else if (MATCH("NOTIFY", 6))
+               return_value = _readNotifyStmt();
+       else if (MATCH("DEFELEM", 7))
+               return_value = _readDefElem();
+       else if (MATCH("DECLARECURSOR", 13))
+               return_value = _readDeclareCursorStmt();
+       else if (MATCH("PLANNEDSTMT", 11))
+               return_value = _readPlannedStmt();
+       else if (MATCH("PLAN", 4))
+               return_value = _readPlan();
+       else if (MATCH("RESULT", 6))
+               return_value = _readResult();
+       else if (MATCH("PROJECTSET", 10))
+               return_value = _readProjectSet();
+       else if (MATCH("MODIFYTABLE", 11))
+               return_value = _readModifyTable();
+       else if (MATCH("MERGEWHENCLAUSE", 15))
+               return_value = _readMergeWhenClause();
+       else if (MATCH("APPEND", 6))
+               return_value = _readAppend();
+       else if (MATCH("MERGEAPPEND", 11))
+               return_value = _readMergeAppend();
+       else if (MATCH("RECURSIVEUNION", 14))
+               return_value = _readRecursiveUnion();
+       else if (MATCH("BITMAPAND", 9))
+               return_value = _readBitmapAnd();
+       else if (MATCH("BITMAPOR", 8))
+               return_value = _readBitmapOr();
+       else if (MATCH("SCAN", 4))
+               return_value = _readScan();
+       else if (MATCH("SEQSCAN", 7))
+               return_value = _readSeqScan();
+       else if (MATCH("SAMPLESCAN", 10))
+               return_value = _readSampleScan();
+       else if (MATCH("INDEXSCAN", 9))
+               return_value = _readIndexScan();
+       else if (MATCH("INDEXONLYSCAN", 13))
+               return_value = _readIndexOnlyScan();
+       else if (MATCH("BITMAPINDEXSCAN", 15))
+               return_value = _readBitmapIndexScan();
+       else if (MATCH("BITMAPHEAPSCAN", 14))
+               return_value = _readBitmapHeapScan();
+       else if (MATCH("TIDSCAN", 7))
+               return_value = _readTidScan();
+       else if (MATCH("SUBQUERYSCAN", 12))
+               return_value = _readSubqueryScan();
+       else if (MATCH("FUNCTIONSCAN", 12))
+               return_value = _readFunctionScan();
+       else if (MATCH("VALUESSCAN", 10))
+               return_value = _readValuesScan();
+       else if (MATCH("TABLEFUNCSCAN", 13))
+               return_value = _readTableFuncScan();
+       else if (MATCH("CTESCAN", 7))
+               return_value = _readCteScan();
+       else if (MATCH("WORKTABLESCAN", 13))
+               return_value = _readWorkTableScan();
+       else if (MATCH("FOREIGNSCAN", 11))
+               return_value = _readForeignScan();
+       else if (MATCH("CUSTOMSCAN", 10))
+               return_value = _readCustomScan();
+       else if (MATCH("JOIN", 4))
+               return_value = _readJoin();
+       else if (MATCH("NESTLOOP", 8))
+               return_value = _readNestLoop();
+       else if (MATCH("MERGEJOIN", 9))
+               return_value = _readMergeJoin();
+       else if (MATCH("HASHJOIN", 8))
+               return_value = _readHashJoin();
+       else if (MATCH("MATERIAL", 8))
+               return_value = _readMaterial();
+       else if (MATCH("SORT", 4))
+               return_value = _readSort();
+       else if (MATCH("GROUP", 5))
+               return_value = _readGroup();
+       else if (MATCH("AGG", 3))
+               return_value = _readAgg();
+       else if (MATCH("WINDOWAGG", 9))
+               return_value = _readWindowAgg();
+       else if (MATCH("UNIQUE", 6))
+               return_value = _readUnique();
+       else if (MATCH("GATHER", 6))
+               return_value = _readGather();
+       else if (MATCH("GATHERMERGE", 11))
+               return_value = _readGatherMerge();
+       else if (MATCH("HASH", 4))
+               return_value = _readHash();
+       else if (MATCH("SETOP", 5))
+               return_value = _readSetOp();
+       else if (MATCH("LOCKROWS", 8))
+               return_value = _readLockRows();
+       else if (MATCH("LIMIT", 5))
+               return_value = _readLimit();
+       else if (MATCH("NESTLOOPPARAM", 13))
+               return_value = _readNestLoopParam();
+       else if (MATCH("PLANROWMARK", 11))
+               return_value = _readPlanRowMark();
+       else if (MATCH("PLANINVALITEM", 13))
+               return_value = _readPlanInvalItem();
+       else if (MATCH("SUBPLAN", 7))
+               return_value = _readSubPlan();
+       else if (MATCH("ALTERNATIVESUBPLAN", 18))
+               return_value = _readAlternativeSubPlan();
+       else if (MATCH("EXTENSIBLENODE", 14))
+               return_value = _readExtensibleNode();
+       else if (MATCH("PARTITIONBOUNDSPEC", 18))
+               return_value = _readPartitionBoundSpec();
+       else if (MATCH("PARTITIONRANGEDATUM", 19))
+               return_value = _readPartitionRangeDatum();
+       else
+       {
+               elog(ERROR, "badly formatted node string \"%.32s\"...", token);
+               return_value = NULL;    /* keep compiler quiet */
+       }
+
+       return (Node *) return_value;
+}
+
+
+/*
+ * readDatum
+ *
+ * Given a string representation of a constant, recreate the appropriate
+ * Datum.  The string representation embeds length info, but not byValue,
+ * so we must be told that.
+ */
+Datum
+readDatum(bool typbyval)
+{
+       Size            length,
+                               i;
+       int                     tokenLength;
+       char       *token;
+       Datum           res;
        char       *s;
 
        /*
@@ -1521,3 +2799,99 @@ readDatum(bool typbyval)
 
        return res;
 }
+
+/*
+ * readAttrNumberCols
+ */
+AttrNumber *
+readAttrNumberCols(int numCols)
+{
+       int                     tokenLength,
+                               i;
+       char       *token;
+       AttrNumber *attr_vals;
+
+       if (numCols <= 0)
+               return NULL;
+
+       attr_vals = (AttrNumber *) palloc(numCols * sizeof(AttrNumber));
+       for (i = 0; i < numCols; i++)
+       {
+               token = pg_strtok(&tokenLength);
+               attr_vals[i] = atoi(token);
+       }
+
+       return attr_vals;
+}
+
+/*
+ * readOidCols
+ */
+Oid *
+readOidCols(int numCols)
+{
+       int                     tokenLength,
+                               i;
+       char       *token;
+       Oid                *oid_vals;
+
+       if (numCols <= 0)
+               return NULL;
+
+       oid_vals = (Oid *) palloc(numCols * sizeof(Oid));
+       for (i = 0; i < numCols; i++)
+       {
+               token = pg_strtok(&tokenLength);
+               oid_vals[i] = atooid(token);
+       }
+
+       return oid_vals;
+}
+
+/*
+ * readIntCols
+ */
+int *
+readIntCols(int numCols)
+{
+       int                     tokenLength,
+                               i;
+       char       *token;
+       int                *int_vals;
+
+       if (numCols <= 0)
+               return NULL;
+
+       int_vals = (int *) palloc(numCols * sizeof(int));
+       for (i = 0; i < numCols; i++)
+       {
+               token = pg_strtok(&tokenLength);
+               int_vals[i] = atoi(token);
+       }
+
+       return int_vals;
+}
+
+/*
+ * readBoolCols
+ */
+bool *
+readBoolCols(int numCols)
+{
+       int                     tokenLength,
+                               i;
+       char       *token;
+       bool       *bool_vals;
+
+       if (numCols <= 0)
+               return NULL;
+
+       bool_vals = (bool *) palloc(numCols * sizeof(bool));
+       for (i = 0; i < numCols; i++)
+       {
+               token = pg_strtok(&tokenLength);
+               bool_vals[i] = strtobool(token);
+       }
+
+       return bool_vals;
+}