@@ -1224,6 +1224,7 @@ typedef struct
12241224 /* Target type when converting whole-row vars */
12251225 Oid to_rowtype ;
12261226 bool * found_whole_row ; /* output flag */
1227+ bool coerced_var ; /* var is under ConvertRowTypeExpr */
12271228} map_variable_attnos_context ;
12281229
12291230static Node *
@@ -1267,29 +1268,58 @@ map_variable_attnos_mutator(Node *node,
12671268 /* Don't convert unless necessary. */
12681269 if (context -> to_rowtype != var -> vartype )
12691270 {
1270- ConvertRowtypeExpr * r ;
1271-
12721271 /* Var itself is converted to the requested type. */
12731272 newvar -> vartype = context -> to_rowtype ;
12741273
12751274 /*
1276- * And a conversion node on top to convert back to the
1277- * original type .
1275+ * If this var is already under a ConvertRowtypeExpr,
1276+ * we don't have to add another one .
12781277 */
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 ;
1278+ if (!context -> coerced_var )
1279+ {
1280+ ConvertRowtypeExpr * r ;
1281+
1282+ /*
1283+ * And a conversion node on top to convert back to
1284+ * the original type.
1285+ */
1286+ r = makeNode (ConvertRowtypeExpr );
1287+ r -> arg = (Expr * ) newvar ;
1288+ r -> resulttype = var -> vartype ;
1289+ r -> convertformat = COERCE_IMPLICIT_CAST ;
1290+ r -> location = -1 ;
1291+
1292+ return (Node * ) r ;
1293+ }
12861294 }
12871295 }
12881296 }
12891297 return (Node * ) newvar ;
12901298 }
12911299 /* otherwise fall through to copy the var normally */
12921300 }
1301+ else if (IsA (node , ConvertRowtypeExpr ))
1302+ {
1303+ ConvertRowtypeExpr * r = (ConvertRowtypeExpr * ) node ;
1304+
1305+ /*
1306+ * If this is coercing a var (which is typical), convert only the var,
1307+ * as against adding another ConvertRowtypeExpr over it.
1308+ */
1309+ if (IsA (r -> arg , Var ))
1310+ {
1311+ ConvertRowtypeExpr * newnode ;
1312+
1313+ newnode = (ConvertRowtypeExpr * ) palloc (sizeof (ConvertRowtypeExpr ));
1314+ * newnode = * r ;
1315+ context -> coerced_var = true;
1316+ newnode -> arg = (Expr * ) map_variable_attnos_mutator ((Node * ) r -> arg , context );
1317+ context -> coerced_var = false;
1318+
1319+ return (Node * ) newnode ;
1320+ }
1321+ /* Else fall through the expression tree mutator */
1322+ }
12931323 else if (IsA (node , Query ))
12941324 {
12951325 /* Recurse into RTE subquery or not-yet-planned sublink subquery */
@@ -1321,6 +1351,7 @@ map_variable_attnos(Node *node,
13211351 context .map_length = map_length ;
13221352 context .to_rowtype = to_rowtype ;
13231353 context .found_whole_row = found_whole_row ;
1354+ context .coerced_var = false;
13241355
13251356 * found_whole_row = false;
13261357
0 commit comments