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

jhyde pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git

commit aabcb2e5d1df0201fc8b5f3d99f9317bde6d49ae
Author: Julian Hyde <[email protected]>
AuthorDate: Mon Apr 29 17:12:49 2019 -0700

    [CALCITE-3096] In RelBuilder, make alias method idempotent
---
 .../java/org/apache/calcite/tools/RelBuilder.java  | 18 ++++++++++-
 .../org/apache/calcite/test/RelBuilderTest.java    | 36 +++++++++++++++++++++-
 2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java 
b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
index f73646a..a33b807 100644
--- a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
+++ b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
@@ -653,10 +653,26 @@ public class RelBuilder {
   /**
    * Returns an expression wrapped in an alias.
    *
+   * <p>This method is idempotent: If the expression is already wrapped in the
+   * correct alias, does nothing; if wrapped in an incorrect alias, removes
+   * the incorrect alias and applies the correct alias.
+   *
    * @see #project
    */
   public RexNode alias(RexNode expr, String alias) {
-    return call(SqlStdOperatorTable.AS, expr, literal(alias));
+    final RexNode aliasLiteral = literal(alias);
+    switch (expr.getKind()) {
+    case AS:
+      final RexCall call = (RexCall) expr;
+      if (call.operands.get(1).equals(aliasLiteral)) {
+        // current alias is correct
+        return expr;
+      }
+      expr = call.operands.get(0);
+      // strip current (incorrect) alias, and fall through
+    default:
+      return call(SqlStdOperatorTable.AS, expr, aliasLiteral);
+    }
   }
 
   /** Converts a sort expression to descending. */
diff --git a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java 
b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
index dc0240f..a9f7341 100644
--- a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
@@ -112,7 +112,6 @@ import static org.junit.Assert.fail;
  *      {@link RelBuilder#alias(RexNode, String)} is removed if not a top-level
  *      project</li>
  *   <li>{@link RelBuilder#aggregate} with grouping sets</li>
- *   <li>{@link RelBuilder#aggregateCall} with filter</li>
  *   <li>Add call to create {@link TableFunctionScan}</li>
  *   <li>Add call to create {@link Window}</li>
  *   <li>Add call to create {@link TableModify}</li>
@@ -1677,6 +1676,41 @@ public class RelBuilderTest {
     assertThat(root, hasTree(expected));
   }
 
+  /** Tests that the {@link RelBuilder#alias(RexNode, String)} function is
+   * idempotent. */
+  @Test public void testScanAlias() {
+    final RelBuilder builder = RelBuilder.create(config().build());
+    builder.scan("EMP");
+
+    // Simplify "emp.deptno as d as d" to "emp.deptno as d".
+    final RexNode e0 =
+        builder.alias(builder.alias(builder.field("DEPTNO"), "D"), "D");
+    assertThat(e0.toString(), is("AS($7, 'D')"));
+
+    // It would be nice if RelBuilder could simplify
+    // "emp.deptno as deptno" to "emp.deptno", but there is not
+    // enough information in RexInputRef.
+    final RexNode e1 = builder.alias(builder.field("DEPTNO"), "DEPTNO");
+    assertThat(e1.toString(), is("AS($7, 'DEPTNO')"));
+
+    // The intervening alias 'DEPTNO' is removed
+    final RexNode e2 =
+        builder.alias(builder.alias(builder.field("DEPTNO"), "DEPTNO"), "D1");
+    assertThat(e2.toString(), is("AS($7, 'D1')"));
+
+    // Simplify "emp.deptno as d2 as d3" to "emp.deptno as d3"
+    // because "d3" alias overrides "d2".
+    final RexNode e3 =
+        builder.alias(builder.alias(builder.field("DEPTNO"), "D2"), "D3");
+    assertThat(e3.toString(), is("AS($7, 'D3')"));
+
+    final RelNode root = builder.project(e0, e1, e2, e3).build();
+    final String expected = ""
+        + "LogicalProject(D=[$7], DEPTNO=[$7], D1=[$7], D3=[$7])\n"
+        + "  LogicalTableScan(table=[[scott, EMP]])\n";
+    assertThat(root, hasTree(expected));
+  }
+
   /**
    * Tests that project field name aliases are suggested incrementally.
    */

Reply via email to