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