summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorTom Lane2015-02-25 17:01:12 +0000
committerTom Lane2015-02-25 17:01:12 +0000
commite9f1c01b71dcd11c86fc8516c06dae2e784b96fd (patch)
tree7f4466ba76b582642e7b8222357afd40dabc05fd /src/backend
parent8794bf1ca164e1be1554197b46c9ffc62d162fb8 (diff)
Fix dumping of views that are just VALUES(...) but have column aliases.
The "simple" path for printing VALUES clauses doesn't work if we need to attach nondefault column aliases, because there's noplace to do that in the minimal VALUES() syntax. So modify get_simple_values_rte() to detect nondefault aliases and treat that as a non-simple case. This further exposes that the "non-simple" path never actually worked; it didn't produce valid syntax. Fix that too. Per bug #12789 from Curtis McEnroe, and analysis by Andrew Gierth. Back-patch to all supported branches. Before 9.3, this also requires back-patching the part of commit 092d7ded29f36b0539046b23b81b9f0bf2d637f1 that created get_simple_values_rte() to begin with; inserting the extra test into the old factorization of that logic would've been too messy.
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/utils/adt/ruleutils.c39
1 files changed, 35 insertions, 4 deletions
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index c1d860ceffd..2fa30be401f 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -4498,10 +4498,7 @@ get_simple_values_rte(Query *query)
/*
* We want to return TRUE even if the Query also contains OLD or NEW rule
* RTEs. So the idea is to scan the rtable and see if there is only one
- * inFromCl RTE that is a VALUES RTE. We don't look at the targetlist at
- * all. This is okay because parser/analyze.c will never generate a
- * "bare" VALUES RTE --- they only appear inside auto-generated
- * sub-queries with very restricted structure.
+ * inFromCl RTE that is a VALUES RTE.
*/
foreach(lc, query->rtable)
{
@@ -4518,6 +4515,33 @@ get_simple_values_rte(Query *query)
else
return NULL; /* something else -> not simple VALUES */
}
+
+ /*
+ * We don't need to check the targetlist in any great detail, because
+ * parser/analyze.c will never generate a "bare" VALUES RTE --- they only
+ * appear inside auto-generated sub-queries with very restricted
+ * structure. However, DefineView might have modified the tlist by
+ * injecting new column aliases; so compare tlist resnames against the
+ * RTE's names to detect that.
+ */
+ if (result)
+ {
+ ListCell *lcn;
+
+ if (list_length(query->targetList) != list_length(result->eref->colnames))
+ return NULL; /* this probably cannot happen */
+ forboth(lc, query->targetList, lcn, result->eref->colnames)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(lc);
+ char *cname = strVal(lfirst(lcn));
+
+ if (tle->resjunk)
+ return NULL; /* this probably cannot happen */
+ if (tle->resname == NULL || strcmp(tle->resname, cname) != 0)
+ return NULL; /* column name has been changed */
+ }
+ }
+
return result;
}
@@ -8517,7 +8541,9 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
break;
case RTE_VALUES:
/* Values list RTE */
+ appendStringInfoChar(buf, '(');
get_values_def(rte->values_lists, context);
+ appendStringInfoChar(buf, ')');
break;
case RTE_CTE:
appendStringInfoString(buf, quote_identifier(rte->ctename));
@@ -8559,6 +8585,11 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
*/
printalias = true;
}
+ else if (rte->rtekind == RTE_VALUES)
+ {
+ /* Alias is syntactically required for VALUES */
+ printalias = true;
+ }
else if (rte->rtekind == RTE_CTE)
{
/*