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

libenchao 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 cb34e78c23 [CALCITE-5530] RelToSqlConverter[ORDER BY] generates an 
incorrect field alias when 2 projection fields have the same name
cb34e78c23 is described below

commit cb34e78c2305663cd3e2da06acf4ba7ad797947e
Author: xiejiajun <[email protected]>
AuthorDate: Sun Feb 26 17:15:55 2023 +0800

    [CALCITE-5530] RelToSqlConverter[ORDER BY] generates an incorrect field 
alias when 2 projection fields have the same name
    
    Close apache/calcite#3085
---
 .../apache/calcite/rel/rel2sql/SqlImplementor.java |  9 +--
 .../calcite/rel/rel2sql/RelToSqlConverterTest.java | 72 ++++++++++++++++++++++
 2 files changed, 77 insertions(+), 4 deletions(-)

diff --git 
a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java 
b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
index 6af0bd989e..69e6dac5e8 100644
--- a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
+++ b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
@@ -1758,7 +1758,7 @@ public abstract class SqlImplementor {
                 if (selectItem.i != ordinal) {
                   final @Nullable String alias =
                       SqlValidatorUtil.alias(selectItem.e);
-                  if (name.equalsIgnoreCase(alias)) {
+                  if (name.equalsIgnoreCase(alias) && 
dialect.getConformance().isSortByAlias()) {
                     return SqlLiteral.createExactNumeric(
                         Integer.toString(ordinal + 1), SqlParserPos.ZERO);
                   }
@@ -1825,9 +1825,10 @@ public abstract class SqlImplementor {
 
       if (rel instanceof Project
           && clauses.contains(Clause.ORDER_BY)
-          && dialect.getConformance().isSortByOrdinal()) {
+          && dialect.getConformance().isSortByOrdinal()
+          && hasSortByOrdinal()) {
         // Cannot merge a Project that contains sort by ordinal under it.
-        return hasSortByOrdinal();
+        return true;
       }
 
       if (rel instanceof Aggregate) {
@@ -1862,7 +1863,7 @@ public abstract class SqlImplementor {
         }
         for (SqlNode sqlNode : orderList) {
           if (!(sqlNode instanceof SqlBasicCall)) {
-            return false;
+            return sqlNode instanceof SqlNumericLiteral;
           }
           for (SqlNode operand : ((SqlBasicCall) sqlNode).getOperandList()) {
             if (operand instanceof SqlNumericLiteral) {
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 4d146ec5d2..1d7431b922 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
@@ -877,6 +877,78 @@ class RelToSqlConverterTest {
         .withPresto().ok(expectedPresto);
   }
 
+  /**
+   * Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-5530";>[CALCITE-5530]
+   * RelToSqlConverter[ORDER BY] generates an incorrect field alias
+   * when 2 projection fields have the same name</a>.
+   */
+  @Test void 
testOrderByFieldNotInTheProjectionWithASameAliasAsThatInTheProjection() {
+    final RelBuilder builder = relBuilder();
+    final RelNode base = builder
+        .scan("EMP")
+        .project(
+            builder.alias(
+                builder.call(SqlStdOperatorTable.UPPER, 
builder.field("ENAME")), "EMPNO"),
+            builder.field("EMPNO")
+        )
+        .sort(1)
+        .project(builder.field(0))
+        .build();
+
+    // The expected string should deliberately have a subquery to handle a 
scenario in which
+    // the projection field has an alias with the same name as that of the 
field used in the
+    // ORDER BY
+    String expectedSql1 = ""
+        + "SELECT \"EMPNO\"\n"
+        + "FROM (SELECT UPPER(\"ENAME\") AS \"EMPNO\", \"EMPNO\" AS 
\"EMPNO0\"\n"
+        + "FROM \"scott\".\"EMP\"\n"
+        + "ORDER BY 2) AS \"t0\"";
+    String actualSql1 = toSql(base);
+    assertThat(actualSql1, isLinux(expectedSql1));
+
+    String actualSql2 = toSql(base, nonOrdinalDialect());
+    String expectedSql2 = "SELECT UPPER(ENAME) AS EMPNO\n"
+        + "FROM scott.EMP\n"
+        + "ORDER BY EMPNO";
+    assertThat(actualSql2, isLinux(expectedSql2));
+  }
+
+  @Test void 
testOrderByExpressionNotInTheProjectionThatRefersToUnderlyingFieldWithSameAlias()
 {
+    final RelBuilder builder = relBuilder();
+    final RelNode base = builder
+        .scan("EMP")
+        .project(
+            builder.alias(
+                builder.call(SqlStdOperatorTable.UPPER, 
builder.field("ENAME")), "EMPNO"),
+            builder.call(
+                SqlStdOperatorTable.PLUS, builder.field("EMPNO"),
+                builder.literal(1)
+            )
+        )
+        .sort(1)
+        .project(builder.field(0))
+        .build();
+
+    // An output such as
+    // "SELECT UPPER(\"ENAME\") AS \"EMPNO\"\nFROM \"scott\".\"EMP\"\nORDER BY 
\"EMPNO\" + 1"
+    // would be incorrect since the rel is sorting by the field \"EMPNO\" + 1 
in which EMPNO
+    // refers to the physical column EMPNO and not the alias
+    String actualSql1 = toSql(base);
+    String expectedSql1 = ""
+        + "SELECT \"EMPNO\"\n"
+        + "FROM (SELECT UPPER(\"ENAME\") AS \"EMPNO\", \"EMPNO\" + 1 AS 
\"$f1\"\n"
+        + "FROM \"scott\".\"EMP\"\n"
+        + "ORDER BY 2) AS \"t0\"";
+    assertThat(actualSql1, isLinux(expectedSql1));
+
+    String actualSql2 = toSql(base, nonOrdinalDialect());
+    String expectedSql2 = "SELECT UPPER(ENAME) AS EMPNO\n"
+        + "FROM scott.EMP\n"
+        + "ORDER BY EMPNO + 1";
+    assertThat(actualSql2, isLinux(expectedSql2));
+  }
+
   @Test void testSelectQueryWithMinAggregateFunction() {
     String query = "select min(\"net_weight\") from \"product\" group by 
\"product_class_id\" ";
     final String expected = "SELECT MIN(\"net_weight\")\n"

Reply via email to