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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy