summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/nodes/makefuncs.c51
-rw-r--r--src/backend/optimizer/prep/prepjointree.c10
2 files changed, 57 insertions, 4 deletions
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 61ac172a857..9f3b4f200fb 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -159,6 +159,53 @@ makeWholeRowVar(RangeTblEntry *rte,
varlevelsup);
break;
+ case RTE_SUBQUERY:
+
+ /*
+ * For a standard subquery, the Var should be of RECORD type.
+ * However, if we're looking at a subquery that was expanded from
+ * a view or SRF (only possible during planning), we must use the
+ * appropriate rowtype, so that the resulting Var has the same
+ * type that we would have produced from the original RTE.
+ */
+ if (OidIsValid(rte->relid))
+ {
+ /* Subquery was expanded from a view */
+ toid = get_rel_type_id(rte->relid);
+ if (!OidIsValid(toid))
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("relation \"%s\" does not have a composite type",
+ get_rel_name(rte->relid))));
+ }
+ else if (rte->functions)
+ {
+ /*
+ * Subquery was expanded from a set-returning function. That
+ * would not have happened if there's more than one function
+ * or ordinality was requested. We also needn't worry about
+ * the allowScalar case, since the planner doesn't use that.
+ * Otherwise this must match the RTE_FUNCTION code below.
+ */
+ Assert(!allowScalar);
+ fexpr = ((RangeTblFunction *) linitial(rte->functions))->funcexpr;
+ toid = exprType(fexpr);
+ if (!type_is_rowtype(toid))
+ toid = RECORDOID;
+ }
+ else
+ {
+ /* Normal subquery-in-FROM */
+ toid = RECORDOID;
+ }
+ result = makeVar(varno,
+ InvalidAttrNumber,
+ toid,
+ -1,
+ InvalidOid,
+ varlevelsup);
+ break;
+
case RTE_FUNCTION:
/*
@@ -215,8 +262,8 @@ makeWholeRowVar(RangeTblEntry *rte,
default:
/*
- * RTE is a join, subselect, tablefunc, or VALUES. We represent
- * this as a whole-row Var of RECORD type. (Note that in most
+ * RTE is a join, tablefunc, VALUES, CTE, etc. We represent these
+ * cases as a whole-row Var of RECORD type. (Note that in most
* cases the Var will be expanded to a RowExpr during planning,
* but that is not our concern here.)
*/
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index e7e8c1499f2..2c6faad4dae 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -908,8 +908,14 @@ preprocess_function_rtes(PlannerInfo *root)
rte->rtekind = RTE_SUBQUERY;
rte->subquery = funcquery;
rte->security_barrier = false;
- /* Clear fields that should not be set in a subquery RTE */
- rte->functions = NIL;
+
+ /*
+ * Clear fields that should not be set in a subquery RTE.
+ * However, we leave rte->functions filled in for the moment,
+ * in case makeWholeRowVar needs to consult it. We'll clear
+ * it in setrefs.c (see add_rte_to_flat_rtable) so that this
+ * abuse of the data structure doesn't escape the planner.
+ */
rte->funcordinality = false;
}
}