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 a7c1e8ac77 [CALCITE-6370] AS operator problems with USING clause
a7c1e8ac77 is described below
commit a7c1e8ac774f0ca602ed598f9dd0aef99ca7ad23
Author: Norman Jordan <[email protected]>
AuthorDate: Thu May 23 11:00:48 2024 -0700
[CALCITE-6370] AS operator problems with USING clause
* Detect when a nested AS call is inserted and prevent it
---
.../calcite/sql/validate/SqlValidatorImpl.java | 43 +++++++++++++++++++---
.../calcite/rel/rel2sql/RelToSqlConverterTest.java | 15 ++++++++
2 files changed, 53 insertions(+), 5 deletions(-)
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 a0e970fadb..f9d9e951df 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
@@ -47,6 +47,7 @@ import org.apache.calcite.sql.JoinType;
import org.apache.calcite.sql.SqlAccessEnum;
import org.apache.calcite.sql.SqlAccessType;
import org.apache.calcite.sql.SqlAggFunction;
+import org.apache.calcite.sql.SqlAsOperator;
import org.apache.calcite.sql.SqlBasicCall;
import org.apache.calcite.sql.SqlCall;
import org.apache.calcite.sql.SqlCallBinding;
@@ -118,6 +119,7 @@ import org.apache.calcite.util.Util;
import org.apache.calcite.util.trace.CalciteTrace;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
@@ -514,6 +516,8 @@ public class SqlValidatorImpl implements
SqlValidatorWithHints {
return identifier;
}
+ final Map<String, String> fieldAliases = getFieldAliases(scope);
+
for (String name
: SqlIdentifier.simpleNames((SqlNodeList) getCondition(join))) {
if (identifier.getSimple().equals(name)) {
@@ -529,11 +533,20 @@ public class SqlValidatorImpl implements
SqlValidatorWithHints {
}
assert qualifiedNode.size() == 2;
- return SqlStdOperatorTable.AS.createCall(SqlParserPos.ZERO,
- SqlStdOperatorTable.COALESCE.createCall(SqlParserPos.ZERO,
- qualifiedNode.get(0),
- qualifiedNode.get(1)),
- new SqlIdentifier(name, SqlParserPos.ZERO));
+
+ // If there is an alias for the column, no need to wrap the coalesce
with an AS operator
+ boolean haveAlias = fieldAliases.containsKey(name);
+
+ final SqlCall coalesceCall =
+ SqlStdOperatorTable.COALESCE.createCall(SqlParserPos.ZERO,
qualifiedNode.get(0),
+ qualifiedNode.get(1));
+
+ if (haveAlias) {
+ return coalesceCall;
+ } else {
+ return SqlStdOperatorTable.AS.createCall(SqlParserPos.ZERO,
coalesceCall,
+ new SqlIdentifier(name, SqlParserPos.ZERO));
+ }
}
}
@@ -547,6 +560,26 @@ public class SqlValidatorImpl implements
SqlValidatorWithHints {
}
}
+ private static Map<String, String> getFieldAliases(final SelectScope scope) {
+ final ImmutableMap.Builder<String, String> fieldAliases = new
ImmutableMap.Builder<>();
+
+ for (SqlNode selectItem : scope.getNode().getSelectList()) {
+ if (selectItem instanceof SqlCall) {
+ final SqlCall call = (SqlCall) selectItem;
+ if (!(call.getOperator() instanceof SqlAsOperator)
+ || !(call.operand(0) instanceof SqlIdentifier)) {
+ continue;
+ }
+
+ final SqlIdentifier fieldIdentifier = call.operand(0);
+ fieldAliases.put(fieldIdentifier.getSimple(),
+ ((SqlIdentifier) call.operand(1)).getSimple());
+ }
+ }
+
+ return fieldAliases.build();
+ }
+
/** Returns the set of field names in the join condition specified by USING
* or implicitly by NATURAL, de-duplicated and in order. */
public @Nullable List<String> usingNames(SqlJoin join) {
diff --git
a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
index 16c1011e0d..60285257b9 100644
---
a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
+++
b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
@@ -8260,6 +8260,21 @@ class RelToSqlConverterTest {
sql(query).withStarRocks().ok(expectedStarRocks);
}
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-6370">[CALCITE-6370]
+ * AS operator problems with USING clause</a>.
+ */
+ @Test void testUsingClauseWithAsInProjection() {
+ String query = "select \"product_id\" AS \"x\" from
\"foodmart\".\"product\" p0 join "
+ + " \"foodmart\".\"product\" p1 using (\"product_id\")";
+ String expectedQuery = "SELECT \"product\".\"product_id\" AS \"x\"\n"
+ + "FROM \"foodmart\".\"product\"\n"
+ + "INNER JOIN \"foodmart\".\"product\" AS \"product0\" ON "
+ + "\"product\".\"product_id\" = \"product0\".\"product_id\"";
+ sql(query)
+ .withPostgresql().ok(expectedQuery);
+ }
+
/** Fluid interface to run tests. */
static class Sql {
private final CalciteAssert.SchemaSpec schemaSpec;