This is an automated email from the ASF dual-hosted git repository.

mihaibudiu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/main by this push:
     new 21b5b2fb2c [CALCITE-7647] Support SELECT * in GROUP BY ALL and ORDER 
BY ALL
21b5b2fb2c is described below

commit 21b5b2fb2cf09a80fc1b7582c2e950b073046bda
Author: Tisya Bhatia <[email protected]>
AuthorDate: Mon Aug 3 11:56:27 2026 -0500

    [CALCITE-7647] Support SELECT * in GROUP BY ALL and ORDER BY ALL
---
 .../apache/calcite/runtime/CalciteResource.java    |  6 ----
 .../calcite/sql/validate/SqlValidatorImpl.java     | 32 +++++++++++++++++++---
 .../calcite/runtime/CalciteResource.properties     |  2 --
 .../org/apache/calcite/test/SqlValidatorTest.java  | 28 +++++++++++++++----
 core/src/test/resources/sql/agg.iq                 | 31 +++++++++++++++++++++
 core/src/test/resources/sql/sort.iq                | 15 ++++++++++
 site/_docs/reference.md                            |  6 ++++
 7 files changed, 102 insertions(+), 18 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java 
b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
index 2e5056da1d..cc27cb5c20 100644
--- a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
+++ b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
@@ -406,9 +406,6 @@ ExInst<SqlValidatorException> 
naturalOrUsingColumnNotCompatible(String a0,
   @BaseMessage("Windowed aggregate expression is illegal in {0} clause")
   ExInst<SqlValidatorException> windowedAggregateIllegalInClause(String a0);
 
-  @BaseMessage("GROUP BY ALL requires an explicit SELECT list; ''*'' is not 
supported")
-  ExInst<SqlValidatorException> groupByAllRequiresExplicitSelectList();
-
   @BaseMessage("Aggregate expressions cannot be nested")
   ExInst<SqlValidatorException> nestedAggIllegal();
 
@@ -800,9 +797,6 @@ ExInst<CalciteException> 
illegalArgumentForTableFunctionCall(String a0,
   @BaseMessage("Streaming ORDER BY must start with monotonic expression")
   ExInst<SqlValidatorException> streamMustOrderByMonotonic();
 
-  @BaseMessage("ORDER BY ALL requires an explicit SELECT list; ''*'' is not 
supported")
-  ExInst<SqlValidatorException> orderByAllRequiresExplicitSelectList();
-
   @BaseMessage("Set operator cannot combine streaming and non-streaming 
inputs")
   ExInst<SqlValidatorException> streamSetOpInconsistentInputs();
 
diff --git 
a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java 
b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
index 604c03d2d1..c2d12ffd18 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
@@ -5328,6 +5328,24 @@ protected void validateOrderList(SqlSelect select) {
     }
   }
 
+  /** Expands a single "*" or "t.*" select item into its underlying columns,
+   * for a GROUP BY ALL / ORDER BY ALL rewrite.
+   *
+   * <p>Calls the private {@code expandStar} core directly (not the public
+   * {@code expandStar(SqlNodeList, SqlSelect, boolean)} wrapper), with fresh
+   * collections: the wrapper would derive types over every select item and
+   * mark the expanded list, poisoning {@link AggregatingSelectScope}'s
+   * memoized grouping set with the not-yet-rewritten placeholder. The fresh
+   * {@code items}/{@code fields} must stay paired for NATURAL/USING index
+   * alignment. */
+  private List<SqlNode> expandStarForAllRewrite(SqlSelect select, SqlNode 
starItem) {
+    final SelectScope scope = (SelectScope) getWhereScope(select);
+    final List<SqlNode> items = new ArrayList<>();
+    expandStar(items, catalogReader.nameMatcher().createSet(), PairList.of(),
+        false, scope, starItem, false);
+    return items;
+  }
+
   protected void rewriteOrderByAll(SqlSelect select) {
     final SqlNodeList orderList = select.getOrderList();
     if (orderList == null || orderList.size() != 1) {
@@ -5360,8 +5378,10 @@ protected void rewriteOrderByAll(SqlSelect select) {
     for (SqlNode selectItem : select.getSelectList()) {
       final SqlNode expr = SqlUtil.stripAs(selectItem);
       if (expr instanceof SqlIdentifier && ((SqlIdentifier) expr).isStar()) {
-        throw newValidationError(expr,
-            RESOURCE.orderByAllRequiresExplicitSelectList());
+        for (SqlNode column : expandStarForAllRewrite(select, expr)) {
+          keys.add(applyOrderByAllDirection(column, desc, nulls, pos));
+        }
+        continue;
       }
       keys.add(applyOrderByAllDirection(expr, desc, nulls, pos));
     }
@@ -5561,8 +5581,12 @@ private void rewriteGroupByAll(SqlSelect select) {
       }
       final SqlNode expr = SqlUtil.stripAs(selectItem);
       if (expr instanceof SqlIdentifier && ((SqlIdentifier) expr).isStar()) {
-        throw newValidationError(expr,
-            RESOURCE.groupByAllRequiresExplicitSelectList());
+        for (SqlNode column : expandStarForAllRewrite(select, expr)) {
+          if (aggOrOverFinder.findAgg(column) == null) {
+            keys.add(column);
+          }
+        }
+        continue;
       }
       if (aggOrOverFinder.findAgg(expr) == null) {
         keys.add(expr);
diff --git 
a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties 
b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
index 636e117c7e..c90ac9c4ed 100644
--- 
a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
+++ 
b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
@@ -136,7 +136,6 @@ GroupingInWrongClause={0} operator may only occur in 
SELECT, HAVING or ORDER BY
 NotSelectDistinctExpr=Expression ''{0}'' is not in the select clause
 AggregateIllegalInClause=Aggregate expression is illegal in {0} clause
 WindowedAggregateIllegalInClause=Windowed aggregate expression is illegal in 
{0} clause
-GroupByAllRequiresExplicitSelectList=GROUP BY ALL requires an explicit SELECT 
list; ''*'' is not supported
 NestedAggIllegal=Aggregate expressions cannot be nested
 MeasureIllegal=Measure expressions can only occur within AGGREGATE function
 MeasureMustBeInAggregateQuery=Measure expressions can only occur within a 
GROUP BY query
@@ -261,7 +260,6 @@ CannotConvertToStream=Cannot convert table ''{0}'' to stream
 CannotConvertToRelation=Cannot convert stream ''{0}'' to relation
 StreamMustGroupByMonotonic=Streaming aggregation requires at least one 
monotonic expression in GROUP BY clause
 StreamMustOrderByMonotonic=Streaming ORDER BY must start with monotonic 
expression
-OrderByAllRequiresExplicitSelectList=ORDER BY ALL requires an explicit SELECT 
list; ''*'' is not supported
 StreamSetOpInconsistentInputs=Set operator cannot combine streaming and 
non-streaming inputs
 CannotStreamValues=Cannot stream VALUES
 CyclicDefinition=Cannot resolve ''{0}''; it references view ''{1}'', whose 
definition is cyclic
diff --git a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java 
b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
index 892d68f117..38f883743e 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -7366,9 +7366,17 @@ public boolean isBangEqualAllowed() {
     sql("select deptno, sal from emp order by all").ok();
     // direction applies to every expanded key
     sql("select deptno, sal from emp order by all desc").ok();
-    // SELECT * can't be expanded here
-    sql("select ^*^ from emp order by all")
-        .fails("(?s).*ORDER BY ALL requires an explicit SELECT list.*");
+    // SELECT * validates with ORDER BY ALL; what the star expands to as sort
+    // keys is asserted explicitly by rewritesTo below.
+    sql("select * from emp order by all").ok();
+    sql("select * from emp order by all desc").ok();
+    // Multiple qualified stars validate together (no cross-expansion error).
+    sql("select emp.*, dept.* from emp, dept order by all desc").ok();
+    // Show the expanded sort keys.
+    sql("select * from dept order by all")
+        .rewritesTo("SELECT *\n"
+            + "FROM `DEPT`\n"
+            + "ORDER BY `DEPT`.`DEPTNO`, `DEPT`.`NAME`");
     // Aliases that shadow other column names must not confuse expansion
     sql("select empno as deptno, deptno as empno from emp order by all").ok();
     // verify "x" still resolves and the two features coexist
@@ -7822,9 +7830,17 @@ public boolean isBangEqualAllowed() {
     // only aggregates -> global aggregation (one group), still valid
     sql("select count(*) from emp group by all").ok();
 
-    // SELECT * cannot be expanded at group-validation time -> clear error
-    sql("select ^*^ from emp group by all")
-        .fails("(?s).*GROUP BY ALL requires an explicit SELECT list.*");
+    // SELECT * validates with GROUP BY ALL; what the star expands to as
+    // grouping keys is asserted explicitly by rewritesTo below.
+    sql("select * from emp group by all").ok();
+    sql("select *, count(*) from emp group by all").ok();
+    sql("select * from emp natural join dept group by all").ok();
+    // Show the expanded grouping keys: GROUP BY ALL is replaced by the
+    // star's underlying columns (behavior validated against DuckDB).
+    sql("select * from dept group by all")
+        .rewritesTo("SELECT *\n"
+            + "FROM `DEPT`\n"
+            + "GROUP BY `DEPT`.`DEPTNO`, `DEPT`.`NAME`");
 
     // contains-an-aggregate
     sql("select deptno, substring(job, 1), count(*) + 1 as c, 'x' as x\n"
diff --git a/core/src/test/resources/sql/agg.iq 
b/core/src/test/resources/sql/agg.iq
index d6557e34f1..bc24ba6014 100644
--- a/core/src/test/resources/sql/agg.iq
+++ b/core/src/test/resources/sql/agg.iq
@@ -4688,4 +4688,35 @@ FROM emp;
 
 !use scott
 
+# [CALCITE-7647] Support SELECT * in GROUP BY ALL and ORDER BY ALL.
+# GROUP BY ALL expands SELECT * to every underlying column;
+# the star columns become grouping keys and the aggregate is excluded.
+select *, count(*) as c from (values (1, 'a'), (1, 'a'), (2, 'b')) as t(x, y)
+group by all
+order by x;
++---+---+---+
+| X | Y | C |
++---+---+---+
+| 1 | a | 2 |
+| 2 | b | 1 |
++---+---+---+
+(2 rows)
+
+!ok
+
+# [CALCITE-7647] GROUP BY ALL deduplicates a column that SELECT * and an
+# explicit reference both contribute to the grouping keys.
+select *, x from (values (1, 'a'), (1, 'a'), (2, 'b')) as t(x, y)
+group by all
+order by y;
++---+---+---+
+| X | Y | X |
++---+---+---+
+| 1 | a | 1 |
+| 2 | b | 2 |
++---+---+---+
+(2 rows)
+
+!ok
+
 # End agg.iq
diff --git a/core/src/test/resources/sql/sort.iq 
b/core/src/test/resources/sql/sort.iq
index 0e8d84cff9..a532047425 100644
--- a/core/src/test/resources/sql/sort.iq
+++ b/core/src/test/resources/sql/sort.iq
@@ -568,4 +568,19 @@ order by all;
 
 !ok
 
+# [CALCITE-7647] Support SELECT * in GROUP BY ALL and ORDER BY ALL.
+# ORDER BY ALL expands SELECT * to every underlying column.
+select * from (values (2, 'b'), (1, 'a'), (1, 'c')) as t(x, y)
+order by all;
++---+---+
+| X | Y |
++---+---+
+| 1 | a |
+| 1 | c |
+| 2 | b |
++---+---+
+(3 rows)
+
+!ok
+
 # End sort.iq
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index 71c067e27b..59ddce4af5 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -426,6 +426,9 @@ ## Grammar
 "SELECT x, y FROM t ORDER BY ALL" is equivalent to
 "SELECT x, y FROM t ORDER BY x, y"
 An optional trailing ASC / DESC and NULLS FIRST / NULLS LAST applies to all 
keys.
+A `*` in the SELECT clause is expanded to its underlying columns, each of which
+becomes a sort key; for example, "SELECT * FROM t ORDER BY ALL" sorts by every
+column of `t`.
 
 In *query*, *start* may be either an unsigned numeric literal or a dynamic
 parameter whose value is numeric. The *count* in a LIMIT clause may be either
@@ -468,6 +471,9 @@ ## Grammar
 that is not an aggregate function; for example,
 "SELECT deptno, SUM(sal) FROM emp GROUP BY ALL" is equivalent to
 "SELECT deptno, SUM(sal) FROM emp GROUP BY deptno".
+A `*` in the SELECT clause is expanded to its underlying columns, each of which
+becomes a grouping key; for example,
+"SELECT *, COUNT(*) FROM emp GROUP BY ALL" groups by every column of `emp`.
 
 *selectWithoutFrom* is equivalent to VALUES,
 but is not standard SQL and is only allowed in certain

Reply via email to