diff --git a/doc/src/sgml/queries.sgml b/doc/src/sgml/queries.sgml index b3cfbc93582..3d729f983b5 100644 --- a/doc/src/sgml/queries.sgml +++ b/doc/src/sgml/queries.sgml @@ -1159,31 +1159,6 @@ SELECT product_id, p.name, (sum(s.units) * p.price) AS sales expressions cannot contain aggregate functions or window functions). - - PostgreSQL also supports the syntax GROUP BY ALL, - which is equivalent to explicitly writing all select-list entries that - do not contain either an aggregate function referring to the same query level or a window function. - This can greatly simplify ad-hoc exploration of data. - As an example, these queries are equivalent: - -=> SELECT a, b, a + b, sum(c) FROM test1 GROUP BY ALL; - a | b | ?column? | sum ----+---+----------+---- - 1 | 4 | 5 | 9 - 2 | 5 | 7 | 12 - 3 | 6 | 9 | 15 -(3 rows) - -=> SELECT a, b, a + b, sum(c) FROM test1 GROUP BY a, b, a + b; - a | b | ?column? | sum ----+---+----------+---- - 1 | 4 | 5 | 9 - 2 | 5 | 7 | 12 - 3 | 6 | 9 | 15 -(3 rows) - - - HAVING diff --git a/doc/src/sgml/ref/select.sgml b/doc/src/sgml/ref/select.sgml index 8d5a751af7e..837bf6d7832 100644 --- a/doc/src/sgml/ref/select.sgml +++ b/doc/src/sgml/ref/select.sgml @@ -37,7 +37,7 @@ SELECT [ ALL | DISTINCT [ ON ( expressionexpression [ [ AS ] output_name ] } [, ...] ] [ FROM from_item [, ...] ] [ WHERE condition ] - [ GROUP BY { ALL | [ ALL | DISTINCT ] grouping_element [, ...] } ] + [ GROUP BY [ ALL | DISTINCT ] grouping_element [, ...] ] [ HAVING condition ] [ WINDOW window_name AS ( window_definition ) [, ...] ] [ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] select ] @@ -839,7 +839,7 @@ WHERE condition The optional GROUP BY clause has the general form -GROUP BY { ALL | [ ALL | DISTINCT ] grouping_element [, ...] } +GROUP BY [ ALL | DISTINCT ] grouping_element [, ...] @@ -857,15 +857,6 @@ GROUP BY { ALL | [ ALL | DISTINCT ] grouping_elem input-column name rather than an output column name. - - The form GROUP BY ALL with no explicit - grouping_elements - provided is equivalent to writing GROUP BY with the - numbers of all SELECT output columns that do not - contain either an aggregate function referring to the same query level or - a window function. - - If any of GROUPING SETS, ROLLUP or CUBE are present as grouping elements, then the diff --git a/doc/src/sgml/ref/select_into.sgml b/doc/src/sgml/ref/select_into.sgml index cbf865ff838..550ba69d5d1 100644 --- a/doc/src/sgml/ref/select_into.sgml +++ b/doc/src/sgml/ref/select_into.sgml @@ -27,7 +27,7 @@ SELECT [ ALL | DISTINCT [ ON ( expressionnew_table [ FROM from_item [, ...] ] [ WHERE condition ] - [ GROUP BY { ALL | [ ALL | DISTINCT ] grouping_element [, ...] } ] + [ GROUP BY [ ALL | DISTINCT ] grouping_element [, ...] ] [ HAVING condition ] [ WINDOW window_name AS ( window_definition ) [, ...] ] [ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] select ] diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index ea97d236ea8..562e4facd74 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -1811,14 +1811,12 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt, qry->groupClause = transformGroupClause(pstate, stmt->groupClause, - stmt->groupByAll, &qry->groupingSets, &qry->targetList, qry->sortClause, EXPR_KIND_GROUP_BY, false /* allow SQL92 rules */ ); qry->groupDistinct = stmt->groupDistinct; - qry->groupByAll = stmt->groupByAll; if (stmt->distinctClause == NIL) { diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index ff4e1388c55..e1e65c414db 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -120,7 +120,6 @@ typedef struct SelectLimit typedef struct GroupClause { bool distinct; - bool all; List *list; } GroupClause; @@ -13751,7 +13750,6 @@ simple_select: n->whereClause = $6; n->groupClause = ($7)->list; n->groupDistinct = ($7)->distinct; - n->groupByAll = ($7)->all; n->havingClause = $8; n->windowClause = $9; $$ = (Node *) n; @@ -13769,7 +13767,6 @@ simple_select: n->whereClause = $6; n->groupClause = ($7)->list; n->groupDistinct = ($7)->distinct; - n->groupByAll = ($7)->all; n->havingClause = $8; n->windowClause = $9; $$ = (Node *) n; @@ -14267,24 +14264,14 @@ group_clause: GroupClause *n = palloc_object(GroupClause); n->distinct = $3 == SET_QUANTIFIER_DISTINCT; - n->all = false; n->list = $4; $$ = n; } - | GROUP_P BY ALL - { - GroupClause *n = palloc_object(GroupClause); - n->distinct = false; - n->all = true; - n->list = NIL; - $$ = n; - } | /*EMPTY*/ { GroupClause *n = palloc_object(GroupClause); n->distinct = false; - n->all = false; n->list = NIL; $$ = n; } @@ -18707,7 +18694,6 @@ PLpgSQL_Expr: opt_distinct_clause opt_target_list n->whereClause = $4; n->groupClause = ($5)->list; n->groupDistinct = ($5)->distinct; - n->groupByAll = ($5)->all; n->havingClause = $6; n->windowClause = $7; n->sortClause = $8; diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 2f7333e6786..485e33b9e5a 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -2746,9 +2746,6 @@ transformGroupingSet(List **flatresult, * GROUP BY items will be added to the targetlist (as resjunk columns) * if not already present, so the targetlist must be passed by reference. * - * If GROUP BY ALL is specified, the groupClause will be inferred to be all - * non-aggregate, non-window expressions in the targetlist. - * * This is also used for window PARTITION BY clauses (which act almost the * same, but are always interpreted per SQL99 rules). * @@ -2773,7 +2770,6 @@ transformGroupingSet(List **flatresult, * * pstate ParseState * grouplist clause to transform - * groupByAll is this a GROUP BY ALL statement? * groupingSets reference to list to contain the grouping set tree * targetlist reference to TargetEntry list * sortClause ORDER BY clause (SortGroupClause nodes) @@ -2781,8 +2777,7 @@ transformGroupingSet(List **flatresult, * useSQL99 SQL99 rather than SQL92 syntax */ List * -transformGroupClause(ParseState *pstate, List *grouplist, bool groupByAll, - List **groupingSets, +transformGroupClause(ParseState *pstate, List *grouplist, List **groupingSets, List **targetlist, List *sortClause, ParseExprKind exprKind, bool useSQL99) { @@ -2793,61 +2788,6 @@ transformGroupClause(ParseState *pstate, List *grouplist, bool groupByAll, bool hasGroupingSets = false; Bitmapset *seen_local = NULL; - /* Handle GROUP BY ALL */ - if (groupByAll) - { - /* There cannot have been any explicit grouplist items */ - Assert(grouplist == NIL); - - /* Iterate over targets, adding acceptable ones to the result list */ - foreach_ptr(TargetEntry, tle, *targetlist) - { - /* Ignore junk TLEs */ - if (tle->resjunk) - continue; - - /* - * TLEs containing aggregates are not okay to add to GROUP BY - * (compare checkTargetlistEntrySQL92). But the SQL standard - * directs us to skip them, so it's fine. - */ - if (pstate->p_hasAggs && - contain_aggs_of_level((Node *) tle->expr, 0)) - continue; - - /* - * Likewise, TLEs containing window functions are not okay to add - * to GROUP BY, and the SQL standard directs us to skip them. - */ - if (pstate->p_hasWindowFuncs && - contain_windowfuncs((Node *) tle->expr)) - continue; - - /* - * Otherwise, add the TLE to the result using default sort/group - * semantics. We specify the parse location as the TLE's - * location, despite the comment for addTargetToGroupList - * discouraging that. The only other thing we could point to is - * the ALL keyword, which seems unhelpful when there are multiple - * TLEs. - */ - result = addTargetToGroupList(pstate, tle, - result, *targetlist, - exprLocation((Node *) tle->expr)); - } - - /* If we found any acceptable targets, we're done */ - if (result != NIL) - return result; - - /* - * Otherwise, the SQL standard says to treat it like "GROUP BY ()". - * Build a representation of that, and let the rest of this function - * handle it. - */ - grouplist = list_make1(makeGroupingSet(GROUPING_SET_EMPTY, NIL, -1)); - } - /* * Recursively flatten implicit RowExprs. (Technically this is only needed * for GROUP BY, per the syntax rules for grouping sets, but we do it @@ -3026,7 +2966,6 @@ transformWindowDefinitions(ParseState *pstate, true /* force SQL99 rules */ ); partitionClause = transformGroupClause(pstate, windef->partitionClause, - false /* not GROUP BY ALL */ , NULL, targetlist, orderClause, diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 819631781c0..c6555948df8 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -6555,9 +6555,7 @@ get_basic_select_query(Query *query, deparse_context *context) save_ingroupby = context->inGroupBy; context->inGroupBy = true; - if (query->groupByAll) - appendStringInfoString(buf, "ALL"); - else if (query->groupingSets == NIL) + if (query->groupingSets == NIL) { sep = ""; foreach(l, query->groupClause) diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 79291aaaf5c..2471ccb96a3 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -57,6 +57,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202607071 +#define CATALOG_VERSION_NO 202607172 #endif diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 4133c404a6b..ad31a9c059b 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -220,7 +220,6 @@ typedef struct Query List *groupClause; /* a list of SortGroupClause's */ bool groupDistinct; /* was GROUP BY DISTINCT used? */ - bool groupByAll; /* was GROUP BY ALL used? */ List *groupingSets; /* a list of GroupingSet's if present */ @@ -2297,7 +2296,6 @@ typedef struct SelectStmt Node *whereClause; /* WHERE qualification */ List *groupClause; /* GROUP BY clauses */ bool groupDistinct; /* Is this GROUP BY DISTINCT? */ - bool groupByAll; /* Is this GROUP BY ALL? */ Node *havingClause; /* HAVING conditional-expression */ List *windowClause; /* WINDOW window_name AS (...), ... */ diff --git a/src/include/parser/parse_clause.h b/src/include/parser/parse_clause.h index fe234611007..ca815a9d1bb 100644 --- a/src/include/parser/parse_clause.h +++ b/src/include/parser/parse_clause.h @@ -26,7 +26,6 @@ extern Node *transformLimitClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName, LimitOption limitOption); extern List *transformGroupClause(ParseState *pstate, List *grouplist, - bool groupByAll, List **groupingSets, List **targetlist, List *sortClause, ParseExprKind exprKind, bool useSQL99); diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out index 728a3ecd03f..1824f7db557 100644 --- a/src/test/regress/expected/aggregates.out +++ b/src/test/regress/expected/aggregates.out @@ -1774,129 +1774,6 @@ select a, count(*) from t_having group by a having a = row(1.0)::avg_rec; drop table t_having; drop type avg_rec; -- --- Test GROUP BY ALL --- --- We don't care about the data here, just the proper transformation of the --- GROUP BY clause, so test some queries and verify the EXPLAIN plans. --- -CREATE TEMP TABLE t1 ( - a int, - b int, - c int -); --- basic example -EXPLAIN (COSTS OFF) SELECT b, COUNT(*) FROM t1 GROUP BY ALL; - QUERY PLAN ----------------------- - HashAggregate - Group Key: b - -> Seq Scan on t1 -(3 rows) - --- multiple columns, non-consecutive order -EXPLAIN (COSTS OFF) SELECT a, SUM(b), b FROM t1 GROUP BY ALL; - QUERY PLAN ----------------------- - HashAggregate - Group Key: a, b - -> Seq Scan on t1 -(3 rows) - --- multi columns, no aggregate -EXPLAIN (COSTS OFF) SELECT a + b FROM t1 GROUP BY ALL; - QUERY PLAN ----------------------- - HashAggregate - Group Key: (a + b) - -> Seq Scan on t1 -(3 rows) - --- check we detect a non-top-level aggregate -EXPLAIN (COSTS OFF) SELECT a, SUM(b) + 4 FROM t1 GROUP BY ALL; - QUERY PLAN ----------------------- - HashAggregate - Group Key: a - -> Seq Scan on t1 -(3 rows) - --- including grouped column is okay -EXPLAIN (COSTS OFF) SELECT a, SUM(b) + a FROM t1 GROUP BY ALL; - QUERY PLAN ----------------------- - HashAggregate - Group Key: a - -> Seq Scan on t1 -(3 rows) - --- including non-grouped column, not so much -EXPLAIN (COSTS OFF) SELECT a, SUM(b) + c FROM t1 GROUP BY ALL; -ERROR: column "t1.c" must appear in the GROUP BY clause or be used in an aggregate function -LINE 1: EXPLAIN (COSTS OFF) SELECT a, SUM(b) + c FROM t1 GROUP BY AL... - ^ --- all aggregates, should reduce to GROUP BY () -EXPLAIN (COSTS OFF) SELECT COUNT(a), SUM(b) FROM t1 GROUP BY ALL; - QUERY PLAN ----------------------- - Aggregate - Group Key: () - -> Seq Scan on t1 -(3 rows) - --- likewise with empty target list -EXPLAIN (COSTS OFF) SELECT FROM t1 GROUP BY ALL; - QUERY PLAN ------------------------ - Result - Replaces: Aggregate -(2 rows) - --- window functions are not to be included in GROUP BY, either -EXPLAIN (COSTS OFF) SELECT a, COUNT(a) OVER (PARTITION BY a) FROM t1 GROUP BY ALL; - QUERY PLAN ----------------------------------- - WindowAgg - Window: w1 AS (PARTITION BY a) - -> Sort - Sort Key: a - -> HashAggregate - Group Key: a - -> Seq Scan on t1 -(7 rows) - --- all cols -EXPLAIN (COSTS OFF) SELECT *, count(*) FROM t1 GROUP BY ALL; - QUERY PLAN ----------------------- - HashAggregate - Group Key: a, b, c - -> Seq Scan on t1 -(3 rows) - --- group by all with grouping element(s) (equivalent to GROUP BY's --- default behavior, explicit antithesis to GROUP BY DISTINCT) -EXPLAIN (COSTS OFF) SELECT a, count(*) FROM t1 GROUP BY ALL a; - QUERY PLAN ----------------------- - HashAggregate - Group Key: a - -> Seq Scan on t1 -(3 rows) - --- verify deparsing of GROUP BY ALL -CREATE TEMP VIEW v1 AS SELECT b, COUNT(*) FROM t1 GROUP BY ALL; -SELECT pg_get_viewdef('v1'::regclass); - pg_get_viewdef ------------------------ - SELECT b, + - count(*) AS count+ - FROM t1 + - GROUP BY ALL; -(1 row) - -DROP VIEW v1; -DROP TABLE t1; --- -- Test GROUP BY matching of join columns that are type-coerced due to USING -- create temp table t1(f1 int, f2 int); diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql index 342605d5497..490c52d4c03 100644 --- a/src/test/regress/sql/aggregates.sql +++ b/src/test/regress/sql/aggregates.sql @@ -640,60 +640,6 @@ select a, count(*) from t_having group by a having a = row(1.0)::avg_rec; drop table t_having; drop type avg_rec; --- --- Test GROUP BY ALL --- --- We don't care about the data here, just the proper transformation of the --- GROUP BY clause, so test some queries and verify the EXPLAIN plans. --- - -CREATE TEMP TABLE t1 ( - a int, - b int, - c int -); - --- basic example -EXPLAIN (COSTS OFF) SELECT b, COUNT(*) FROM t1 GROUP BY ALL; - --- multiple columns, non-consecutive order -EXPLAIN (COSTS OFF) SELECT a, SUM(b), b FROM t1 GROUP BY ALL; - --- multi columns, no aggregate -EXPLAIN (COSTS OFF) SELECT a + b FROM t1 GROUP BY ALL; - --- check we detect a non-top-level aggregate -EXPLAIN (COSTS OFF) SELECT a, SUM(b) + 4 FROM t1 GROUP BY ALL; - --- including grouped column is okay -EXPLAIN (COSTS OFF) SELECT a, SUM(b) + a FROM t1 GROUP BY ALL; - --- including non-grouped column, not so much -EXPLAIN (COSTS OFF) SELECT a, SUM(b) + c FROM t1 GROUP BY ALL; - --- all aggregates, should reduce to GROUP BY () -EXPLAIN (COSTS OFF) SELECT COUNT(a), SUM(b) FROM t1 GROUP BY ALL; - --- likewise with empty target list -EXPLAIN (COSTS OFF) SELECT FROM t1 GROUP BY ALL; - --- window functions are not to be included in GROUP BY, either -EXPLAIN (COSTS OFF) SELECT a, COUNT(a) OVER (PARTITION BY a) FROM t1 GROUP BY ALL; - --- all cols -EXPLAIN (COSTS OFF) SELECT *, count(*) FROM t1 GROUP BY ALL; - --- group by all with grouping element(s) (equivalent to GROUP BY's --- default behavior, explicit antithesis to GROUP BY DISTINCT) -EXPLAIN (COSTS OFF) SELECT a, count(*) FROM t1 GROUP BY ALL a; - --- verify deparsing of GROUP BY ALL -CREATE TEMP VIEW v1 AS SELECT b, COUNT(*) FROM t1 GROUP BY ALL; -SELECT pg_get_viewdef('v1'::regclass); - -DROP VIEW v1; -DROP TABLE t1; - -- -- Test GROUP BY matching of join columns that are type-coerced due to USING --