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

zhenchen 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 ca7be004f1 [CALCITE-7332] SELECT * EXCLUDE list should error when it 
excludes all columns
ca7be004f1 is described below

commit ca7be004f1a01749bab13d0cb0124d87e7fd092f
Author: Zhen Chen <[email protected]>
AuthorDate: Sat Dec 13 10:35:30 2025 +0800

    [CALCITE-7332] SELECT * EXCLUDE list should error when it excludes all 
columns
---
 .../java/org/apache/calcite/test/BabelTest.java     | 21 +++++++++++++++++++++
 .../org/apache/calcite/runtime/CalciteResource.java |  3 +++
 .../calcite/sql/validate/SqlValidatorImpl.java      | 15 +++++++++++++++
 .../calcite/runtime/CalciteResource.properties      |  1 +
 4 files changed, 40 insertions(+)

diff --git a/babel/src/test/java/org/apache/calcite/test/BabelTest.java 
b/babel/src/test/java/org/apache/calcite/test/BabelTest.java
index 9368a7ab71..261bcb2479 100644
--- a/babel/src/test/java/org/apache/calcite/test/BabelTest.java
+++ b/babel/src/test/java/org/apache/calcite/test/BabelTest.java
@@ -210,6 +210,27 @@ names, is(
         });
   }
 
+  /** Test case for <a 
href="https://issues.apache.org/jira/browse/CALCITE-7332";>[CALCITE-7332]
+   * SELECT * EXCLUDE list should error when it excludes all columns</a>. */
+  @Test void testStarExcludeWithEmptyColumn() {
+    final SqlValidatorFixture fixture = Fixtures.forValidator()
+        .withParserConfig(p -> 
p.withParserFactory(SqlBabelParserImpl.FACTORY));
+
+    // To verify the scenario where all columns in the exclude list exist
+    // and the number of columns in the list is equal to the number of columns 
in the table.
+    fixture.withSql("select * exclude(deptno, deptno) from dept")
+        .type(type -> {
+          final List<String> names = type.getFieldList().stream()
+              .map(RelDataTypeField::getName)
+              .collect(Collectors.toList());
+          assertThat(names, is(ImmutableList.of("NAME")));
+        });
+
+    // To verify that the exclude list contains all columns in the table
+    fixture.withSql("select ^*^ exclude(deptno, name) from dept")
+        .fails("SELECT \\* EXCLUDE list cannot exclude all columns");
+  }
+
   /** Tests that DATEADD, DATEDIFF, DATEPART, DATE_PART allow custom time
    * frames. */
   @Test void testTimeFrames() {
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 d35f1a030e..6769f68283 100644
--- a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
+++ b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
@@ -813,6 +813,9 @@ ExInst<CalciteException> 
illegalArgumentForTableFunctionCall(String a0,
   @BaseMessage("SELECT * EXCLUDE list contains unknown column(s): {0}")
   ExInst<SqlValidatorException> 
selectStarExcludeListContainsUnknownColumns(String columns);
 
+  @BaseMessage("SELECT * EXCLUDE list cannot exclude all columns")
+  ExInst<SqlValidatorException> selectStarExcludeCannotExcludeAllColumns();
+
   @BaseMessage("Group function ''{0}'' can only appear in GROUP BY clause")
   ExInst<SqlValidatorException> groupFunctionMustAppearInGroupByClause(String 
funcName);
 
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 172921babf..fd737039c4 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
@@ -662,6 +662,7 @@ private boolean expandStar(List<SqlNode> selectItems, 
Set<String> aliases,
         scope.validator.catalogReader.nameMatcher();
     final int originalSize = selectItems.size();
     final SqlParserPos startPosition = identifier.getParserPosition();
+    final int fieldsBeforeStar = fields.size();
     switch (identifier.names.size()) {
     case 1:
       SqlNode from = scope.getNode().getFrom();
@@ -739,6 +740,8 @@ private boolean expandStar(List<SqlNode> selectItems, 
Set<String> aliases,
         new Permute(from, offset).permute(selectItems, fields);
       }
       throwIfUnknownExcludeColumns(excludeIdentifiers, excludeMatched);
+      throwIfExcludeEliminatesAllColumns(excludeIdentifiers, fieldsBeforeStar,
+          fields, identifier);
       return true;
 
     default:
@@ -789,6 +792,8 @@ private boolean expandStar(List<SqlNode> selectItems, 
Set<String> aliases,
         throw newValidationError(prefixId, RESOURCE.starRequiresRecordType());
       }
       throwIfUnknownExcludeColumns(excludeIdentifiers, excludeMatched);
+      throwIfExcludeEliminatesAllColumns(excludeIdentifiers, fieldsBeforeStar,
+          fields, identifier);
       return true;
     }
   }
@@ -885,6 +890,16 @@ private void 
throwIfUnknownExcludeColumns(List<SqlIdentifier> excludeIdentifiers
     }
   }
 
+  private void throwIfExcludeEliminatesAllColumns(List<SqlIdentifier> 
excludeIdentifiers,
+      int fieldsBeforeStar, PairList<String, RelDataType> fields,
+      SqlIdentifier identifier) {
+    if (!excludeIdentifiers.isEmpty()
+        && fields.size() == fieldsBeforeStar) {
+      throw newValidationError(identifier,
+          RESOURCE.selectStarExcludeCannotExcludeAllColumns());
+    }
+  }
+
   private SqlNode maybeCast(SqlNode node, RelDataType currentType,
       RelDataType desiredType) {
     return SqlTypeUtil.equalSansNullability(typeFactory, currentType, 
desiredType)
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 4cc492795e..25531dd2cd 100644
--- 
a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
+++ 
b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
@@ -268,6 +268,7 @@ SelectMissingFrom=SELECT must have a FROM clause
 SelectStarRequiresFrom=SELECT * requires a FROM clause
 SelectExcludeRequiresStar=EXCLUDE clause must follow a STAR expression
 SelectStarExcludeListContainsUnknownColumns=SELECT * EXCLUDE list contains 
unknown column(s): {0}
+SelectStarExcludeCannotExcludeAllColumns=SELECT * EXCLUDE list cannot exclude 
all columns
 GroupFunctionMustAppearInGroupByClause=Group function ''{0}'' can only appear 
in GROUP BY clause
 AuxiliaryWithoutMatchingGroupCall=Call to auxiliary group function ''{0}'' 
must have matching call to group function ''{1}'' in GROUP BY clause
 PivotAggMalformed=Measure expression in PIVOT must use aggregate function

Reply via email to