diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2012-08-19 14:12:16 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2012-08-19 14:12:16 -0400 |
commit | 092d7ded29f36b0539046b23b81b9f0bf2d637f1 (patch) | |
tree | 9d42dc496cf768b95fafd903f01bb9ee9dbd9b73 /src/backend/utils/adt/ruleutils.c | |
parent | c246eb5aafe66d5537b468d6da2116c462775faf (diff) | |
download | postgresql-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.c | 57 |
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; } /* |