diff --git a/src/backend/nodes/read.c b/src/backend/nodes/read.c
index 5af15c2..d0157d0 100644
--- a/src/backend/nodes/read.c
+++ b/src/backend/nodes/read.c
@@ -50,7 +50,7 @@ stringToNode(char *str)
 
 	pg_strtok_ptr = str;		/* point pg_strtok at the string to read */
 
-	retval = nodeRead(NULL, 0); /* do the reading */
+	retval = nodeRead(NULL, 0, 0); /* do the reading */
 
 	pg_strtok_ptr = save_strtok;
 
@@ -266,15 +266,18 @@ nodeTokenType(char *token, int length)
  * The return value is declared void *, not Node *, to avoid having to
  * cast it explicitly in callers that assign to fields of different types.
  *
- * External callers should always pass NULL/0 for the arguments.  Internally
+ * External callers should always pass NULL/0 for the token/tok_lenarguments.  Internally
  * a non-NULL token may be passed when the upper recursion level has already
  * scanned the first token of a node's representation.
  *
+ * If expectedType is non-zero, the node must of the given type, or an error
+ * is thrown.
+ *
  * We assume pg_strtok is already initialized with a string to read (hence
  * this should only be invoked from within a stringToNode operation).
  */
 void *
-nodeRead(char *token, int tok_len)
+nodeRead(char *token, int tok_len, int expectedType)
 {
 	Node	   *result;
 	NodeTag		type;
@@ -358,7 +361,7 @@ nodeRead(char *token, int tok_len)
 						/* We have already scanned next token... */
 						if (token[0] == ')')
 							break;
-						l = lappend(l, nodeRead(token, tok_len));
+						l = lappend(l, nodeRead(token, tok_len, 0));
 						token = pg_strtok(&tok_len);
 						if (token == NULL)
 							elog(ERROR, "unterminated List structure");
@@ -419,5 +422,9 @@ nodeRead(char *token, int tok_len)
 			break;
 	}
 
+	if (expectedType != 0 && nodeTag(result) != expectedType)
+		elog(ERROR, "node type %d found, expected %d",
+			 nodeTag(result), expectedType);
+
 	return (void *) result;
 }
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index bc6e2a6..cb814fd 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -57,66 +57,90 @@
 
 /* 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 */ \
+	token = pg_strtok_e(&length);		/* skip :fldname */ \
+	token = pg_strtok_e(&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 */ \
+	token = pg_strtok_e(&length);		/* skip :fldname */ \
+	token = pg_strtok_e(&length);		/* get field value */ \
 	local_node->fldname = atoui(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 */ \
+	token = pg_strtok_e(&length);		/* skip :fldname */ \
+	token = pg_strtok_e(&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 */ \
+	token = pg_strtok_e(&length);		/* skip :fldname */ \
+	token = pg_strtok_e(&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 */ \
+	token = pg_strtok_e(&length);		/* skip :fldname */ \
+	token = pg_strtok_e(&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 */ \
+	token = pg_strtok_e(&length);		/* skip :fldname */ \
+	token = pg_strtok_e(&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 */ \
+	token = pg_strtok_e(&length);		/* skip :fldname */ \
+	token = pg_strtok_e(&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 */ \
+	token = pg_strtok_e(&length);		/* skip :fldname */ \
+	token = pg_strtok_e(&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 */ \
+	token = pg_strtok_e(&length);		/* skip :fldname */ \
+	token = pg_strtok_e(&length);		/* get field value */ \
 	local_node->fldname = -1	/* set field to "unknown" */
 
 /* Read a Node field */
-#define READ_NODE_FIELD(fldname) \
-	token = pg_strtok(&length);		/* skip :fldname */ \
-	local_node->fldname = nodeRead(NULL, 0)
+#define READ_NODE_FIELD(fldname, type) \
+	token = pg_strtok_e(&length);		/* skip :fldname */ \
+	local_node->fldname = (type *) nodeRead(NULL, 0, T_##type)
+
+/* Read a Node field */
+#define READ_ANY_NODE_FIELD(fldname) \
+	token = pg_strtok_e(&length);		/* skip :fldname */ \
+	local_node->fldname = nodeRead(NULL, 0, 0)
+
+/* Read a List field */
+#define READ_LIST_FIELD(fldname, type)							\
+	token = pg_strtok_e(&length);		/* skip :fldname */ \
+	local_node->fldname = readList(T_##type)
+
+#define READ_ANY_LIST_FIELD(fldname)							\
+	token = pg_strtok_e(&length);		/* skip :fldname */ \
+	local_node->fldname = (List *) nodeRead(NULL, 0, T_List);
+
+/* Read a IntList field */
+#define READ_INT_LIST_FIELD(fldname) \
+	token = pg_strtok_e(&length);		/* skip :fldname */ \
+	local_node->fldname = nodeRead(NULL, 0, T_IntList)
+
+/* Read a OidList field */
+#define READ_OID_LIST_FIELD(fldname)						\
+	token = pg_strtok_e(&length);		/* skip :fldname */ \
+	local_node->fldname = nodeRead(NULL, 0, T_OidList)
 
 /* Read a bitmapset field */
 #define READ_BITMAPSET_FIELD(fldname) \
-	token = pg_strtok(&length);		/* skip :fldname */ \
+	token = pg_strtok_e(&length);		/* skip :fldname */ \
 	local_node->fldname = _readBitmapset()
 
 /* Routine exit */
@@ -139,8 +163,21 @@
 #define nullable_string(token,length)  \
 	((length) == 0 ? NULL : debackslash(token, length))
 
-
 static Datum readDatum(bool typbyval);
+static List *readList(int elemtype);
+static char *pg_strtok_e(int *length);
+
+/*
+ * Like pg_strtok(), but throws an error on end of string
+ */
+static char *
+pg_strtok_e(int *length)
+{
+	char *token = pg_strtok(length);
+	if (token == NULL)
+		elog(ERROR, "unexpected end of string while reading tree node");
+	return token;
+}
 
 /*
  * _readBitmapset
@@ -195,29 +232,29 @@ _readQuery(void)
 	READ_ENUM_FIELD(commandType, CmdType);
 	READ_ENUM_FIELD(querySource, QuerySource);
 	READ_BOOL_FIELD(canSetTag);
-	READ_NODE_FIELD(utilityStmt);
+	READ_ANY_NODE_FIELD(utilityStmt);
 	READ_INT_FIELD(resultRelation);
-	READ_NODE_FIELD(intoClause);
+	READ_NODE_FIELD(intoClause, IntoClause);
 	READ_BOOL_FIELD(hasAggs);
 	READ_BOOL_FIELD(hasWindowFuncs);
 	READ_BOOL_FIELD(hasSubLinks);
 	READ_BOOL_FIELD(hasDistinctOn);
 	READ_BOOL_FIELD(hasRecursive);
 	READ_BOOL_FIELD(hasForUpdate);
-	READ_NODE_FIELD(cteList);
-	READ_NODE_FIELD(rtable);
-	READ_NODE_FIELD(jointree);
-	READ_NODE_FIELD(targetList);
-	READ_NODE_FIELD(returningList);
-	READ_NODE_FIELD(groupClause);
-	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_LIST_FIELD(cteList, CommonTableExpr);
+	READ_LIST_FIELD(rtable, RangeTblEntry);
+	READ_NODE_FIELD(jointree, FromExpr);
+	READ_LIST_FIELD(targetList, TargetEntry);
+	READ_LIST_FIELD(returningList, TargetEntry);
+	READ_LIST_FIELD(groupClause, SortGroupClause);
+	READ_ANY_NODE_FIELD(havingQual);
+	READ_LIST_FIELD(windowClause, WindowClause);
+	READ_LIST_FIELD(distinctClause, SortGroupClause);
+	READ_LIST_FIELD(sortClause, SortGroupClause);
+	READ_ANY_NODE_FIELD(limitOffset);
+	READ_ANY_NODE_FIELD(limitCount);
+	READ_LIST_FIELD(rowMarks, RowMarkClause);
+	READ_ANY_NODE_FIELD(setOperations);
 
 	READ_DONE();
 }
@@ -246,7 +283,7 @@ _readDeclareCursorStmt(void)
 
 	READ_STRING_FIELD(portalname);
 	READ_INT_FIELD(options);
-	READ_NODE_FIELD(query);
+	READ_ANY_NODE_FIELD(query);
 
 	READ_DONE();
 }
@@ -277,11 +314,11 @@ _readWindowClause(void)
 
 	READ_STRING_FIELD(name);
 	READ_STRING_FIELD(refname);
-	READ_NODE_FIELD(partitionClause);
-	READ_NODE_FIELD(orderClause);
+	READ_LIST_FIELD(partitionClause, SortGroupClause);
+	READ_LIST_FIELD(orderClause, SortGroupClause);
 	READ_INT_FIELD(frameOptions);
-	READ_NODE_FIELD(startOffset);
-	READ_NODE_FIELD(endOffset);
+	READ_ANY_NODE_FIELD(startOffset);
+	READ_ANY_NODE_FIELD(endOffset);
 	READ_UINT_FIELD(winref);
 	READ_BOOL_FIELD(copiedOrder);
 
@@ -313,14 +350,14 @@ _readCommonTableExpr(void)
 	READ_LOCALS(CommonTableExpr);
 
 	READ_STRING_FIELD(ctename);
-	READ_NODE_FIELD(aliascolnames);
-	READ_NODE_FIELD(ctequery);
+	READ_LIST_FIELD(aliascolnames, String);
+	READ_ANY_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_LIST_FIELD(ctecolnames, String);
+	READ_OID_LIST_FIELD(ctecoltypes);
+	READ_INT_LIST_FIELD(ctecoltypmods);
 
 	READ_DONE();
 }
@@ -335,11 +372,11 @@ _readSetOperationStmt(void)
 
 	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(groupClauses);
+	READ_ANY_NODE_FIELD(larg);
+	READ_ANY_NODE_FIELD(rarg);
+	READ_OID_LIST_FIELD(colTypes);
+	READ_INT_LIST_FIELD(colTypmods);
+	READ_LIST_FIELD(groupClauses, SortGroupClause);
 
 	READ_DONE();
 }
@@ -355,7 +392,7 @@ _readAlias(void)
 	READ_LOCALS(Alias);
 
 	READ_STRING_FIELD(aliasname);
-	READ_NODE_FIELD(colnames);
+	READ_LIST_FIELD(colnames, String);
 
 	READ_DONE();
 }
@@ -372,7 +409,7 @@ _readRangeVar(void)
 	READ_STRING_FIELD(relname);
 	READ_ENUM_FIELD(inhOpt, InhOption);
 	READ_BOOL_FIELD(istemp);
-	READ_NODE_FIELD(alias);
+	READ_NODE_FIELD(alias, Alias);
 	READ_LOCATION_FIELD(location);
 
 	READ_DONE();
@@ -383,9 +420,9 @@ _readIntoClause(void)
 {
 	READ_LOCALS(IntoClause);
 
-	READ_NODE_FIELD(rel);
-	READ_NODE_FIELD(colNames);
-	READ_NODE_FIELD(options);
+	READ_NODE_FIELD(rel, RangeVar);
+	READ_LIST_FIELD(colNames, ColumnDef);
+	READ_LIST_FIELD(options, DefElem);
 	READ_ENUM_FIELD(onCommit, OnCommitAction);
 	READ_STRING_FIELD(tableSpaceName);
 
@@ -463,9 +500,9 @@ _readAggref(void)
 
 	READ_OID_FIELD(aggfnoid);
 	READ_OID_FIELD(aggtype);
-	READ_NODE_FIELD(args);
-	READ_NODE_FIELD(aggorder);
-	READ_NODE_FIELD(aggdistinct);
+	READ_LIST_FIELD(args, TargetEntry);
+	READ_LIST_FIELD(aggorder, SortGroupClause);
+	READ_LIST_FIELD(aggdistinct, SortGroupClause);
 	READ_BOOL_FIELD(aggstar);
 	READ_UINT_FIELD(agglevelsup);
 	READ_LOCATION_FIELD(location);
@@ -483,7 +520,7 @@ _readWindowFunc(void)
 
 	READ_OID_FIELD(winfnoid);
 	READ_OID_FIELD(wintype);
-	READ_NODE_FIELD(args);
+	READ_ANY_LIST_FIELD(args);
 	READ_UINT_FIELD(winref);
 	READ_BOOL_FIELD(winstar);
 	READ_BOOL_FIELD(winagg);
@@ -503,10 +540,10 @@ _readArrayRef(void)
 	READ_OID_FIELD(refarraytype);
 	READ_OID_FIELD(refelemtype);
 	READ_INT_FIELD(reftypmod);
-	READ_NODE_FIELD(refupperindexpr);
-	READ_NODE_FIELD(reflowerindexpr);
-	READ_NODE_FIELD(refexpr);
-	READ_NODE_FIELD(refassgnexpr);
+	READ_ANY_LIST_FIELD(refupperindexpr);
+	READ_ANY_LIST_FIELD(reflowerindexpr);
+	READ_ANY_NODE_FIELD(refexpr);
+	READ_ANY_NODE_FIELD(refassgnexpr);
 
 	READ_DONE();
 }
@@ -523,7 +560,7 @@ _readFuncExpr(void)
 	READ_OID_FIELD(funcresulttype);
 	READ_BOOL_FIELD(funcretset);
 	READ_ENUM_FIELD(funcformat, CoercionForm);
-	READ_NODE_FIELD(args);
+	READ_ANY_LIST_FIELD(args);
 	READ_LOCATION_FIELD(location);
 
 	READ_DONE();
@@ -537,7 +574,7 @@ _readNamedArgExpr(void)
 {
 	READ_LOCALS(NamedArgExpr);
 
-	READ_NODE_FIELD(arg);
+	READ_ANY_NODE_FIELD(arg);
 	READ_STRING_FIELD(name);
 	READ_INT_FIELD(argnumber);
 	READ_LOCATION_FIELD(location);
@@ -568,7 +605,7 @@ _readOpExpr(void)
 
 	READ_OID_FIELD(opresulttype);
 	READ_BOOL_FIELD(opretset);
-	READ_NODE_FIELD(args);
+	READ_ANY_LIST_FIELD(args);
 	READ_LOCATION_FIELD(location);
 
 	READ_DONE();
@@ -597,7 +634,7 @@ _readDistinctExpr(void)
 
 	READ_OID_FIELD(opresulttype);
 	READ_BOOL_FIELD(opretset);
-	READ_NODE_FIELD(args);
+	READ_ANY_LIST_FIELD(args);
 	READ_LOCATION_FIELD(location);
 
 	READ_DONE();
@@ -625,7 +662,7 @@ _readScalarArrayOpExpr(void)
 	local_node->opfuncid = InvalidOid;
 
 	READ_BOOL_FIELD(useOr);
-	READ_NODE_FIELD(args);
+	READ_ANY_LIST_FIELD(args);
 	READ_LOCATION_FIELD(location);
 
 	READ_DONE();
@@ -640,8 +677,8 @@ _readBoolExpr(void)
 	READ_LOCALS(BoolExpr);
 
 	/* do-it-yourself enum representation */
-	token = pg_strtok(&length); /* skip :boolop */
-	token = pg_strtok(&length); /* get field value */
+	token = pg_strtok_e(&length); /* skip :boolop */
+	token = pg_strtok_e(&length); /* get field value */
 	if (strncmp(token, "and", 3) == 0)
 		local_node->boolop = AND_EXPR;
 	else if (strncmp(token, "or", 2) == 0)
@@ -651,7 +688,7 @@ _readBoolExpr(void)
 	else
 		elog(ERROR, "unrecognized boolop \"%.*s\"", length, token);
 
-	READ_NODE_FIELD(args);
+	READ_ANY_LIST_FIELD(args);
 	READ_LOCATION_FIELD(location);
 
 	READ_DONE();
@@ -666,9 +703,9 @@ _readSubLink(void)
 	READ_LOCALS(SubLink);
 
 	READ_ENUM_FIELD(subLinkType, SubLinkType);
-	READ_NODE_FIELD(testexpr);
-	READ_NODE_FIELD(operName);
-	READ_NODE_FIELD(subselect);
+	READ_ANY_NODE_FIELD(testexpr);
+	READ_LIST_FIELD(operName, String);
+	READ_ANY_NODE_FIELD(subselect);
 	READ_LOCATION_FIELD(location);
 
 	READ_DONE();
@@ -686,7 +723,7 @@ _readFieldSelect(void)
 {
 	READ_LOCALS(FieldSelect);
 
-	READ_NODE_FIELD(arg);
+	READ_ANY_NODE_FIELD(arg);
 	READ_INT_FIELD(fieldnum);
 	READ_OID_FIELD(resulttype);
 	READ_INT_FIELD(resulttypmod);
@@ -702,9 +739,9 @@ _readFieldStore(void)
 {
 	READ_LOCALS(FieldStore);
 
-	READ_NODE_FIELD(arg);
-	READ_NODE_FIELD(newvals);
-	READ_NODE_FIELD(fieldnums);
+	READ_ANY_NODE_FIELD(arg);
+	READ_ANY_LIST_FIELD(newvals);
+	READ_INT_LIST_FIELD(fieldnums);
 	READ_OID_FIELD(resulttype);
 
 	READ_DONE();
@@ -718,7 +755,7 @@ _readRelabelType(void)
 {
 	READ_LOCALS(RelabelType);
 
-	READ_NODE_FIELD(arg);
+	READ_ANY_NODE_FIELD(arg);
 	READ_OID_FIELD(resulttype);
 	READ_INT_FIELD(resulttypmod);
 	READ_ENUM_FIELD(relabelformat, CoercionForm);
@@ -735,7 +772,7 @@ _readCoerceViaIO(void)
 {
 	READ_LOCALS(CoerceViaIO);
 
-	READ_NODE_FIELD(arg);
+	READ_ANY_NODE_FIELD(arg);
 	READ_OID_FIELD(resulttype);
 	READ_ENUM_FIELD(coerceformat, CoercionForm);
 	READ_LOCATION_FIELD(location);
@@ -751,7 +788,7 @@ _readArrayCoerceExpr(void)
 {
 	READ_LOCALS(ArrayCoerceExpr);
 
-	READ_NODE_FIELD(arg);
+	READ_ANY_NODE_FIELD(arg);
 	READ_OID_FIELD(elemfuncid);
 	READ_OID_FIELD(resulttype);
 	READ_INT_FIELD(resulttypmod);
@@ -770,7 +807,7 @@ _readConvertRowtypeExpr(void)
 {
 	READ_LOCALS(ConvertRowtypeExpr);
 
-	READ_NODE_FIELD(arg);
+	READ_ANY_NODE_FIELD(arg);
 	READ_OID_FIELD(resulttype);
 	READ_ENUM_FIELD(convertformat, CoercionForm);
 	READ_LOCATION_FIELD(location);
@@ -787,9 +824,9 @@ _readCaseExpr(void)
 	READ_LOCALS(CaseExpr);
 
 	READ_OID_FIELD(casetype);
-	READ_NODE_FIELD(arg);
-	READ_NODE_FIELD(args);
-	READ_NODE_FIELD(defresult);
+	READ_ANY_NODE_FIELD(arg);
+	READ_LIST_FIELD(args, CaseWhen);
+	READ_ANY_NODE_FIELD(defresult);
 	READ_LOCATION_FIELD(location);
 
 	READ_DONE();
@@ -803,8 +840,8 @@ _readCaseWhen(void)
 {
 	READ_LOCALS(CaseWhen);
 
-	READ_NODE_FIELD(expr);
-	READ_NODE_FIELD(result);
+	READ_ANY_NODE_FIELD(expr);
+	READ_ANY_NODE_FIELD(result);
 	READ_LOCATION_FIELD(location);
 
 	READ_DONE();
@@ -834,7 +871,7 @@ _readArrayExpr(void)
 
 	READ_OID_FIELD(array_typeid);
 	READ_OID_FIELD(element_typeid);
-	READ_NODE_FIELD(elements);
+	READ_ANY_LIST_FIELD(elements);
 	READ_BOOL_FIELD(multidims);
 	READ_LOCATION_FIELD(location);
 
@@ -849,10 +886,10 @@ _readRowExpr(void)
 {
 	READ_LOCALS(RowExpr);
 
-	READ_NODE_FIELD(args);
+	READ_ANY_LIST_FIELD(args);
 	READ_OID_FIELD(row_typeid);
 	READ_ENUM_FIELD(row_format, CoercionForm);
-	READ_NODE_FIELD(colnames);
+	READ_LIST_FIELD(colnames, String);
 	READ_LOCATION_FIELD(location);
 
 	READ_DONE();
@@ -867,10 +904,10 @@ _readRowCompareExpr(void)
 	READ_LOCALS(RowCompareExpr);
 
 	READ_ENUM_FIELD(rctype, RowCompareType);
-	READ_NODE_FIELD(opnos);
-	READ_NODE_FIELD(opfamilies);
-	READ_NODE_FIELD(largs);
-	READ_NODE_FIELD(rargs);
+	READ_OID_LIST_FIELD(opnos);
+	READ_OID_LIST_FIELD(opfamilies);
+	READ_ANY_LIST_FIELD(largs);
+	READ_ANY_LIST_FIELD(rargs);
 
 	READ_DONE();
 }
@@ -884,7 +921,7 @@ _readCoalesceExpr(void)
 	READ_LOCALS(CoalesceExpr);
 
 	READ_OID_FIELD(coalescetype);
-	READ_NODE_FIELD(args);
+	READ_ANY_LIST_FIELD(args);
 	READ_LOCATION_FIELD(location);
 
 	READ_DONE();
@@ -900,7 +937,7 @@ _readMinMaxExpr(void)
 
 	READ_OID_FIELD(minmaxtype);
 	READ_ENUM_FIELD(op, MinMaxOp);
-	READ_NODE_FIELD(args);
+	READ_ANY_LIST_FIELD(args);
 	READ_LOCATION_FIELD(location);
 
 	READ_DONE();
@@ -916,9 +953,9 @@ _readXmlExpr(void)
 
 	READ_ENUM_FIELD(op, XmlExprOp);
 	READ_STRING_FIELD(name);
-	READ_NODE_FIELD(named_args);
-	READ_NODE_FIELD(arg_names);
-	READ_NODE_FIELD(args);
+	READ_ANY_LIST_FIELD(named_args);
+	READ_LIST_FIELD(arg_names, String);
+	READ_ANY_LIST_FIELD(args);
 	READ_ENUM_FIELD(xmloption, XmlOptionType);
 	READ_OID_FIELD(type);
 	READ_INT_FIELD(typmod);
@@ -950,7 +987,7 @@ _readNullIfExpr(void)
 
 	READ_OID_FIELD(opresulttype);
 	READ_BOOL_FIELD(opretset);
-	READ_NODE_FIELD(args);
+	READ_ANY_LIST_FIELD(args);
 	READ_LOCATION_FIELD(location);
 
 	READ_DONE();
@@ -964,7 +1001,7 @@ _readNullTest(void)
 {
 	READ_LOCALS(NullTest);
 
-	READ_NODE_FIELD(arg);
+	READ_ANY_NODE_FIELD(arg);
 	READ_ENUM_FIELD(nulltesttype, NullTestType);
 	READ_BOOL_FIELD(argisrow);
 
@@ -979,7 +1016,7 @@ _readBooleanTest(void)
 {
 	READ_LOCALS(BooleanTest);
 
-	READ_NODE_FIELD(arg);
+	READ_ANY_NODE_FIELD(arg);
 	READ_ENUM_FIELD(booltesttype, BoolTestType);
 
 	READ_DONE();
@@ -993,7 +1030,7 @@ _readCoerceToDomain(void)
 {
 	READ_LOCALS(CoerceToDomain);
 
-	READ_NODE_FIELD(arg);
+	READ_ANY_NODE_FIELD(arg);
 	READ_OID_FIELD(resulttype);
 	READ_INT_FIELD(resulttypmod);
 	READ_ENUM_FIELD(coercionformat, CoercionForm);
@@ -1055,7 +1092,7 @@ _readTargetEntry(void)
 {
 	READ_LOCALS(TargetEntry);
 
-	READ_NODE_FIELD(expr);
+	READ_ANY_NODE_FIELD(expr);
 	READ_INT_FIELD(resno);
 	READ_STRING_FIELD(resname);
 	READ_UINT_FIELD(ressortgroupref);
@@ -1089,11 +1126,11 @@ _readJoinExpr(void)
 
 	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_ANY_NODE_FIELD(larg);
+	READ_ANY_NODE_FIELD(rarg);
+	READ_LIST_FIELD(usingClause, String);
+	READ_ANY_NODE_FIELD(quals);
+	READ_NODE_FIELD(alias, Alias);
 	READ_INT_FIELD(rtindex);
 
 	READ_DONE();
@@ -1107,8 +1144,8 @@ _readFromExpr(void)
 {
 	READ_LOCALS(FromExpr);
 
-	READ_NODE_FIELD(fromlist);
-	READ_NODE_FIELD(quals);
+	READ_ANY_LIST_FIELD(fromlist);
+	READ_ANY_NODE_FIELD(quals);
 
 	READ_DONE();
 }
@@ -1127,8 +1164,8 @@ _readRangeTblEntry(void)
 	READ_LOCALS(RangeTblEntry);
 
 	/* put alias + eref first to make dump more legible */
-	READ_NODE_FIELD(alias);
-	READ_NODE_FIELD(eref);
+	READ_NODE_FIELD(alias, Alias);
+	READ_NODE_FIELD(eref, Alias);
 	READ_ENUM_FIELD(rtekind, RTEKind);
 
 	switch (local_node->rtekind)
@@ -1138,26 +1175,26 @@ _readRangeTblEntry(void)
 			READ_OID_FIELD(relid);
 			break;
 		case RTE_SUBQUERY:
-			READ_NODE_FIELD(subquery);
+			READ_NODE_FIELD(subquery, Query);
 			break;
 		case RTE_JOIN:
 			READ_ENUM_FIELD(jointype, JoinType);
-			READ_NODE_FIELD(joinaliasvars);
+			READ_ANY_LIST_FIELD(joinaliasvars);
 			break;
 		case RTE_FUNCTION:
-			READ_NODE_FIELD(funcexpr);
-			READ_NODE_FIELD(funccoltypes);
-			READ_NODE_FIELD(funccoltypmods);
+			READ_ANY_NODE_FIELD(funcexpr);
+			READ_OID_LIST_FIELD(funccoltypes);
+			READ_INT_LIST_FIELD(funccoltypmods);
 			break;
 		case RTE_VALUES:
-			READ_NODE_FIELD(values_lists);
+			READ_LIST_FIELD(values_lists, List);
 			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_OID_LIST_FIELD(ctecoltypes);
+			READ_INT_LIST_FIELD(ctecoltypmods);
 			break;
 		default:
 			elog(ERROR, "unrecognized RTE kind: %d",
@@ -1191,7 +1228,7 @@ parseNodeString(void)
 
 	READ_TEMP_LOCALS();
 
-	token = pg_strtok(&length);
+	token = pg_strtok_e(&length);
 
 #define MATCH(tokname, namelen) \
 	(length == namelen && strncmp(token, tokname, namelen) == 0)
@@ -1328,7 +1365,7 @@ readDatum(bool typbyval)
 	/*
 	 * read the actual length of the value
 	 */
-	token = pg_strtok(&tokenLength);
+	token = pg_strtok_e(&tokenLength);
 	length = atoui(token);
 
 	token = pg_strtok(&tokenLength);	/* read the '[' */
@@ -1346,7 +1383,7 @@ readDatum(bool typbyval)
 		s = (char *) (&res);
 		for (i = 0; i < (Size) sizeof(Datum); i++)
 		{
-			token = pg_strtok(&tokenLength);
+			token = pg_strtok_e(&tokenLength);
 			s[i] = (char) atoi(token);
 		}
 	}
@@ -1357,7 +1394,7 @@ readDatum(bool typbyval)
 		s = (char *) palloc(length);
 		for (i = 0; i < length; i++)
 		{
-			token = pg_strtok(&tokenLength);
+			token = pg_strtok_e(&tokenLength);
 			s[i] = (char) atoi(token);
 		}
 		res = PointerGetDatum(s);
@@ -1371,3 +1408,21 @@ readDatum(bool typbyval)
 
 	return res;
 }
+
+/*
+ * Reads a node list, and checks that all elements are of the given type.
+ */
+static List *
+readList(int elemtype)
+{
+	List *l = (List *) nodeRead(NULL, 0, T_List);
+	ListCell *lc;
+
+	foreach(lc, l)
+	{
+		if (nodeTag(lfirst(lc)) != elemtype)
+			elog(ERROR, "element type %d found in List, expected %d",
+				 nodeTag(lfirst(lc)), elemtype);
+	}
+	return l;
+}
diff --git a/src/include/nodes/readfuncs.h b/src/include/nodes/readfuncs.h
index f373b32..03f75aa 100644
--- a/src/include/nodes/readfuncs.h
+++ b/src/include/nodes/readfuncs.h
@@ -21,7 +21,7 @@
  */
 extern char *pg_strtok(int *length);
 extern char *debackslash(char *token, int length);
-extern void *nodeRead(char *token, int tok_len);
+extern void *nodeRead(char *token, int tok_len, int expectedType);
 
 /*
  * prototypes for functions in readfuncs.c
