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