[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:
