diff --git a/src/backend/nodes/gen_node_support.pl b/src/backend/nodes/gen_node_support.pl
index 4a7902e6bf..fc699c3f19 100644
--- a/src/backend/nodes/gen_node_support.pl
+++ b/src/backend/nodes/gen_node_support.pl
@@ -97,21 +97,19 @@ push @scalar_types, qw(QualCost);
 
 # XXX various things we are not publishing right now to stay level
 # with the manual system
-push @no_copy,  qw(CallContext InlineCodeBlock);
-push @no_equal, qw(CallContext InlineCodeBlock);
-push @no_read_write,
-  qw(AccessPriv AlterTableCmd CallContext CreateOpClassItem FunctionParameter InferClause InlineCodeBlock ObjectWithArgs OnConflictClause PartitionCmd RoleSpec VacuumRelation);
-push @no_read, qw(A_ArrayExpr A_Indices A_Indirection AlterStatsStmt
-  CollateClause ColumnDef ColumnRef CreateForeignTableStmt CreateStatsStmt
-  CreateStmt FuncCall ImportForeignSchemaStmt IndexElem IndexStmt
+push @no_copy,       qw(CallContext InlineCodeBlock);
+push @no_equal,      qw(CallContext InlineCodeBlock);
+push @no_read_write, qw(CallContext InlineCodeBlock);
+push @no_read,       qw(A_ArrayExpr A_Indices A_Indirection
+  CollateClause ColumnDef ColumnRef FuncCall IndexElem
   JsonAggConstructor JsonArgument JsonArrayAgg JsonArrayConstructor
   JsonArrayQueryConstructor JsonCommon JsonFuncExpr JsonKeyValue
   JsonObjectAgg JsonObjectConstructor JsonOutput JsonParseExpr JsonScalarExpr
   JsonSerializeExpr JsonTable JsonTableColumn JsonTablePlan LockingClause
-  MultiAssignRef PLAssignStmt ParamRef PartitionElem PartitionSpec
+  MultiAssignRef ParamRef PartitionElem PartitionSpec
   PlaceHolderVar PublicationObjSpec PublicationTable RangeFunction
-  RangeSubselect RangeTableFunc RangeTableFuncCol RangeTableSample RawStmt
-  ResTarget ReturnStmt SelectStmt SortBy StatsElem TableLikeClause
+  RangeSubselect RangeTableFunc RangeTableFuncCol RangeTableSample
+  ResTarget SortBy StatsElem TableLikeClause
   TriggerTransition TypeCast TypeName WindowDef WithClause XmlSerialize);
 
 
@@ -693,16 +691,16 @@ foreach my $n (@node_types)
 	next if elem $n, @abstract_types;
 	next if elem $n, @no_read_write;
 
-	# XXX For now, skip all "Stmt"s except that ones that were there before.
+	my $no_read = (elem $n, @no_read);
+
+	# Disable read support for utility statements.
+	# XXX this is a very ugly way to do it.
 	if ($n =~ /Stmt$/)
 	{
-		my @keep =
-		  qw(AlterStatsStmt CreateForeignTableStmt CreateStatsStmt CreateStmt DeclareCursorStmt ImportForeignSchemaStmt IndexStmt NotifyStmt PlannedStmt PLAssignStmt RawStmt ReturnStmt SelectStmt SetOperationStmt);
-		next unless elem $n, @keep;
+		my @keep = qw(NotifyStmt PlannedStmt SetOperationStmt);
+		$no_read = 1 unless elem $n, @keep;
 	}
 
-	my $no_read = (elem $n, @no_read);
-
 	# output format starts with upper case node type name
 	my $N = uc $n;
 
@@ -725,13 +723,20 @@ _out${n}(StringInfo str, const $n *node)
 
 ";
 
-	print $rff "
+	if (!$no_read)
+	{
+		my $macro =
+		  (@{ $node_type_info{$n}->{fields} } > 0)
+		  ? 'READ_LOCALS'
+		  : 'READ_LOCALS_NO_FIELDS';
+		print $rff "
 static $n *
 _read${n}(void)
 {
-\tREAD_LOCALS($n);
+\t$macro($n);
 
-" unless $no_read;
+";
+	}
 
 	# print instructions for each field
 	foreach my $f (@{ $node_type_info{$n}->{fields} })
@@ -781,6 +786,7 @@ _read${n}(void)
 			print $rff "\tREAD_LOCATION_FIELD($f);\n" unless $no_read;
 		}
 		elsif ($t eq 'int'
+			|| $t eq 'int16'
 			|| $t eq 'int32'
 			|| $t eq 'AttrNumber'
 			|| $t eq 'StrategyNumber')
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 4d776e7b51..85ac0b5e21 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -415,79 +415,6 @@ _outExtensibleNode(StringInfo str, const ExtensibleNode *node)
 	methods->nodeOut(str, node);
 }
 
-static void
-_outQuery(StringInfo str, const Query *node)
-{
-	WRITE_NODE_TYPE("QUERY");
-
-	WRITE_ENUM_FIELD(commandType, CmdType);
-	WRITE_ENUM_FIELD(querySource, QuerySource);
-	/* we intentionally do not print the queryId field */
-	WRITE_BOOL_FIELD(canSetTag);
-
-	/*
-	 * Hack to work around missing outfuncs routines for a lot of the
-	 * utility-statement node types.  (The only one we actually *need* for
-	 * rules support is NotifyStmt.)  Someday we ought to support 'em all, but
-	 * for the meantime do this to avoid getting lots of warnings when running
-	 * with debug_print_parse on.
-	 */
-	if (node->utilityStmt)
-	{
-		switch (nodeTag(node->utilityStmt))
-		{
-			case T_CreateStmt:
-			case T_IndexStmt:
-			case T_NotifyStmt:
-			case T_DeclareCursorStmt:
-				WRITE_NODE_FIELD(utilityStmt);
-				break;
-			default:
-				appendStringInfoString(str, " :utilityStmt ?");
-				break;
-		}
-	}
-	else
-		appendStringInfoString(str, " :utilityStmt <>");
-
-	WRITE_INT_FIELD(resultRelation);
-	WRITE_BOOL_FIELD(hasAggs);
-	WRITE_BOOL_FIELD(hasWindowFuncs);
-	WRITE_BOOL_FIELD(hasTargetSRFs);
-	WRITE_BOOL_FIELD(hasSubLinks);
-	WRITE_BOOL_FIELD(hasDistinctOn);
-	WRITE_BOOL_FIELD(hasRecursive);
-	WRITE_BOOL_FIELD(hasModifyingCTE);
-	WRITE_BOOL_FIELD(hasForUpdate);
-	WRITE_BOOL_FIELD(hasRowSecurity);
-	WRITE_BOOL_FIELD(isReturn);
-	WRITE_NODE_FIELD(cteList);
-	WRITE_NODE_FIELD(rtable);
-	WRITE_NODE_FIELD(jointree);
-	WRITE_NODE_FIELD(targetList);
-	WRITE_ENUM_FIELD(override, OverridingKind);
-	WRITE_NODE_FIELD(onConflict);
-	WRITE_NODE_FIELD(returningList);
-	WRITE_NODE_FIELD(groupClause);
-	WRITE_BOOL_FIELD(groupDistinct);
-	WRITE_NODE_FIELD(groupingSets);
-	WRITE_NODE_FIELD(havingQual);
-	WRITE_NODE_FIELD(windowClause);
-	WRITE_NODE_FIELD(distinctClause);
-	WRITE_NODE_FIELD(sortClause);
-	WRITE_NODE_FIELD(limitOffset);
-	WRITE_NODE_FIELD(limitCount);
-	WRITE_ENUM_FIELD(limitOption, LimitOption);
-	WRITE_NODE_FIELD(rowMarks);
-	WRITE_NODE_FIELD(setOperations);
-	WRITE_NODE_FIELD(constraintDeps);
-	WRITE_NODE_FIELD(withCheckOptions);
-	WRITE_NODE_FIELD(mergeActionList);
-	WRITE_BOOL_FIELD(mergeUseOuterJoin);
-	WRITE_LOCATION_FIELD(stmt_location);
-	WRITE_INT_FIELD(stmt_len);
-}
-
 static void
 _outRangeTblEntry(StringInfo str, const RangeTblEntry *node)
 {
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 1421686938..a2391280be 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -240,56 +240,6 @@ readBitmapset(void)
  * special_read_write attribute
  */
 
-static Query *
-_readQuery(void)
-{
-	READ_LOCALS(Query);
-
-	READ_ENUM_FIELD(commandType, CmdType);
-	READ_ENUM_FIELD(querySource, QuerySource);
-	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);
-	READ_BOOL_FIELD(hasModifyingCTE);
-	READ_BOOL_FIELD(hasForUpdate);
-	READ_BOOL_FIELD(hasRowSecurity);
-	READ_BOOL_FIELD(isReturn);
-	READ_NODE_FIELD(cteList);
-	READ_NODE_FIELD(rtable);
-	READ_NODE_FIELD(jointree);
-	READ_NODE_FIELD(targetList);
-	READ_ENUM_FIELD(override, OverridingKind);
-	READ_NODE_FIELD(onConflict);
-	READ_NODE_FIELD(returningList);
-	READ_NODE_FIELD(groupClause);
-	READ_BOOL_FIELD(groupDistinct);
-	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_ENUM_FIELD(limitOption, LimitOption);
-	READ_NODE_FIELD(rowMarks);
-	READ_NODE_FIELD(setOperations);
-	READ_NODE_FIELD(constraintDeps);
-	READ_NODE_FIELD(withCheckOptions);
-	READ_NODE_FIELD(mergeActionList);
-	READ_BOOL_FIELD(mergeUseOuterJoin);
-	READ_LOCATION_FIELD(stmt_location);
-	READ_INT_FIELD(stmt_len);
-
-	READ_DONE();
-}
-
 static Const *
 _readConst(void)
 {
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 0b6a7bb365..617ba619de 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -117,8 +117,6 @@ typedef uint32 AclMode;			/* a bitmask of privilege bits */
  */
 typedef struct Query
 {
-	pg_node_attr(custom_read_write)
-
 	NodeTag		type;
 
 	CmdType		commandType;	/* select|insert|update|delete|merge|utility */
@@ -126,10 +124,10 @@ typedef struct Query
 	QuerySource querySource;	/* where did I come from? */
 
 	/*
-	 * query identifier (can be set by plugins); ignored for equal, might not
-	 * be set
+	 * query identifier (can be set by plugins); ignored for equal, as it
+	 * might not be set; also not stored
 	 */
-	uint64		queryId pg_node_attr(equal_ignore, read_as(0));
+	uint64		queryId pg_node_attr(equal_ignore, read_write_ignore, read_as(0));
 
 	bool		canSetTag;		/* do I set the command result tag? */
 
