You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2015/07/07 19:58:35 UTC

[4/5] incubator-calcite git commit: In RelBuilder, calling sort then limit has same effect as calling sortLimit

In RelBuilder, calling sort then limit has same effect as calling sortLimit


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

Branch: refs/heads/master
Commit: 40c55fd463e4a249953bf298450110027d6c3bd6
Parents: d35df36
Author: Julian Hyde <jh...@apache.org>
Authored: Sun Jul 5 00:05:11 2015 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Jul 6 20:49:53 2015 -0700

----------------------------------------------------------------------
 .../org/apache/calcite/tools/RelBuilder.java    | 33 ++++++++++++
 .../org/apache/calcite/test/RelBuilderTest.java | 54 ++++++++++++++++++++
 2 files changed, 87 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/40c55fd4/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 f664baf..13cf96e 100644
--- a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
+++ b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
@@ -28,6 +28,7 @@ import org.apache.calcite.rel.RelFieldCollation;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.AggregateCall;
 import org.apache.calcite.rel.core.JoinRelType;
+import org.apache.calcite.rel.core.Project;
 import org.apache.calcite.rel.core.RelFactories;
 import org.apache.calcite.rel.core.Sort;
 import org.apache.calcite.rel.core.Values;
@@ -865,6 +866,38 @@ public class RelBuilder {
     final RexNode offsetNode = offset <= 0 ? null : literal(offset);
     final RexNode fetchNode = fetch < 0 ? null : literal(fetch);
     final boolean addedFields = extraNodes.size() > originalExtraNodes.size();
+    if (fieldCollations.isEmpty()) {
+      assert !addedFields;
+      RelNode top = peek();
+      if (top instanceof Sort) {
+        final Sort sort2 = (Sort) top;
+        if (sort2.offset == null && sort2.fetch == null) {
+          Stacks.pop(stack);
+          push(sort2.getInput());
+          final RelNode sort =
+              sortFactory.createSort(build(), sort2.collation,
+                  offsetNode, fetchNode);
+          push(sort);
+          return this;
+        }
+      }
+      if (top instanceof Project) {
+        final Project project = (Project) top;
+        if (project.getInput() instanceof Sort) {
+          final Sort sort2 = (Sort) project.getInput();
+          if (sort2.offset == null && sort2.fetch == null) {
+            Stacks.pop(stack);
+            push(sort2.getInput());
+            final RelNode sort =
+                sortFactory.createSort(build(), sort2.collation,
+                    offsetNode, fetchNode);
+            push(sort);
+            project(project.getProjects());
+            return this;
+          }
+        }
+      }
+    }
     if (addedFields) {
       project(extraNodes);
     }

http://git-wip-us.apache.org/repos/asf/incubator-calcite/blob/40c55fd4/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 0a2b990..0474590 100644
--- a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
@@ -625,6 +625,60 @@ public class RelBuilderTest {
             + "  LogicalTableScan(table=[[scott, EMP]])\n";
     assertThat(str(root), is(expected));
   }
+
+  /** Tests that a sort on a field followed by a limit gives the same
+   * effect as calling sortLimit.
+   *
+   * <p>In general a relational operator cannot rely on the order of its input,
+   * but it is reasonable to merge sort and limit if they were created by
+   * consecutive builder operations. And clients such as Piglet rely on it. */
+  @Test public void testSortThenLimit() {
+    final RelBuilder builder = RelBuilder.create(config().build());
+    final RelNode root =
+        builder.scan("EMP")
+            .sort(builder.desc(builder.field("DEPTNO")))
+            .limit(-1, 10)
+            .build();
+    final String expected = ""
+        + "LogicalSort(sort0=[$7], dir0=[DESC], fetch=[10])\n"
+        + "  LogicalTableScan(table=[[scott, EMP]])\n";
+    assertThat(RelOptUtil.toString(root), is(expected));
+
+    final RelNode root2 =
+        builder.scan("EMP")
+            .sortLimit(-1, 10, builder.desc(builder.field("DEPTNO")))
+            .build();
+    assertThat(RelOptUtil.toString(root2), is(expected));
+  }
+
+  /** Tests that a sort on an expression followed by a limit gives the same
+   * effect as calling sortLimit. */
+  @Test public void testSortExpThenLimit() {
+    final RelBuilder builder = RelBuilder.create(config().build());
+    final RelNode root =
+        builder.scan("DEPT")
+            .sort(
+                builder.desc(
+                    builder.call(SqlStdOperatorTable.PLUS,
+                        builder.field("DEPTNO"), builder.literal(1))))
+            .limit(3, 10)
+            .build();
+    final String expected = ""
+        + "LogicalProject(DEPTNO=[$0], DNAME=[$1], LOC=[$2])\n"
+        + "  LogicalSort(sort0=[$3], dir0=[DESC], offset=[3], fetch=[10])\n"
+        + "    LogicalProject(DEPTNO=[$0], DNAME=[$1], LOC=[$2], $f3=[+($0, 1)])\n"
+        + "      LogicalTableScan(table=[[scott, DEPT]])\n";
+    assertThat(RelOptUtil.toString(root), is(expected));
+
+    final RelNode root2 =
+        builder.scan("DEPT")
+            .sortLimit(3, 10,
+                builder.desc(
+                    builder.call(SqlStdOperatorTable.PLUS,
+                        builder.field("DEPTNO"), builder.literal(1))))
+            .build();
+    assertThat(RelOptUtil.toString(root2), is(expected));
+  }
 }
 
 // End RelBuilderTest.java