This is an automated email from the ASF dual-hosted git repository.
mbudiu 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 b5057b7bd5 [CALCITE-7072] Validator should not insert aliases on
subexpressions
b5057b7bd5 is described below
commit b5057b7bd5192bdb723808af75612e06f55afc4f
Author: Mihai Budiu <[email protected]>
AuthorDate: Tue Jun 24 21:52:32 2025 -0700
[CALCITE-7072] Validator should not insert aliases on subexpressions
Signed-off-by: Mihai Budiu <[email protected]>
---
.../validate/implicit/AbstractTypeCoercion.java | 6 +++-
.../org/apache/calcite/test/SqlValidatorTest.java | 32 ++++++++++++++++++++++
2 files changed, 37 insertions(+), 1 deletion(-)
diff --git
a/core/src/main/java/org/apache/calcite/sql/validate/implicit/AbstractTypeCoercion.java
b/core/src/main/java/org/apache/calcite/sql/validate/implicit/AbstractTypeCoercion.java
index 396044eacf..fe882eac75 100644
---
a/core/src/main/java/org/apache/calcite/sql/validate/implicit/AbstractTypeCoercion.java
+++
b/core/src/main/java/org/apache/calcite/sql/validate/implicit/AbstractTypeCoercion.java
@@ -40,6 +40,7 @@
import org.apache.calcite.sql.type.SqlTypeMappingRule;
import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.calcite.sql.type.SqlTypeUtil;
+import org.apache.calcite.sql.validate.SelectScope;
import org.apache.calcite.sql.validate.SqlValidator;
import org.apache.calcite.sql.validate.SqlValidatorNamespace;
import org.apache.calcite.sql.validate.SqlValidatorScope;
@@ -213,7 +214,10 @@ protected boolean coerceColumnType(
}
RelDataType targetType3 = syncAttributes(validator.deriveType(scope,
node), targetType);
SqlNode node3 = castTo(node, targetType3);
- if (node.getKind() == SqlKind.IDENTIFIER) {
+ // Preserve the original column name as an alias only if 'node' is an item
in a select list.
+ boolean isSelectItem = (scope instanceof SelectScope)
+ && ((SelectScope) scope).getNode().getSelectList() == nodeList;
+ if (node.getKind() == SqlKind.IDENTIFIER && isSelectItem) {
SqlIdentifier id = (SqlIdentifier) node;
String name = id.getComponent(id.names.size() - 1).getSimple();
node3 = SqlValidatorUtil.addAlias(node3, name);
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 8470bb61d1..ec4cd2b84b 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -25,6 +25,8 @@
import org.apache.calcite.rel.type.RelDataTypeSystem;
import org.apache.calcite.rel.type.TimeFrameSet;
import org.apache.calcite.runtime.CalciteContextException;
+import org.apache.calcite.sql.SqlAsOperator;
+import org.apache.calcite.sql.SqlBasicCall;
import org.apache.calcite.sql.SqlBasicFunction;
import org.apache.calcite.sql.SqlCall;
import org.apache.calcite.sql.SqlCollation;
@@ -38,6 +40,7 @@
import org.apache.calcite.sql.SqlOperatorTable;
import org.apache.calcite.sql.SqlSelect;
import org.apache.calcite.sql.SqlSpecialOperator;
+import org.apache.calcite.sql.fun.SqlCase;
import org.apache.calcite.sql.fun.SqlLibrary;
import org.apache.calcite.sql.fun.SqlLibraryOperatorTableFactory;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
@@ -5935,6 +5938,35 @@ void testReturnsCorrectRowTypeOnCombinedJoin() {
.fails("(?s).*Encountered \"\\( true\" at .*");
}
+ /** Test case for <a
href="https://issues.apache.org/jira/browse/CALCITE-7072">[CALCITE-7072]
+ * Validator should not insert aliases on subexpressions</a>. */
+ @Test void testCaseCast() throws CalciteContextException, SqlParseException {
+ final String sql = "SELECT CASE WHEN deptno IS NOT NULL THEN empno\n"
+ + "ELSE CAST(deptno AS VARCHAR) END AS ID FROM emp";
+ final SqlParser.Config config = SqlParser.config();
+ final String messagePassingSqlString;
+ final SqlParser sqlParserReader = SqlParser.create(sql, config);
+ final SqlNode node = sqlParserReader.parseQuery();
+ final SqlValidator validator = fixture().factory
+ .withValidatorConfig(c -> c.withIdentifierExpansion(true))
+ .createValidator();
+ final SqlNode x = validator.validate(node);
+ assert x instanceof SqlSelect;
+ SqlSelect select = (SqlSelect) x;
+ SqlNode item = select.getSelectList().get(0);
+ assert item instanceof SqlBasicCall;
+ SqlBasicCall call = (SqlBasicCall) item;
+ assert call.getOperandList().size() == 2;
+ SqlNode op0 = call.getOperandList().get(0);
+ assert op0 instanceof SqlCase;
+ SqlCase caseStat = (SqlCase) op0;
+ assert caseStat.getThenOperands().size() == 1;
+ SqlNode then = caseStat.getThenOperands().get(0);
+ assert then instanceof SqlBasicCall;
+ SqlOperator operator = ((SqlBasicCall) then).getOperator();
+ assert !(operator instanceof SqlAsOperator);
+ }
+
@Disabled("bug: should fail if sub-query does not have alias")
@Test void testJoinSubQuery() {
// Sub-queries require alias