Skip to content
Snippets Groups Projects
Select Git revision
  • a05dc4d7fd57d4ae084c1f0801973e5c1a1aa26e
  • master default
  • benchmark-tools
  • postgres-lambda
  • REL9_4_25
  • REL9_5_20
  • REL9_6_16
  • REL_10_11
  • REL_11_6
  • REL_12_1
  • REL_12_0
  • REL_12_RC1
  • REL_12_BETA4
  • REL9_4_24
  • REL9_5_19
  • REL9_6_15
  • REL_10_10
  • REL_11_5
  • REL_12_BETA3
  • REL9_4_23
  • REL9_5_18
  • REL9_6_14
  • REL_10_9
  • REL_11_4
24 results

readfuncs.c

Blame
  • user avatar
    Robert Haas authored
    Commit a0d9f6e4 added this support for
    all other plan node types; this fills in the gap.
    
    Since TextOutCustomScan complicates this and is pretty well useless,
    remove it.
    
    KaiGai Kohei, with some modifications by me.
    a05dc4d7
    History
    readfuncs.c 50.33 KiB
    /*-------------------------------------------------------------------------
     *
     * readfuncs.c
     *	  Reader functions for Postgres tree nodes.
     *
     * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
     * Portions Copyright (c) 1994, Regents of the University of California
     *
     *
     * IDENTIFICATION
     *	  src/backend/nodes/readfuncs.c
     *
     * NOTES
     *	  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.
     *
     *	  Parse location fields are written out by outfuncs.c, but only for
     *	  possible debugging use.  When reading a location field, we discard
     *	  the stored value and set the location field to -1 (ie, "unknown").
     *	  This is because nodes coming from a stored rule should not be thought
     *	  to have a known location in the current query's text.
     *
     *-------------------------------------------------------------------------
     */
    #include "postgres.h"
    
    #include <math.h>
    
    #include "fmgr.h"
    #include "nodes/parsenodes.h"
    #include "nodes/plannodes.h"
    #include "nodes/readfuncs.h"
    
    
    /*
     * Macros to simplify reading of different kinds of fields.  Use these
     * wherever possible to reduce the chance for silly typos.  Note that these
     * hard-wire conventions about the names of the local variables in a Read
     * routine.
     */
    
    /* Macros for declaring appropriate local variables */
    
    /* A few guys need only local_node */
    #define READ_LOCALS_NO_FIELDS(nodeTypeName) \
    	nodeTypeName *local_node = makeNode(nodeTypeName)
    
    /* And a few guys need only the pg_strtok support fields */
    #define READ_TEMP_LOCALS()	\
    	char	   *token;		\
    	int			length
    
    /* ... but most need both */
    #define READ_LOCALS(nodeTypeName)			\
    	READ_LOCALS_NO_FIELDS(nodeTypeName);	\
    	READ_TEMP_LOCALS()
    
    /* Read an integer field (anything written as ":fldname %d") */
    #define READ_INT_FIELD(fldname) \
    	token = pg_strtok(&length);		/* skip :fldname */ \
    	token = pg_strtok(&length);		/* get field value */ \
    	local_node->fldname = atoi(token)
    
    /* Read an unsigned integer field (anything written as ":fldname %u") */
    #define READ_UINT_FIELD(fldname) \
    	token = pg_strtok(&length);		/* skip :fldname */ \
    	token = pg_strtok(&length);		/* get field value */ \
    	local_node->fldname = atoui(token)
    
    /* Read an 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 */ \
    	token = pg_strtok(&length);		/* get field value */ \
    	local_node->fldname = atooid(token)
    
    /* Read a char field (ie, one ascii character) */
    #define READ_CHAR_FIELD(fldname) \
    	token = pg_strtok(&length);		/* skip :fldname */ \
    	token = pg_strtok(&length);		/* get field value */ \
    	local_node->fldname = token[0]
    
    /* Read an enumerated-type field that was written as an integer code */
    #define READ_ENUM_FIELD(fldname, enumtype) \
    	token = pg_strtok(&length);		/* skip :fldname */ \
    	token = pg_strtok(&length);		/* get field value */ \
    	local_node->fldname = (enumtype) atoi(token)
    
    /* Read a float field */
    #define READ_FLOAT_FIELD(fldname) \
    	token = pg_strtok(&length);		/* skip :fldname */ \
    	token = pg_strtok(&length);		/* get field value */ \
    	local_node->fldname = atof(token)
    
    /* Read a boolean field */
    #define READ_BOOL_FIELD(fldname) \
    	token = pg_strtok(&length);		/* skip :fldname */ \
    	token = pg_strtok(&length);		/* get field value */ \
    	local_node->fldname = strtobool(token)
    
    /* Read a character-string field */
    #define READ_STRING_FIELD(fldname) \
    	token = pg_strtok(&length);		/* skip :fldname */ \
    	token = pg_strtok(&length);		/* get field value */ \
    	local_node->fldname = nullable_string(token, length)
    
    /* Read a parse location field (and throw away the value, per notes above) */
    #define READ_LOCATION_FIELD(fldname) \
    	token = pg_strtok(&length);		/* skip :fldname */ \
    	token = pg_strtok(&length);		/* get field value */ \
    	(void) token;				/* in case not used elsewhere */ \
    	local_node->fldname = -1	/* set field to "unknown" */
    
    /* Read a Node field */
    #define READ_NODE_FIELD(fldname) \
    	token = pg_strtok(&length);		/* skip :fldname */ \
    	(void) token;				/* in case not used elsewhere */ \
    	local_node->fldname = nodeRead(NULL, 0)
    
    /* Read a bitmapset field */
    #define READ_BITMAPSET_FIELD(fldname) \
    	token = pg_strtok(&length);		/* skip :fldname */ \
    	(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
    
    
    /*
     * NOTE: use atoi() to read values written with %d, or atoui() to read
     * values written with %u in outfuncs.c.  An exception is OID values,
     * for which use atooid().  (As of 7.1, outfuncs.c writes OIDs as %u,
     * but this will probably change in the future.)
     */
    #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);
    static bool *readBoolCols(int numCols);
    static int *readIntCols(int numCols);
    static Oid *readOidCols(int numCols);
    static AttrNumber *readAttrNumberCols(int numCols);
    
    /*
     * _readBitmapset
     */
    static Bitmapset *
    _readBitmapset(void)
    {
    	Bitmapset  *result = NULL;
    
    	READ_TEMP_LOCALS();
    
    	token = pg_strtok(&length);
    	if (token == NULL)
    		elog(ERROR, "incomplete Bitmapset structure");
    	if (length != 1 || token[0] != '(')
    		elog(ERROR, "unrecognized token: \"%.*s\"", length, token);
    
    	token = pg_strtok(&length);
    	if (token == NULL)
    		elog(ERROR, "incomplete Bitmapset structure");
    	if (length != 1 || token[0] != 'b')
    		elog(ERROR, "unrecognized token: \"%.*s\"", length, token);
    
    	for (;;)
    	{
    		int			val;
    		char	   *endptr;
    
    		token = pg_strtok(&length);
    		if (token == NULL)
    			elog(ERROR, "unterminated Bitmapset structure");
    		if (length == 1 && token[0] == ')')
    			break;
    		val = (int) strtol(token, &endptr, 10);
    		if (endptr != token + length)
    			elog(ERROR, "unrecognized integer: \"%.*s\"", length, token);
    		result = bms_add_member(result, val);
    	}
    
    	return result;
    }
    
    
    /*
     * _readQuery
     */
    static Query *
    _readQuery(void)
    {
    	READ_LOCALS(Query);
    
    	READ_ENUM_FIELD(commandType, CmdType);
    	READ_ENUM_FIELD(querySource, QuerySource);
    	local_node->queryId = 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(hasSubLinks);
    	READ_BOOL_FIELD(hasDistinctOn);
    	READ_BOOL_FIELD(hasRecursive);
    	READ_BOOL_FIELD(hasModifyingCTE);
    	READ_BOOL_FIELD(hasForUpdate);
    	READ_BOOL_FIELD(hasRowSecurity);
    	READ_NODE_FIELD(cteList);
    	READ_NODE_FIELD(rtable);
    	READ_NODE_FIELD(jointree);
    	READ_NODE_FIELD(targetList);
    	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);
    	READ_NODE_FIELD(sortClause);
    	READ_NODE_FIELD(limitOffset);
    	READ_NODE_FIELD(limitCount);
    	READ_NODE_FIELD(rowMarks);
    	READ_NODE_FIELD(setOperations);
    	READ_NODE_FIELD(constraintDeps);
    
    	READ_DONE();
    }
    
    /*
     * _readNotifyStmt
     */
    static NotifyStmt *
    _readNotifyStmt(void)
    {
    	READ_LOCALS(NotifyStmt);
    
    	READ_STRING_FIELD(conditionname);
    	READ_STRING_FIELD(payload);
    
    	READ_DONE();
    }
    
    /*
     * _readDeclareCursorStmt
     */
    static DeclareCursorStmt *
    _readDeclareCursorStmt(void)
    {
    	READ_LOCALS(DeclareCursorStmt);
    
    	READ_STRING_FIELD(portalname);
    	READ_INT_FIELD(options);
    	READ_NODE_FIELD(query);
    
    	READ_DONE();
    }
    
    /*
     * _readWithCheckOption
     */
    static WithCheckOption *
    _readWithCheckOption(void)
    {
    	READ_LOCALS(WithCheckOption);
    
    	READ_ENUM_FIELD(kind, WCOKind);
    	READ_STRING_FIELD(relname);
    	READ_STRING_FIELD(polname);
    	READ_NODE_FIELD(qual);
    	READ_BOOL_FIELD(cascaded);
    
    	READ_DONE();
    }
    
    /*
     * _readSortGroupClause
     */
    static SortGroupClause *
    _readSortGroupClause(void)
    {
    	READ_LOCALS(SortGroupClause);
    
    	READ_UINT_FIELD(tleSortGroupRef);
    	READ_OID_FIELD(eqop);
    	READ_OID_FIELD(sortop);
    	READ_BOOL_FIELD(nulls_first);
    	READ_BOOL_FIELD(hashable);
    
    	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
     */
    static WindowClause *
    _readWindowClause(void)
    {
    	READ_LOCALS(WindowClause);
    
    	READ_STRING_FIELD(name);
    	READ_STRING_FIELD(refname);
    	READ_NODE_FIELD(partitionClause);
    	READ_NODE_FIELD(orderClause);
    	READ_INT_FIELD(frameOptions);
    	READ_NODE_FIELD(startOffset);
    	READ_NODE_FIELD(endOffset);
    	READ_UINT_FIELD(winref);
    	READ_BOOL_FIELD(copiedOrder);
    
    	READ_DONE();
    }
    
    /*
     * _readRowMarkClause
     */
    static RowMarkClause *
    _readRowMarkClause(void)
    {
    	READ_LOCALS(RowMarkClause);
    
    	READ_UINT_FIELD(rti);
    	READ_ENUM_FIELD(strength, LockClauseStrength);
    	READ_ENUM_FIELD(waitPolicy, LockWaitPolicy);
    	READ_BOOL_FIELD(pushedDown);
    
    	READ_DONE();
    }
    
    /*
     * _readCommonTableExpr
     */
    static CommonTableExpr *
    _readCommonTableExpr(void)
    {
    	READ_LOCALS(CommonTableExpr);
    
    	READ_STRING_FIELD(ctename);
    	READ_NODE_FIELD(aliascolnames);
    	READ_NODE_FIELD(ctequery);
    	READ_LOCATION_FIELD(location);
    	READ_BOOL_FIELD(cterecursive);
    	READ_INT_FIELD(cterefcount);
    	READ_NODE_FIELD(ctecolnames);
    	READ_NODE_FIELD(ctecoltypes);
    	READ_NODE_FIELD(ctecoltypmods);
    	READ_NODE_FIELD(ctecolcollations);
    
    	READ_DONE();
    }
    
    /*
     * _readSetOperationStmt
     */
    static SetOperationStmt *
    _readSetOperationStmt(void)
    {
    	READ_LOCALS(SetOperationStmt);
    
    	READ_ENUM_FIELD(op, SetOperation);
    	READ_BOOL_FIELD(all);
    	READ_NODE_FIELD(larg);
    	READ_NODE_FIELD(rarg);
    	READ_NODE_FIELD(colTypes);
    	READ_NODE_FIELD(colTypmods);
    	READ_NODE_FIELD(colCollations);
    	READ_NODE_FIELD(groupClauses);
    
    	READ_DONE();
    }
    
    
    /*
     *	Stuff from primnodes.h.
     */
    
    static Alias *
    _readAlias(void)
    {
    	READ_LOCALS(Alias);
    
    	READ_STRING_FIELD(aliasname);
    	READ_NODE_FIELD(colnames);
    
    	READ_DONE();
    }
    
    static RangeVar *
    _readRangeVar(void)
    {
    	READ_LOCALS(RangeVar);
    
    	local_node->catalogname = NULL;		/* not currently saved in output
    										 * format */
    
    	READ_STRING_FIELD(schemaname);
    	READ_STRING_FIELD(relname);
    	READ_ENUM_FIELD(inhOpt, InhOption);
    	READ_CHAR_FIELD(relpersistence);
    	READ_NODE_FIELD(alias);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    static IntoClause *
    _readIntoClause(void)
    {
    	READ_LOCALS(IntoClause);
    
    	READ_NODE_FIELD(rel);
    	READ_NODE_FIELD(colNames);
    	READ_NODE_FIELD(options);
    	READ_ENUM_FIELD(onCommit, OnCommitAction);
    	READ_STRING_FIELD(tableSpaceName);
    	READ_NODE_FIELD(viewQuery);
    	READ_BOOL_FIELD(skipData);
    
    	READ_DONE();
    }
    
    /*
     * _readVar
     */
    static Var *
    _readVar(void)
    {
    	READ_LOCALS(Var);
    
    	READ_UINT_FIELD(varno);
    	READ_INT_FIELD(varattno);
    	READ_OID_FIELD(vartype);
    	READ_INT_FIELD(vartypmod);
    	READ_OID_FIELD(varcollid);
    	READ_UINT_FIELD(varlevelsup);
    	READ_UINT_FIELD(varnoold);
    	READ_INT_FIELD(varoattno);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readConst
     */
    static Const *
    _readConst(void)
    {
    	READ_LOCALS(Const);
    
    	READ_OID_FIELD(consttype);
    	READ_INT_FIELD(consttypmod);
    	READ_OID_FIELD(constcollid);
    	READ_INT_FIELD(constlen);
    	READ_BOOL_FIELD(constbyval);
    	READ_BOOL_FIELD(constisnull);
    	READ_LOCATION_FIELD(location);
    
    	token = pg_strtok(&length); /* skip :constvalue */
    	if (local_node->constisnull)
    		token = pg_strtok(&length);		/* skip "<>" */
    	else
    		local_node->constvalue = readDatum(local_node->constbyval);
    
    	READ_DONE();
    }
    
    /*
     * _readParam
     */
    static Param *
    _readParam(void)
    {
    	READ_LOCALS(Param);
    
    	READ_ENUM_FIELD(paramkind, ParamKind);
    	READ_INT_FIELD(paramid);
    	READ_OID_FIELD(paramtype);
    	READ_INT_FIELD(paramtypmod);
    	READ_OID_FIELD(paramcollid);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readAggref
     */
    static Aggref *
    _readAggref(void)
    {
    	READ_LOCALS(Aggref);
    
    	READ_OID_FIELD(aggfnoid);
    	READ_OID_FIELD(aggtype);
    	READ_OID_FIELD(aggcollid);
    	READ_OID_FIELD(inputcollid);
    	READ_NODE_FIELD(aggdirectargs);
    	READ_NODE_FIELD(args);
    	READ_NODE_FIELD(aggorder);
    	READ_NODE_FIELD(aggdistinct);
    	READ_NODE_FIELD(aggfilter);
    	READ_BOOL_FIELD(aggstar);
    	READ_BOOL_FIELD(aggvariadic);
    	READ_CHAR_FIELD(aggkind);
    	READ_UINT_FIELD(agglevelsup);
    	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();
    }
    
    /*
     * _readWindowFunc
     */
    static WindowFunc *
    _readWindowFunc(void)
    {
    	READ_LOCALS(WindowFunc);
    
    	READ_OID_FIELD(winfnoid);
    	READ_OID_FIELD(wintype);
    	READ_OID_FIELD(wincollid);
    	READ_OID_FIELD(inputcollid);
    	READ_NODE_FIELD(args);
    	READ_NODE_FIELD(aggfilter);
    	READ_UINT_FIELD(winref);
    	READ_BOOL_FIELD(winstar);
    	READ_BOOL_FIELD(winagg);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readArrayRef
     */
    static ArrayRef *
    _readArrayRef(void)
    {
    	READ_LOCALS(ArrayRef);
    
    	READ_OID_FIELD(refarraytype);
    	READ_OID_FIELD(refelemtype);
    	READ_INT_FIELD(reftypmod);
    	READ_OID_FIELD(refcollid);
    	READ_NODE_FIELD(refupperindexpr);
    	READ_NODE_FIELD(reflowerindexpr);
    	READ_NODE_FIELD(refexpr);
    	READ_NODE_FIELD(refassgnexpr);
    
    	READ_DONE();
    }
    
    /*
     * _readFuncExpr
     */
    static FuncExpr *
    _readFuncExpr(void)
    {
    	READ_LOCALS(FuncExpr);
    
    	READ_OID_FIELD(funcid);
    	READ_OID_FIELD(funcresulttype);
    	READ_BOOL_FIELD(funcretset);
    	READ_BOOL_FIELD(funcvariadic);
    	READ_ENUM_FIELD(funcformat, CoercionForm);
    	READ_OID_FIELD(funccollid);
    	READ_OID_FIELD(inputcollid);
    	READ_NODE_FIELD(args);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readNamedArgExpr
     */
    static NamedArgExpr *
    _readNamedArgExpr(void)
    {
    	READ_LOCALS(NamedArgExpr);
    
    	READ_NODE_FIELD(arg);
    	READ_STRING_FIELD(name);
    	READ_INT_FIELD(argnumber);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readOpExpr
     */
    static OpExpr *
    _readOpExpr(void)
    {
    	READ_LOCALS(OpExpr);
    
    	READ_OID_FIELD(opno);
    	READ_OID_FIELD(opfuncid);
    	READ_OID_FIELD(opresulttype);
    	READ_BOOL_FIELD(opretset);
    	READ_OID_FIELD(opcollid);
    	READ_OID_FIELD(inputcollid);
    	READ_NODE_FIELD(args);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readDistinctExpr
     */
    static DistinctExpr *
    _readDistinctExpr(void)
    {
    	READ_LOCALS(DistinctExpr);
    
    	READ_OID_FIELD(opno);
    	READ_OID_FIELD(opfuncid);
    	READ_OID_FIELD(opresulttype);
    	READ_BOOL_FIELD(opretset);
    	READ_OID_FIELD(opcollid);
    	READ_OID_FIELD(inputcollid);
    	READ_NODE_FIELD(args);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readNullIfExpr
     */
    static NullIfExpr *
    _readNullIfExpr(void)
    {
    	READ_LOCALS(NullIfExpr);
    
    	READ_OID_FIELD(opno);
    	READ_OID_FIELD(opfuncid);
    	READ_OID_FIELD(opresulttype);
    	READ_BOOL_FIELD(opretset);
    	READ_OID_FIELD(opcollid);
    	READ_OID_FIELD(inputcollid);
    	READ_NODE_FIELD(args);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readScalarArrayOpExpr
     */
    static ScalarArrayOpExpr *
    _readScalarArrayOpExpr(void)
    {
    	READ_LOCALS(ScalarArrayOpExpr);
    
    	READ_OID_FIELD(opno);
    	READ_OID_FIELD(opfuncid);
    	READ_BOOL_FIELD(useOr);
    	READ_OID_FIELD(inputcollid);
    	READ_NODE_FIELD(args);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readBoolExpr
     */
    static BoolExpr *
    _readBoolExpr(void)
    {
    	READ_LOCALS(BoolExpr);
    
    	/* do-it-yourself enum representation */
    	token = pg_strtok(&length); /* skip :boolop */
    	token = pg_strtok(&length); /* get field value */
    	if (strncmp(token, "and", 3) == 0)
    		local_node->boolop = AND_EXPR;
    	else if (strncmp(token, "or", 2) == 0)
    		local_node->boolop = OR_EXPR;
    	else if (strncmp(token, "not", 3) == 0)
    		local_node->boolop = NOT_EXPR;
    	else
    		elog(ERROR, "unrecognized boolop \"%.*s\"", length, token);
    
    	READ_NODE_FIELD(args);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readSubLink
     */
    static SubLink *
    _readSubLink(void)
    {
    	READ_LOCALS(SubLink);
    
    	READ_ENUM_FIELD(subLinkType, SubLinkType);
    	READ_INT_FIELD(subLinkId);
    	READ_NODE_FIELD(testexpr);
    	READ_NODE_FIELD(operName);
    	READ_NODE_FIELD(subselect);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readSubPlan is not needed since it doesn't appear in stored rules.
     */
    
    /*
     * _readFieldSelect
     */
    static FieldSelect *
    _readFieldSelect(void)
    {
    	READ_LOCALS(FieldSelect);
    
    	READ_NODE_FIELD(arg);
    	READ_INT_FIELD(fieldnum);
    	READ_OID_FIELD(resulttype);
    	READ_INT_FIELD(resulttypmod);
    	READ_OID_FIELD(resultcollid);
    
    	READ_DONE();
    }
    
    /*
     * _readFieldStore
     */
    static FieldStore *
    _readFieldStore(void)
    {
    	READ_LOCALS(FieldStore);
    
    	READ_NODE_FIELD(arg);
    	READ_NODE_FIELD(newvals);
    	READ_NODE_FIELD(fieldnums);
    	READ_OID_FIELD(resulttype);
    
    	READ_DONE();
    }
    
    /*
     * _readRelabelType
     */
    static RelabelType *
    _readRelabelType(void)
    {
    	READ_LOCALS(RelabelType);
    
    	READ_NODE_FIELD(arg);
    	READ_OID_FIELD(resulttype);
    	READ_INT_FIELD(resulttypmod);
    	READ_OID_FIELD(resultcollid);
    	READ_ENUM_FIELD(relabelformat, CoercionForm);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readCoerceViaIO
     */
    static CoerceViaIO *
    _readCoerceViaIO(void)
    {
    	READ_LOCALS(CoerceViaIO);
    
    	READ_NODE_FIELD(arg);
    	READ_OID_FIELD(resulttype);
    	READ_OID_FIELD(resultcollid);
    	READ_ENUM_FIELD(coerceformat, CoercionForm);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readArrayCoerceExpr
     */
    static ArrayCoerceExpr *
    _readArrayCoerceExpr(void)
    {
    	READ_LOCALS(ArrayCoerceExpr);
    
    	READ_NODE_FIELD(arg);
    	READ_OID_FIELD(elemfuncid);
    	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);
    
    	READ_DONE();
    }
    
    /*
     * _readConvertRowtypeExpr
     */
    static ConvertRowtypeExpr *
    _readConvertRowtypeExpr(void)
    {
    	READ_LOCALS(ConvertRowtypeExpr);
    
    	READ_NODE_FIELD(arg);
    	READ_OID_FIELD(resulttype);
    	READ_ENUM_FIELD(convertformat, CoercionForm);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readCollateExpr
     */
    static CollateExpr *
    _readCollateExpr(void)
    {
    	READ_LOCALS(CollateExpr);
    
    	READ_NODE_FIELD(arg);
    	READ_OID_FIELD(collOid);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readCaseExpr
     */
    static CaseExpr *
    _readCaseExpr(void)
    {
    	READ_LOCALS(CaseExpr);
    
    	READ_OID_FIELD(casetype);
    	READ_OID_FIELD(casecollid);
    	READ_NODE_FIELD(arg);
    	READ_NODE_FIELD(args);
    	READ_NODE_FIELD(defresult);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readCaseWhen
     */
    static CaseWhen *
    _readCaseWhen(void)
    {
    	READ_LOCALS(CaseWhen);
    
    	READ_NODE_FIELD(expr);
    	READ_NODE_FIELD(result);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readCaseTestExpr
     */
    static CaseTestExpr *
    _readCaseTestExpr(void)
    {
    	READ_LOCALS(CaseTestExpr);
    
    	READ_OID_FIELD(typeId);
    	READ_INT_FIELD(typeMod);
    	READ_OID_FIELD(collation);
    
    	READ_DONE();
    }
    
    /*
     * _readArrayExpr
     */
    static ArrayExpr *
    _readArrayExpr(void)
    {
    	READ_LOCALS(ArrayExpr);
    
    	READ_OID_FIELD(array_typeid);
    	READ_OID_FIELD(array_collid);
    	READ_OID_FIELD(element_typeid);
    	READ_NODE_FIELD(elements);
    	READ_BOOL_FIELD(multidims);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readRowExpr
     */
    static RowExpr *
    _readRowExpr(void)
    {
    	READ_LOCALS(RowExpr);
    
    	READ_NODE_FIELD(args);
    	READ_OID_FIELD(row_typeid);
    	READ_ENUM_FIELD(row_format, CoercionForm);
    	READ_NODE_FIELD(colnames);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readRowCompareExpr
     */
    static RowCompareExpr *
    _readRowCompareExpr(void)
    {
    	READ_LOCALS(RowCompareExpr);
    
    	READ_ENUM_FIELD(rctype, RowCompareType);
    	READ_NODE_FIELD(opnos);
    	READ_NODE_FIELD(opfamilies);
    	READ_NODE_FIELD(inputcollids);
    	READ_NODE_FIELD(largs);
    	READ_NODE_FIELD(rargs);
    
    	READ_DONE();
    }
    
    /*
     * _readCoalesceExpr
     */
    static CoalesceExpr *
    _readCoalesceExpr(void)
    {
    	READ_LOCALS(CoalesceExpr);
    
    	READ_OID_FIELD(coalescetype);
    	READ_OID_FIELD(coalescecollid);
    	READ_NODE_FIELD(args);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readMinMaxExpr
     */
    static MinMaxExpr *
    _readMinMaxExpr(void)
    {
    	READ_LOCALS(MinMaxExpr);
    
    	READ_OID_FIELD(minmaxtype);
    	READ_OID_FIELD(minmaxcollid);
    	READ_OID_FIELD(inputcollid);
    	READ_ENUM_FIELD(op, MinMaxOp);
    	READ_NODE_FIELD(args);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readXmlExpr
     */
    static XmlExpr *
    _readXmlExpr(void)
    {
    	READ_LOCALS(XmlExpr);
    
    	READ_ENUM_FIELD(op, XmlExprOp);
    	READ_STRING_FIELD(name);
    	READ_NODE_FIELD(named_args);
    	READ_NODE_FIELD(arg_names);
    	READ_NODE_FIELD(args);
    	READ_ENUM_FIELD(xmloption, XmlOptionType);
    	READ_OID_FIELD(type);
    	READ_INT_FIELD(typmod);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readNullTest
     */
    static NullTest *
    _readNullTest(void)
    {
    	READ_LOCALS(NullTest);
    
    	READ_NODE_FIELD(arg);
    	READ_ENUM_FIELD(nulltesttype, NullTestType);
    	READ_BOOL_FIELD(argisrow);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readBooleanTest
     */
    static BooleanTest *
    _readBooleanTest(void)
    {
    	READ_LOCALS(BooleanTest);
    
    	READ_NODE_FIELD(arg);
    	READ_ENUM_FIELD(booltesttype, BoolTestType);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readCoerceToDomain
     */
    static CoerceToDomain *
    _readCoerceToDomain(void)
    {
    	READ_LOCALS(CoerceToDomain);
    
    	READ_NODE_FIELD(arg);
    	READ_OID_FIELD(resulttype);
    	READ_INT_FIELD(resulttypmod);
    	READ_OID_FIELD(resultcollid);
    	READ_ENUM_FIELD(coercionformat, CoercionForm);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readCoerceToDomainValue
     */
    static CoerceToDomainValue *
    _readCoerceToDomainValue(void)
    {
    	READ_LOCALS(CoerceToDomainValue);
    
    	READ_OID_FIELD(typeId);
    	READ_INT_FIELD(typeMod);
    	READ_OID_FIELD(collation);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readSetToDefault
     */
    static SetToDefault *
    _readSetToDefault(void)
    {
    	READ_LOCALS(SetToDefault);
    
    	READ_OID_FIELD(typeId);
    	READ_INT_FIELD(typeMod);
    	READ_OID_FIELD(collation);
    	READ_LOCATION_FIELD(location);
    
    	READ_DONE();
    }
    
    /*
     * _readCurrentOfExpr
     */
    static CurrentOfExpr *
    _readCurrentOfExpr(void)
    {
    	READ_LOCALS(CurrentOfExpr);
    
    	READ_UINT_FIELD(cvarno);
    	READ_STRING_FIELD(cursor_name);
    	READ_INT_FIELD(cursor_param);
    
    	READ_DONE();
    }
    
    /*
     * _readInferenceElem
     */
    static InferenceElem *
    _readInferenceElem(void)
    {
    	READ_LOCALS(InferenceElem);
    
    	READ_NODE_FIELD(expr);
    	READ_OID_FIELD(infercollid);
    	READ_OID_FIELD(inferopclass);
    
    	READ_DONE();
    }
    
    /*
     * _readTargetEntry
     */
    static TargetEntry *
    _readTargetEntry(void)
    {
    	READ_LOCALS(TargetEntry);
    
    	READ_NODE_FIELD(expr);
    	READ_INT_FIELD(resno);
    	READ_STRING_FIELD(resname);
    	READ_UINT_FIELD(ressortgroupref);
    	READ_OID_FIELD(resorigtbl);
    	READ_INT_FIELD(resorigcol);
    	READ_BOOL_FIELD(resjunk);
    
    	READ_DONE();
    }
    
    /*
     * _readRangeTblRef
     */
    static RangeTblRef *
    _readRangeTblRef(void)
    {
    	READ_LOCALS(RangeTblRef);
    
    	READ_INT_FIELD(rtindex);
    
    	READ_DONE();
    }
    
    /*
     * _readJoinExpr
     */
    static JoinExpr *
    _readJoinExpr(void)
    {
    	READ_LOCALS(JoinExpr);
    
    	READ_ENUM_FIELD(jointype, JoinType);
    	READ_BOOL_FIELD(isNatural);
    	READ_NODE_FIELD(larg);
    	READ_NODE_FIELD(rarg);
    	READ_NODE_FIELD(usingClause);
    	READ_NODE_FIELD(quals);
    	READ_NODE_FIELD(alias);
    	READ_INT_FIELD(rtindex);
    
    	READ_DONE();
    }
    
    /*
     * _readFromExpr
     */
    static FromExpr *
    _readFromExpr(void)
    {
    	READ_LOCALS(FromExpr);
    
    	READ_NODE_FIELD(fromlist);
    	READ_NODE_FIELD(quals);
    
    	READ_DONE();
    }
    
    /*
     * _readOnConflictExpr
     */
    static OnConflictExpr *
    _readOnConflictExpr(void)
    {
    	READ_LOCALS(OnConflictExpr);
    
    	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_INT_FIELD(exclRelIndex);
    	READ_NODE_FIELD(exclRelTlist);
    
    	READ_DONE();
    }
    
    /*
     *	Stuff from parsenodes.h.
     */
    
    /*
     * _readRangeTblEntry
     */
    static RangeTblEntry *
    _readRangeTblEntry(void)
    {
    	READ_LOCALS(RangeTblEntry);
    
    	/* put alias + eref first to make dump more legible */
    	READ_NODE_FIELD(alias);
    	READ_NODE_FIELD(eref);
    	READ_ENUM_FIELD(rtekind, RTEKind);
    
    	switch (local_node->rtekind)
    	{
    		case RTE_RELATION:
    			READ_OID_FIELD(relid);
    			READ_CHAR_FIELD(relkind);
    			READ_NODE_FIELD(tablesample);
    			break;
    		case RTE_SUBQUERY:
    			READ_NODE_FIELD(subquery);
    			READ_BOOL_FIELD(security_barrier);
    			break;
    		case RTE_JOIN:
    			READ_ENUM_FIELD(jointype, JoinType);
    			READ_NODE_FIELD(joinaliasvars);
    			break;
    		case RTE_FUNCTION:
    			READ_NODE_FIELD(functions);
    			READ_BOOL_FIELD(funcordinality);
    			break;
    		case RTE_VALUES:
    			READ_NODE_FIELD(values_lists);
    			READ_NODE_FIELD(values_collations);
    			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);
    			break;
    		default:
    			elog(ERROR, "unrecognized RTE kind: %d",
    				 (int) local_node->rtekind);
    			break;
    	}
    
    	READ_BOOL_FIELD(lateral);
    	READ_BOOL_FIELD(inh);
    	READ_BOOL_FIELD(inFromCl);
    	READ_UINT_FIELD(requiredPerms);
    	READ_OID_FIELD(checkAsUser);
    	READ_BITMAPSET_FIELD(selectedCols);
    	READ_BITMAPSET_FIELD(insertedCols);
    	READ_BITMAPSET_FIELD(updatedCols);
    	READ_NODE_FIELD(securityQuals);
    
    	READ_DONE();
    }
    
    /*
     * _readRangeTblFunction
     */
    static RangeTblFunction *
    _readRangeTblFunction(void)
    {
    	READ_LOCALS(RangeTblFunction);
    
    	READ_NODE_FIELD(funcexpr);
    	READ_INT_FIELD(funccolcount);
    	READ_NODE_FIELD(funccolnames);
    	READ_NODE_FIELD(funccoltypes);
    	READ_NODE_FIELD(funccoltypmods);
    	READ_NODE_FIELD(funccolcollations);
    	READ_BITMAPSET_FIELD(funcparams);
    
    	READ_DONE();
    }
    
    /*
     * _readTableSampleClause
     */
    static TableSampleClause *
    _readTableSampleClause(void)
    {
    	READ_LOCALS(TableSampleClause);
    
    	READ_OID_FIELD(tsmhandler);
    	READ_NODE_FIELD(args);
    	READ_NODE_FIELD(repeatable);
    
    	READ_DONE();
    }
    
    /*
     * _readDefElem
     */
    static DefElem *
    _readDefElem(void)
    {
    	READ_LOCALS(DefElem);
    
    	READ_STRING_FIELD(defnamespace);
    	READ_STRING_FIELD(defname);
    	READ_NODE_FIELD(arg);
    	READ_ENUM_FIELD(defaction, DefElemAction);
    
    	READ_DONE();
    }
    
    /*
     * _readPlannedStmt
     */
    static PlannedStmt *
    _readPlannedStmt(void)
    {
    	READ_LOCALS(PlannedStmt);
    
    	READ_ENUM_FIELD(commandType, CmdType);
    	READ_UINT_FIELD(queryId);
    	READ_BOOL_FIELD(hasReturning);
    	READ_BOOL_FIELD(hasModifyingCTE);
    	READ_BOOL_FIELD(canSetTag);
    	READ_BOOL_FIELD(transientPlan);
    	READ_NODE_FIELD(planTree);
    	READ_NODE_FIELD(rtable);
    	READ_NODE_FIELD(resultRelations);
    	READ_NODE_FIELD(utilityStmt);
    	READ_NODE_FIELD(subplans);
    	READ_BITMAPSET_FIELD(rewindPlanIDs);
    	READ_NODE_FIELD(rowMarks);
    	READ_NODE_FIELD(relationOids);
    	READ_NODE_FIELD(invalItems);
    	READ_INT_FIELD(nParamExec);
    	READ_BOOL_FIELD(hasRowSecurity);
    	READ_BOOL_FIELD(parallelModeNeeded);
    
    	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_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();
    }
    
    /*
     * _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(resultRelations);
    	READ_INT_FIELD(resultRelIndex);
    	READ_NODE_FIELD(plans);
    	READ_NODE_FIELD(withCheckOptionLists);
    	READ_NODE_FIELD(returningLists);
    	READ_NODE_FIELD(fdwPrivLists);
    	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_DONE();
    }
    
    /*
     * _readAppend
     */
    static Append *
    _readAppend(void)
    {
    	READ_LOCALS(Append);
    
    	ReadCommonPlan(&local_node->plan);
    
    	READ_NODE_FIELD(appendplans);
    
    	READ_DONE();
    }
    
    /*
     * _readMergeAppend
     */
    static MergeAppend *
    _readMergeAppend(void)
    {
    	READ_LOCALS(MergeAppend);
    
    	ReadCommonPlan(&local_node->plan);
    
    	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_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_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();
    }
    
    /*
     * _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_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	   *library_name;
    	char	   *symbol_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);
    
    	/*
    	 * Reconstruction of methods using library and symbol name
    	 */
    	token = pg_strtok(&length);		/* skip methods: */
    	token = pg_strtok(&length);		/* LibraryName */
    	library_name = nullable_string(token, length);
    	token = pg_strtok(&length);		/* SymbolName */
    	symbol_name = nullable_string(token, length);
    
    	methods = (const CustomScanMethods *)
    		load_external_function(library_name, symbol_name, true, NULL);
    	Assert(strcmp(methods->LibraryName, library_name) == 0 &&
    		   strcmp(methods->SymbolName, symbol_name) == 0);
    	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_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_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_INT_FIELD(numCols);
    	READ_ATTRNUMBER_ARRAY(grpColIdx, local_node->numCols);
    	READ_OID_ARRAY(grpOperators, local_node->numCols);
    	READ_LONG_FIELD(numGroups);
    	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_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_BOOL_FIELD(single_copy);
    
    	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_OID_FIELD(skewColType);
    	READ_INT_FIELD(skewColTypmod);
    
    	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_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();
    }
    
    /*
     * 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("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("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("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("MODIFYTABLE", 11))
    		return_value = _readModifyTable();
    	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("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("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
    	{
    		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.
     */
    static Datum
    readDatum(bool typbyval)
    {
    	Size		length,
    				i;
    	int			tokenLength;
    	char	   *token;
    	Datum		res;
    	char	   *s;
    
    	/*
    	 * read the actual length of the value
    	 */
    	token = pg_strtok(&tokenLength);
    	length = atoui(token);
    
    	token = pg_strtok(&tokenLength);	/* read the '[' */
    	if (token == NULL || token[0] != '[')
    		elog(ERROR, "expected \"[\" to start datum, but got \"%s\"; length = %zu",
    			 token ? (const char *) token : "[NULL]", length);
    
    	if (typbyval)
    	{
    		if (length > (Size) sizeof(Datum))
    			elog(ERROR, "byval datum but length = %zu", length);
    		res = (Datum) 0;
    		s = (char *) (&res);
    		for (i = 0; i < (Size) sizeof(Datum); i++)
    		{
    			token = pg_strtok(&tokenLength);
    			s[i] = (char) atoi(token);
    		}
    	}
    	else if (length <= 0)
    		res = (Datum) NULL;
    	else
    	{
    		s = (char *) palloc(length);
    		for (i = 0; i < length; i++)
    		{
    			token = pg_strtok(&tokenLength);
    			s[i] = (char) atoi(token);
    		}
    		res = PointerGetDatum(s);
    	}
    
    	token = pg_strtok(&tokenLength);	/* read the ']' */
    	if (token == NULL || token[0] != ']')
    		elog(ERROR, "expected \"]\" to end datum, but got \"%s\"; length = %zu",
    			 token ? (const char *) token : "[NULL]", length);
    
    	return res;
    }
    
    /*
     * readAttrNumberCols
     */
    static 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
     */
    static 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
     */
    static 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
     */
    static 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;
    }