diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index d2a0e501d1e..30ae22e43df 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -1859,8 +1859,12 @@ ApplyRetrieveRule(Query *parsetree, rte->rtekind = RTE_SUBQUERY; rte->subquery = rule_action; rte->security_barrier = RelationIsSecurityView(relation); - /* Clear fields that should not be set in a subquery RTE */ - rte->relid = InvalidOid; + + /* + * Clear fields that should not be set in a subquery RTE. However, we + * retain the relid to support correct operation of makeWholeRowVar during + * planning. + */ rte->relkind = 0; rte->rellockmode = 0; rte->tablesample = NULL; diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 6944362c7ac..abc87c59e6f 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1017,6 +1017,12 @@ typedef struct RangeTblEntry /* * Fields valid for a plain relation RTE (else zero): * + * 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.) + * * 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 * relation. This allows plans referencing AFTER trigger transition