diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 4d05d59c5bd..59387c21b51 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -512,6 +512,15 @@ add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte)
 	newrte->colcollations = NIL;
 	newrte->securityQuals = NIL;
 
+	/*
+	 * Also, if it's a subquery RTE, lose the relid that may have been kept to
+	 * signal that it had been a view.  We don't want that to escape the
+	 * planner, mainly because doing so breaks -DWRITE_READ_PARSE_PLAN_TREES
+	 * testing thanks to outfuncs/readfuncs not preserving it.
+	 */
+	if (newrte->rtekind == RTE_SUBQUERY)
+		newrte->relid = InvalidOid;
+
 	glob->finalrtable = lappend(glob->finalrtable, newrte);
 
 	/*
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 30ae22e43df..aa0a3bfe89b 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -1862,8 +1862,8 @@ ApplyRetrieveRule(Query *parsetree,
 
 	/*
 	 * Clear fields that should not be set in a subquery RTE.  However, we
-	 * retain the relid to support correct operation of makeWholeRowVar during
-	 * planning.
+	 * retain the relid for now, to support correct operation of
+	 * makeWholeRowVar during planning.
 	 */
 	rte->relkind = 0;
 	rte->rellockmode = 0;
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 8a464fcf150..a6a13dc71ba 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -813,45 +813,10 @@ pg_rewrite_query(Query *query)
 	}
 #endif
 
-#ifdef WRITE_READ_PARSE_PLAN_TREES
-	/* Optional debugging check: pass querytree through outfuncs/readfuncs */
-	{
-		List	   *new_list = NIL;
-		ListCell   *lc;
-
-		/*
-		 * We currently lack outfuncs/readfuncs support for most utility
-		 * statement types, so only attempt to write/read non-utility queries.
-		 */
-		foreach(lc, querytree_list)
-		{
-			Query	   *query = lfirst_node(Query, lc);
-
-			if (query->commandType != CMD_UTILITY)
-			{
-				char	   *str = nodeToString(query);
-				Query	   *new_query = stringToNodeWithLocations(str);
-
-				/*
-				 * queryId is not saved in stored rules, but we must preserve
-				 * it here to avoid breaking pg_stat_statements.
-				 */
-				new_query->queryId = query->queryId;
-
-				new_list = lappend(new_list, new_query);
-				pfree(str);
-			}
-			else
-				new_list = lappend(new_list, query);
-		}
-
-		/* This checks both outfuncs/readfuncs and the equal() routines... */
-		if (!equal(new_list, querytree_list))
-			elog(WARNING, "outfuncs/readfuncs failed to produce equal parse tree");
-		else
-			querytree_list = new_list;
-	}
-#endif
+	/*
+	 * We don't apply WRITE_READ_PARSE_PLAN_TREES to rewritten query trees,
+	 * because it breaks the hack of preserving relid for rewritten views.
+	 */
 
 	if (Debug_print_rewritten)
 		elog_node_display(LOG, "rewritten parse tree", querytree_list,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index abc87c59e6f..a77b5ba1b14 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1020,8 +1020,8 @@ typedef struct RangeTblEntry
 	 * As a special case, relid can also be set in RTE_SUBQUERY RTEs.  This
 	 * happens when an RTE_RELATION RTE for a view is transformed to an
 	 * RTE_SUBQUERY during rewriting.  We keep the relid because it is useful
-	 * during planning, cf makeWholeRowVar.  (It cannot be relied on during
-	 * execution, because it will not propagate to parallel workers.)
+	 * during planning, cf makeWholeRowVar.  (It will not be passed on to the
+	 * executor, however.)
 	 *
 	 * As a special case, RTE_NAMEDTUPLESTORE can also set relid to indicate
 	 * that the tuple format of the tuplestore is the same as the referenced
