diff options
author | Andres Freund <andres@anarazel.de> | 2015-07-26 16:37:49 +0200 |
---|---|---|
committer | Andres Freund <andres@anarazel.de> | 2015-07-26 16:50:29 +0200 |
commit | faab14ecb8c1b4ea2bee3723d4fa04f47275abd3 (patch) | |
tree | 7190afc8a2e788c3c1a59f4dac0d79424beabb43 /src/backend/parser/parse_clause.c | |
parent | 61444bfb809d3a088a270a59f383af3d4cd157b0 (diff) | |
download | postgresql-faab14ecb8c1b4ea2bee3723d4fa04f47275abd3.tar.gz postgresql-faab14ecb8c1b4ea2bee3723d4fa04f47275abd3.zip |
Fix flattening of nested grouping sets.
Previously nested grouping set specifications accidentally weren't
flattened, but instead contained the nested specification as a element
in the outer list.
Fix this by, as actually documented in comments, concatenating the
nested set specification into the outer one. Also add tests to prevent
this from breaking again.
Author: Andrew Gierth, with tests from Jeevan Chalke
Reported-By: Jeevan Chalke
Discussion: CAM2+6=V5YvuxB+EyN4iH=GbD-XTA435TCNvnDFSD--YvXs+pww@mail.gmail.com
Backpatch: 9.5, where grouping sets were introduced
Diffstat (limited to 'src/backend/parser/parse_clause.c')
-rw-r--r-- | src/backend/parser/parse_clause.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 4e490b23b4e..59808568a52 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -1812,7 +1812,7 @@ findTargetlistEntrySQL99(ParseState *pstate, Node *node, List **tlist, * Inside a grouping set (ROLLUP, CUBE, or GROUPING SETS), we expect the * content to be nested no more than 2 deep: i.e. ROLLUP((a,b),(c,d)) is * ok, but ROLLUP((a,(b,c)),d) is flattened to ((a,b,c),d), which we then - * normalize to ((a,b,c),(d)). + * (later) normalize to ((a,b,c),(d)). * * CUBE or ROLLUP can be nested inside GROUPING SETS (but not the reverse), * and we leave that alone if we find it. But if we see GROUPING SETS inside @@ -1881,9 +1881,16 @@ flatten_grouping_sets(Node *expr, bool toplevel, bool *hasGroupingSets) foreach(l2, gset->content) { - Node *n2 = flatten_grouping_sets(lfirst(l2), false, NULL); + Node *n1 = lfirst(l2); + Node *n2 = flatten_grouping_sets(n1, false, NULL); - result_set = lappend(result_set, n2); + if (IsA(n1, GroupingSet) && + ((GroupingSet *)n1)->kind == GROUPING_SET_SETS) + { + result_set = list_concat(result_set, (List *) n2); + } + else + result_set = lappend(result_set, n2); } /* |