aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2017-10-12 17:10:48 -0400
committerRobert Haas <rhaas@postgresql.org>2017-10-12 17:10:48 -0400
commit1c497fa72df7593d8976653538da3d0ab033207f (patch)
treed5d0feffb020b3490787921c48cb2c24daa687c1 /src
parent60f7c0abef0327648c02795312d1679c66586fbb (diff)
downloadpostgresql-1c497fa72df7593d8976653538da3d0ab033207f.tar.gz
postgresql-1c497fa72df7593d8976653538da3d0ab033207f.zip
Avoid coercing a whole-row variable that is already coerced.
Marginal efficiency and beautification hack. I'm not sure whether this case ever arises currently, but the pending patch for update tuple routing will cause it to arise. Amit Khandekar Discussion: http://postgr.es/m/CAJ3gD9cazfppe7-wwUbabPcQ4_0SubkiPFD1+0r5_DkVNWo5yg@mail.gmail.com
Diffstat (limited to 'src')
-rw-r--r--src/backend/rewrite/rewriteManip.c53
1 files changed, 42 insertions, 11 deletions
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c
index c5773efd192..9290c7f7936 100644
--- a/src/backend/rewrite/rewriteManip.c
+++ b/src/backend/rewrite/rewriteManip.c
@@ -1224,6 +1224,7 @@ typedef struct
/* Target type when converting whole-row vars */
Oid to_rowtype;
bool *found_whole_row; /* output flag */
+ bool coerced_var; /* var is under ConvertRowTypeExpr */
} map_variable_attnos_context;
static Node *
@@ -1267,22 +1268,29 @@ map_variable_attnos_mutator(Node *node,
/* Don't convert unless necessary. */
if (context->to_rowtype != var->vartype)
{
- ConvertRowtypeExpr *r;
-
/* Var itself is converted to the requested type. */
newvar->vartype = context->to_rowtype;
/*
- * And a conversion node on top to convert back to the
- * original type.
+ * If this var is already under a ConvertRowtypeExpr,
+ * we don't have to add another one.
*/
- r = makeNode(ConvertRowtypeExpr);
- r->arg = (Expr *) newvar;
- r->resulttype = var->vartype;
- r->convertformat = COERCE_IMPLICIT_CAST;
- r->location = -1;
-
- return (Node *) r;
+ if (!context->coerced_var)
+ {
+ ConvertRowtypeExpr *r;
+
+ /*
+ * And a conversion node on top to convert back to
+ * the original type.
+ */
+ r = makeNode(ConvertRowtypeExpr);
+ r->arg = (Expr *) newvar;
+ r->resulttype = var->vartype;
+ r->convertformat = COERCE_IMPLICIT_CAST;
+ r->location = -1;
+
+ return (Node *) r;
+ }
}
}
}
@@ -1290,6 +1298,28 @@ map_variable_attnos_mutator(Node *node,
}
/* otherwise fall through to copy the var normally */
}
+ else if (IsA(node, ConvertRowtypeExpr))
+ {
+ ConvertRowtypeExpr *r = (ConvertRowtypeExpr *) node;
+
+ /*
+ * If this is coercing a var (which is typical), convert only the var,
+ * as against adding another ConvertRowtypeExpr over it.
+ */
+ if (IsA(r->arg, Var))
+ {
+ ConvertRowtypeExpr *newnode;
+
+ newnode = (ConvertRowtypeExpr *) palloc(sizeof(ConvertRowtypeExpr));
+ *newnode = *r;
+ context->coerced_var = true;
+ newnode->arg = (Expr *) map_variable_attnos_mutator((Node *) r->arg, context);
+ context->coerced_var = false;
+
+ return (Node *) newnode;
+ }
+ /* Else fall through the expression tree mutator */
+ }
else if (IsA(node, Query))
{
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
@@ -1321,6 +1351,7 @@ map_variable_attnos(Node *node,
context.map_length = map_length;
context.to_rowtype = to_rowtype;
context.found_whole_row = found_whole_row;
+ context.coerced_var = false;
*found_whole_row = false;