Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 7393711

Browse files
committed
Improve implementation of CRE-stack-flattening in map_variable_attnos().
I (tgl) objected to the obscure implementation introduced in commit 1c497fa. This one seems a bit less action-at-a-distance-y, at the price of repeating a few lines of code. Improve the comments about what the function is doing, too. Amit Khandekar, whacked around a bit more by me Discussion: https://postgr.es/m/CAJ3gD9egYTyHUH0nTMxm8-1m3RvdqEbaTyGC-CUNtYf7tKNDaQ@mail.gmail.com
1 parent 5229db6 commit 7393711

File tree

1 file changed

+55
-46
lines changed

1 file changed

+55
-46
lines changed

src/backend/rewrite/rewriteManip.c

Lines changed: 55 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,9 +1203,11 @@ 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-
* *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
1206+
* *found_whole_row is set to TRUE. In addition, if to_rowtype is
1207+
* not InvalidOid, we replace the Var with a Var of that vartype, inserting
1208+
* a ConvertRowTypeExpr to map back to the rowtype expected by the expression.
1209+
* (Therefore, to_rowtype had better be a child rowtype of the rowtype of the
1210+
* RTE we're changing references to.) Callers that don't provide to_rowtype
12091211
* should report an error if *found_row_type is true; we don't do that here
12101212
* because we don't know exactly what wording for the error message would
12111213
* be most appropriate. The caller will be aware of the context.
@@ -1221,10 +1223,8 @@ typedef struct
12211223
int sublevels_up; /* (current) nesting depth */
12221224
const AttrNumber *attno_map; /* map array for user attnos */
12231225
int map_length; /* number of entries in attno_map[] */
1224-
/* Target type when converting whole-row vars */
1225-
Oid to_rowtype;
1226+
Oid to_rowtype; /* change whole-row Vars to this type */
12261227
bool *found_whole_row; /* output flag */
1227-
bool coerced_var; /* var is under ConvertRowTypeExpr */
12281228
} map_variable_attnos_context;
12291229

12301230
static Node *
@@ -1244,7 +1244,8 @@ map_variable_attnos_mutator(Node *node,
12441244
Var *newvar = (Var *) palloc(sizeof(Var));
12451245
int attno = var->varattno;
12461246

1247-
*newvar = *var;
1247+
*newvar = *var; /* initially copy all fields of the Var */
1248+
12481249
if (attno > 0)
12491250
{
12501251
/* user-defined column, replace attno */
@@ -1259,39 +1260,29 @@ map_variable_attnos_mutator(Node *node,
12591260
/* whole-row variable, warn caller */
12601261
*(context->found_whole_row) = true;
12611262

1262-
/* If the callers expects us to convert the same, do so. */
1263-
if (OidIsValid(context->to_rowtype))
1263+
/* If the caller expects us to convert the Var, do so. */
1264+
if (OidIsValid(context->to_rowtype) &&
1265+
context->to_rowtype != var->vartype)
12641266
{
1265-
/* No support for RECORDOID. */
1267+
ConvertRowtypeExpr *r;
1268+
1269+
/* This certainly won't work for a RECORD variable. */
12661270
Assert(var->vartype != RECORDOID);
12671271

1268-
/* Don't convert unless necessary. */
1269-
if (context->to_rowtype != var->vartype)
1270-
{
1271-
/* Var itself is converted to the requested type. */
1272-
newvar->vartype = context->to_rowtype;
1273-
1274-
/*
1275-
* If this var is already under a ConvertRowtypeExpr,
1276-
* we don't have to add another one.
1277-
*/
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-
}
1294-
}
1272+
/* Var itself is changed to the requested type. */
1273+
newvar->vartype = context->to_rowtype;
1274+
1275+
/*
1276+
* Add a conversion node on top to convert back to the
1277+
* original type expected by the expression.
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;
12951286
}
12961287
}
12971288
return (Node *) newvar;
@@ -1301,24 +1292,43 @@ map_variable_attnos_mutator(Node *node,
13011292
else if (IsA(node, ConvertRowtypeExpr))
13021293
{
13031294
ConvertRowtypeExpr *r = (ConvertRowtypeExpr *) node;
1295+
Var *var = (Var *) r->arg;
13041296

13051297
/*
1306-
* If this is coercing a var (which is typical), convert only the var,
1307-
* as against adding another ConvertRowtypeExpr over it.
1298+
* If this is coercing a whole-row Var that we need to convert, then
1299+
* just convert the Var without adding an extra ConvertRowtypeExpr.
1300+
* Effectively we're simplifying var::parenttype::grandparenttype into
1301+
* just var::grandparenttype. This avoids building stacks of CREs if
1302+
* this function is applied repeatedly.
13081303
*/
1309-
if (IsA(r->arg, Var))
1304+
if (IsA(var, Var) &&
1305+
var->varno == context->target_varno &&
1306+
var->varlevelsup == context->sublevels_up &&
1307+
var->varattno == 0 &&
1308+
OidIsValid(context->to_rowtype) &&
1309+
context->to_rowtype != var->vartype)
13101310
{
13111311
ConvertRowtypeExpr *newnode;
1312+
Var *newvar = (Var *) palloc(sizeof(Var));
1313+
1314+
/* whole-row variable, warn caller */
1315+
*(context->found_whole_row) = true;
1316+
1317+
*newvar = *var; /* initially copy all fields of the Var */
1318+
1319+
/* This certainly won't work for a RECORD variable. */
1320+
Assert(var->vartype != RECORDOID);
1321+
1322+
/* Var itself is changed to the requested type. */
1323+
newvar->vartype = context->to_rowtype;
13121324

13131325
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;
1326+
*newnode = *r; /* initially copy all fields of the CRE */
1327+
newnode->arg = (Expr *) newvar;
13181328

13191329
return (Node *) newnode;
13201330
}
1321-
/* Else fall through the expression tree mutator */
1331+
/* otherwise fall through to process the expression normally */
13221332
}
13231333
else if (IsA(node, Query))
13241334
{
@@ -1351,7 +1361,6 @@ map_variable_attnos(Node *node,
13511361
context.map_length = map_length;
13521362
context.to_rowtype = to_rowtype;
13531363
context.found_whole_row = found_whole_row;
1354-
context.coerced_var = false;
13551364

13561365
*found_whole_row = false;
13571366

0 commit comments

Comments
 (0)