[CALCITE-2661] In RelBuilder, add methods for creating Exchange and 
SortExchange relational expressions (Chunwei Lei)

Close apache/calcite#910


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/1d292910
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/1d292910
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/1d292910

Branch: refs/heads/master
Commit: 1d2929105f47b944c65529fe59b3072cce167116
Parents: 6d9242a
Author: chunwei.lcw <[email protected]>
Authored: Fri Nov 9 11:30:29 2018 +0800
Committer: Julian Hyde <[email protected]>
Committed: Mon Nov 12 13:54:38 2018 -0800

----------------------------------------------------------------------
 .../org/apache/calcite/rel/core/Exchange.java   |  2 +-
 .../apache/calcite/rel/core/RelFactories.java   | 60 +++++++++++++++++
 .../rel/logical/LogicalSortExchange.java        | 68 ++++++++++++++++++++
 .../org/apache/calcite/tools/RelBuilder.java    | 25 +++++++
 .../org/apache/calcite/test/RelBuilderTest.java | 26 ++++++++
 site/_docs/algebra.md                           |  4 ++
 6 files changed, 184 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/1d292910/core/src/main/java/org/apache/calcite/rel/core/Exchange.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Exchange.java 
b/core/src/main/java/org/apache/calcite/rel/core/Exchange.java
index 221740b..ebb17f2 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Exchange.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Exchange.java
@@ -65,7 +65,7 @@ public abstract class Exchange extends SingleRel {
   }
 
   /**
-   * Creates a Exchange by parsing serialized output.
+   * Creates an Exchange by parsing serialized output.
    */
   public Exchange(RelInput input) {
     this(input.getCluster(), input.getTraitSet().plus(input.getCollation()),

http://git-wip-us.apache.org/repos/asf/calcite/blob/1d292910/core/src/main/java/org/apache/calcite/rel/core/RelFactories.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/RelFactories.java 
b/core/src/main/java/org/apache/calcite/rel/core/RelFactories.java
index 8baef30..c7e290c 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/RelFactories.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/RelFactories.java
@@ -22,9 +22,11 @@ import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.plan.ViewExpanders;
 import org.apache.calcite.rel.RelCollation;
+import org.apache.calcite.rel.RelDistribution;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.logical.LogicalAggregate;
 import org.apache.calcite.rel.logical.LogicalCorrelate;
+import org.apache.calcite.rel.logical.LogicalExchange;
 import org.apache.calcite.rel.logical.LogicalFilter;
 import org.apache.calcite.rel.logical.LogicalIntersect;
 import org.apache.calcite.rel.logical.LogicalJoin;
@@ -32,6 +34,7 @@ import org.apache.calcite.rel.logical.LogicalMatch;
 import org.apache.calcite.rel.logical.LogicalMinus;
 import org.apache.calcite.rel.logical.LogicalProject;
 import org.apache.calcite.rel.logical.LogicalSort;
+import org.apache.calcite.rel.logical.LogicalSortExchange;
 import org.apache.calcite.rel.logical.LogicalTableScan;
 import org.apache.calcite.rel.logical.LogicalUnion;
 import org.apache.calcite.rel.logical.LogicalValues;
@@ -75,6 +78,12 @@ public class RelFactories {
   public static final SortFactory DEFAULT_SORT_FACTORY =
       new SortFactoryImpl();
 
+  public static final ExchangeFactory DEFAULT_EXCHANGE_FACTORY =
+      new ExchangeFactoryImpl();
+
+  public static final SortExchangeFactory DEFAULT_SORT_EXCHANGE_FACTORY =
+      new SortExchangeFactoryImpl();
+
   public static final AggregateFactory DEFAULT_AGGREGATE_FACTORY =
       new AggregateFactoryImpl();
 
@@ -99,6 +108,8 @@ public class RelFactories {
               DEFAULT_JOIN_FACTORY,
               DEFAULT_SEMI_JOIN_FACTORY,
               DEFAULT_SORT_FACTORY,
+              DEFAULT_EXCHANGE_FACTORY,
+              DEFAULT_SORT_EXCHANGE_FACTORY,
               DEFAULT_AGGREGATE_FACTORY,
               DEFAULT_MATCH_FACTORY,
               DEFAULT_SET_OP_FACTORY,
@@ -162,6 +173,55 @@ public class RelFactories {
   }
 
   /**
+   * Can create a {@link org.apache.calcite.rel.core.Exchange}
+   * of the appropriate type for a rule's calling convention.
+   */
+  public interface ExchangeFactory {
+    /** Creates a Exchange. */
+    RelNode createExchange(RelNode input, RelDistribution distribution);
+  }
+
+  /**
+   * Implementation of
+   * {@link RelFactories.ExchangeFactory}
+   * that returns a {@link Exchange}.
+   */
+  private static class ExchangeFactoryImpl implements ExchangeFactory {
+    @Override public RelNode createExchange(
+        RelNode input, RelDistribution distribution) {
+      return LogicalExchange.create(input, distribution);
+    }
+  }
+
+  /**
+   * Can create a {@link SortExchange}
+   * of the appropriate type for a rule's calling convention.
+   */
+  public interface SortExchangeFactory {
+    /**
+     * Creates a {@link SortExchange}.
+     */
+    RelNode createSortExchange(
+        RelNode input,
+        RelDistribution distribution,
+        RelCollation collation);
+  }
+
+  /**
+   * Implementation of
+   * {@link RelFactories.SortExchangeFactory}
+   * that returns a {@link SortExchange}.
+   */
+  private static class SortExchangeFactoryImpl implements SortExchangeFactory {
+    @Override public RelNode createSortExchange(
+        RelNode input,
+        RelDistribution distribution,
+        RelCollation collation) {
+      return LogicalSortExchange.create(input, distribution, collation);
+    }
+  }
+
+  /**
    * Can create a {@link SetOp} for a particular kind of
    * set operation (UNION, EXCEPT, INTERSECT) and of the appropriate type
    * for this rule's calling convention.

http://git-wip-us.apache.org/repos/asf/calcite/blob/1d292910/core/src/main/java/org/apache/calcite/rel/logical/LogicalSortExchange.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/calcite/rel/logical/LogicalSortExchange.java 
b/core/src/main/java/org/apache/calcite/rel/logical/LogicalSortExchange.java
new file mode 100644
index 0000000..73a066a
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalSortExchange.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.rel.logical;
+
+import org.apache.calcite.plan.Convention;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelCollation;
+import org.apache.calcite.rel.RelCollationTraitDef;
+import org.apache.calcite.rel.RelDistribution;
+import org.apache.calcite.rel.RelDistributionTraitDef;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.SortExchange;
+
+/**
+ * Sub-class of {@link org.apache.calcite.rel.core.SortExchange} not
+ * targeted at any particular engine or calling convention.
+ */
+public class LogicalSortExchange extends SortExchange {
+  private LogicalSortExchange(RelOptCluster cluster, RelTraitSet traitSet,
+      RelNode input, RelDistribution distribution, RelCollation collation) {
+    super(cluster, traitSet, input, distribution, collation);
+  }
+
+  /**
+   * Creates a LogicalSortExchange.
+   *
+   * @param input     Input relational expression
+   * @param distribution Distribution specification
+   * @param collation array of sort specifications
+   */
+  public static LogicalSortExchange create(
+      RelNode input,
+      RelDistribution distribution,
+      RelCollation collation) {
+    RelOptCluster cluster = input.getCluster();
+    collation = RelCollationTraitDef.INSTANCE.canonize(collation);
+    distribution = RelDistributionTraitDef.INSTANCE.canonize(distribution);
+    RelTraitSet traitSet =
+        
input.getTraitSet().replace(Convention.NONE).replace(distribution).replace(collation);
+    return new LogicalSortExchange(cluster, traitSet, input, distribution,
+        collation);
+  }
+
+  //~ Methods ----------------------------------------------------------------
+
+  @Override public SortExchange copy(RelTraitSet traitSet, RelNode newInput,
+      RelDistribution newDistribution, RelCollation newCollation) {
+    return new LogicalSortExchange(this.getCluster(), traitSet, newInput,
+        newDistribution, newCollation);
+  }
+}
+
+// End LogicalSortExchange.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/1d292910/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
----------------------------------------------------------------------
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 3b0be9c..9b7a6e9 100644
--- a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
+++ b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
@@ -27,6 +27,7 @@ import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.rel.RelCollation;
 import org.apache.calcite.rel.RelCollations;
+import org.apache.calcite.rel.RelDistribution;
 import org.apache.calcite.rel.RelFieldCollation;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.Aggregate;
@@ -133,6 +134,8 @@ public class RelBuilder {
   private final RelFactories.ProjectFactory projectFactory;
   private final RelFactories.AggregateFactory aggregateFactory;
   private final RelFactories.SortFactory sortFactory;
+  private final RelFactories.ExchangeFactory exchangeFactory;
+  private final RelFactories.SortExchangeFactory sortExchangeFactory;
   private final RelFactories.SetOpFactory setOpFactory;
   private final RelFactories.JoinFactory joinFactory;
   private final RelFactories.SemiJoinFactory semiJoinFactory;
@@ -164,6 +167,12 @@ public class RelBuilder {
     this.sortFactory =
         Util.first(context.unwrap(RelFactories.SortFactory.class),
             RelFactories.DEFAULT_SORT_FACTORY);
+    this.exchangeFactory =
+        Util.first(context.unwrap(RelFactories.ExchangeFactory.class),
+            RelFactories.DEFAULT_EXCHANGE_FACTORY);
+    this.sortExchangeFactory =
+        Util.first(context.unwrap(RelFactories.SortExchangeFactory.class),
+            RelFactories.DEFAULT_SORT_EXCHANGE_FACTORY);
     this.setOpFactory =
         Util.first(context.unwrap(RelFactories.SetOpFactory.class),
             RelFactories.DEFAULT_SET_OP_FACTORY);
@@ -1883,6 +1892,22 @@ public class RelBuilder {
     return sortLimit(offset, fetch, ImmutableList.of());
   }
 
+  /** Creates an Exchange by distribution. */
+  public RelBuilder exchange(RelDistribution distribution) {
+    RelNode exchange = exchangeFactory.createExchange(peek(), distribution);
+    replaceTop(exchange);
+    return this;
+  }
+
+  /** Creates a SortExchange by distribution and collation. */
+  public RelBuilder sortExchange(RelDistribution distribution,
+      RelCollation collation) {
+    RelNode exchange = sortExchangeFactory
+        .createSortExchange(peek(), distribution, collation);
+    replaceTop(exchange);
+    return this;
+  }
+
   /** Creates a {@link Sort} by field ordinals.
    *
    * <p>Negative fields mean descending: -1 means field(0) descending,

http://git-wip-us.apache.org/repos/asf/calcite/blob/1d292910/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
----------------------------------------------------------------------
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 e3d5b95..e6cfe62 100644
--- a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
@@ -20,6 +20,8 @@ import org.apache.calcite.jdbc.CalciteConnection;
 import org.apache.calcite.plan.Contexts;
 import org.apache.calcite.plan.RelOptTable;
 import org.apache.calcite.plan.RelTraitDef;
+import org.apache.calcite.rel.RelCollations;
+import org.apache.calcite.rel.RelDistributions;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.AggregateCall;
 import org.apache.calcite.rel.core.Correlate;
@@ -2276,6 +2278,30 @@ public class RelBuilderTest {
             .build();
     assertThat(root, matcher);
   }
+
+  @Test public void testExchange() {
+    final RelBuilder builder = RelBuilder.create(config().build());
+    final RelNode root = builder.scan("EMP")
+        .exchange(RelDistributions.hash(Lists.newArrayList(0)))
+        .build();
+    final String expected =
+        "LogicalExchange(distribution=[hash[0]])\n"
+            + "  LogicalTableScan(table=[[scott, EMP]])\n";
+    assertThat(root, hasTree(expected));
+  }
+
+  @Test public void testSortExchange() {
+    final RelBuilder builder = RelBuilder.create(config().build());
+    final RelNode root =
+        builder.scan("EMP")
+            .sortExchange(RelDistributions.hash(Lists.newArrayList(0)),
+                RelCollations.of(0))
+            .build();
+    final String expected =
+        "LogicalSortExchange(distribution=[hash[0]], collation=[[0]])\n"
+            + "  LogicalTableScan(table=[[scott, EMP]])\n";
+    assertThat(root, hasTree(expected));
+  }
 }
 
 // End RelBuilderTest.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/1d292910/site/_docs/algebra.md
----------------------------------------------------------------------
diff --git a/site/_docs/algebra.md b/site/_docs/algebra.md
index 8ff2339..4c45f39 100644
--- a/site/_docs/algebra.md
+++ b/site/_docs/algebra.md
@@ -270,6 +270,8 @@ return the `RelBuilder`.
 | `sort(fieldOrdinal...)`<br/>`sort(expr...)`<br/>`sort(exprList)` | Creates a 
[Sort]({{ site.apiRoot }}/org/apache/calcite/rel/core/Sort.html).<br/><br/>In 
the first form, field ordinals are 0-based, and a negative ordinal indicates 
descending; for example, -2 means field 1 descending.<br/><br/>In the other 
forms, you can wrap expressions in `as`, `nullsFirst` or `nullsLast`.
 | `sortLimit(offset, fetch, expr...)`<br/>`sortLimit(offset, fetch, exprList)` 
| Creates a [Sort]({{ site.apiRoot }}/org/apache/calcite/rel/core/Sort.html) 
with offset and limit.
 | `limit(offset, fetch)` | Creates a [Sort]({{ site.apiRoot 
}}/org/apache/calcite/rel/core/Sort.html) that does not sort, only applies with 
offset and limit.
+| `exchange(distribution)` | Creates an [Exchange]({{ site.apiRoot 
}}/org/apache/calcite/rel/core/Exchange.html).
+| `sortExchange(distribution, collation)` | Creates a [SortExchange]({{ 
site.apiRoot }}/org/apache/calcite/rel/core/SortExchange.html).
 | `join(joinType, expr...)`<br/>`join(joinType, exprList)`<br/>`join(joinType, 
fieldName...)` | Creates a [Join]({{ site.apiRoot 
}}/org/apache/calcite/rel/core/Join.html) of the two most recent relational 
expressions.<br/><br/>The first form joins on a boolean expression (multiple 
conditions are combined using AND).<br/><br/>The last form joins on named 
fields; each side must have a field of each name.
 | `semiJoin(expr)` | Creates a [SemiJoin]({{ site.apiRoot 
}}/org/apache/calcite/rel/core/SemiJoin.html) of the two most recent relational 
expressions.
 | `union(all [, n])` | Creates a [Union]({{ site.apiRoot 
}}/org/apache/calcite/rel/core/Union.html) of the `n` (default two) most recent 
relational expressions.
@@ -299,6 +301,8 @@ Argument types:
 * `varHolder` [Holder]({{ site.apiRoot }}/org/apache/calcite/util/Holder.html) 
of [RexCorrelVariable]({{ site.apiRoot 
}}/org/apache/calcite/rex/RexCorrelVariable.html)
 * `patterns` Map whose key is String, value is [RexNode]({{ site.apiRoot 
}}/org/apache/calcite/rex/RexNode.html)
 * `subsets` Map whose key is String, value is a sorted set of String
+* `distribution` [RelDistribution]({{ site.apiRoot 
}}/org/apache/calcite/rel/RelDistribution.html)
+* `collation` [RelCollation]({{ site.apiRoot 
}}/org/apache/calcite/rel/RelCollation.html)
 
 The builder methods perform various optimizations, including:
 

Reply via email to