@@ -1203,14 +1203,12 @@ replace_rte_variables_mutator(Node *node,
12031203 * appear in the expression.
12041204 *
12051205 * If the expression tree contains a whole-row Var for the target RTE,
1206- * the Var is not changed but *found_whole_row is returned as TRUE.
1207- * For most callers this is an error condition, but we leave it to the caller
1208- * to report the error so that useful context can be provided. (In some
1209- * usages it would be appropriate to modify the Var's vartype and insert a
1210- * ConvertRowtypeExpr node to map back to the original vartype. We might
1211- * someday extend this function's API to support that. For now, the only
1212- * concession to that future need is that this function is a tree mutator
1213- * not just a walker.)
1206+ * *found_whole_row is returned as TRUE. In addition, if to_rowtype is
1207+ * not InvalidOid, we modify the Var's vartype and insert a ConvertRowTypeExpr
1208+ * to map back to the orignal rowtype. Callers that don't provide to_rowtype
1209+ * should report an error if *found_row_type is true; we don't do that here
1210+ * because we don't know exactly what wording for the error message would
1211+ * be most appropriate. The caller will be aware of the context.
12141212 *
12151213 * This could be built using replace_rte_variables and a callback function,
12161214 * but since we don't ever need to insert sublinks, replace_rte_variables is
@@ -1223,6 +1221,8 @@ typedef struct
12231221 int sublevels_up ; /* (current) nesting depth */
12241222 const AttrNumber * attno_map ; /* map array for user attnos */
12251223 int map_length ; /* number of entries in attno_map[] */
1224+ /* Target type when converting whole-row vars */
1225+ Oid to_rowtype ;
12261226 bool * found_whole_row ; /* output flag */
12271227} map_variable_attnos_context ;
12281228
@@ -1257,6 +1257,34 @@ map_variable_attnos_mutator(Node *node,
12571257 {
12581258 /* whole-row variable, warn caller */
12591259 * (context -> found_whole_row ) = true;
1260+
1261+ /* If the callers expects us to convert the same, do so. */
1262+ if (OidIsValid (context -> to_rowtype ))
1263+ {
1264+ /* No support for RECORDOID. */
1265+ Assert (var -> vartype != RECORDOID );
1266+
1267+ /* Don't convert unless necessary. */
1268+ if (context -> to_rowtype != var -> vartype )
1269+ {
1270+ ConvertRowtypeExpr * r ;
1271+
1272+ /* Var itself is converted to the requested type. */
1273+ newvar -> vartype = context -> to_rowtype ;
1274+
1275+ /*
1276+ * And a conversion node on top to convert back to the
1277+ * original type.
1278+ */
1279+ r = makeNode (ConvertRowtypeExpr );
1280+ r -> arg = (Expr * ) newvar ;
1281+ r -> resulttype = var -> vartype ;
1282+ r -> convertformat = COERCE_IMPLICIT_CAST ;
1283+ r -> location = -1 ;
1284+
1285+ return (Node * ) r ;
1286+ }
1287+ }
12601288 }
12611289 return (Node * ) newvar ;
12621290 }
@@ -1283,14 +1311,15 @@ Node *
12831311map_variable_attnos (Node * node ,
12841312 int target_varno , int sublevels_up ,
12851313 const AttrNumber * attno_map , int map_length ,
1286- bool * found_whole_row )
1314+ Oid to_rowtype , bool * found_whole_row )
12871315{
12881316 map_variable_attnos_context context ;
12891317
12901318 context .target_varno = target_varno ;
12911319 context .sublevels_up = sublevels_up ;
12921320 context .attno_map = attno_map ;
12931321 context .map_length = map_length ;
1322+ context .to_rowtype = to_rowtype ;
12941323 context .found_whole_row = found_whole_row ;
12951324
12961325 * found_whole_row = false;
0 commit comments