aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/ruleutils.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2012-08-19 14:12:16 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2012-08-19 14:12:16 -0400
commit092d7ded29f36b0539046b23b81b9f0bf2d637f1 (patch)
tree9d42dc496cf768b95fafd903f01bb9ee9dbd9b73 /src/backend/utils/adt/ruleutils.c
parentc246eb5aafe66d5537b468d6da2116c462775faf (diff)
downloadpostgresql-092d7ded29f36b0539046b23b81b9f0bf2d637f1.tar.gz
postgresql-092d7ded29f36b0539046b23b81b9f0bf2d637f1.zip
Allow OLD and NEW in multi-row VALUES within rules.
Now that we have LATERAL, it's fairly painless to allow this case, which was left as a TODO in the original multi-row VALUES implementation.
Diffstat (limited to 'src/backend/utils/adt/ruleutils.c')
-rw-r--r--src/backend/utils/adt/ruleutils.c57
1 files changed, 42 insertions, 15 deletions
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 01030219619..f6f7f85f443 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -2919,11 +2919,48 @@ get_select_query_def(Query *query, deparse_context *context,
context->windowTList = save_windowtlist;
}
+/*
+ * Detect whether query looks like SELECT ... FROM VALUES();
+ * if so, return the VALUES RTE. Otherwise return NULL.
+ */
+static RangeTblEntry *
+get_simple_values_rte(Query *query)
+{
+ RangeTblEntry *result = NULL;
+ ListCell *lc;
+
+ /*
+ * 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.
+ */
+ foreach(lc, query->rtable)
+ {
+ RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
+
+ if (rte->rtekind == RTE_VALUES && rte->inFromCl)
+ {
+ if (result)
+ return NULL; /* multiple VALUES (probably not possible) */
+ result = rte;
+ }
+ else if (rte->rtekind == RTE_RELATION && !rte->inFromCl)
+ continue; /* ignore rule entries */
+ else
+ return NULL; /* something else -> not simple VALUES */
+ }
+ return result;
+}
+
static void
get_basic_select_query(Query *query, deparse_context *context,
TupleDesc resultDesc)
{
StringInfo buf = context->buf;
+ RangeTblEntry *values_rte;
char *sep;
ListCell *l;
@@ -2936,23 +2973,13 @@ get_basic_select_query(Query *query, deparse_context *context,
/*
* If the query looks like SELECT * FROM (VALUES ...), then print just the
* VALUES part. This reverses what transformValuesClause() did at parse
- * time. If the jointree contains just a single VALUES RTE, we assume
- * this case applies (without looking at the targetlist...)
+ * time.
*/
- if (list_length(query->jointree->fromlist) == 1)
+ values_rte = get_simple_values_rte(query);
+ if (values_rte)
{
- RangeTblRef *rtr = (RangeTblRef *) linitial(query->jointree->fromlist);
-
- if (IsA(rtr, RangeTblRef))
- {
- RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable);
-
- if (rte->rtekind == RTE_VALUES)
- {
- get_values_def(rte->values_lists, context);
- return;
- }
- }
+ get_values_def(values_rte->values_lists, context);
+ return;
}
/*