[CALCITE-1058] Add method RelBuilder.empty, and rewrite LIMIT 0 to it
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/ee283cad Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/ee283cad Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/ee283cad Branch: refs/heads/branch-1.6 Commit: ee283cadf17d8add8e8ea2bf1f8dd5735f05dc1d Parents: 3cba705 Author: Julian Hyde <[email protected]> Authored: Wed Jan 13 21:37:27 2016 -0800 Committer: Julian Hyde <[email protected]> Committed: Thu Jan 14 13:51:44 2016 -0800 ---------------------------------------------------------------------- .../org/apache/calcite/tools/RelBuilder.java | 21 +++++++++++++ .../org/apache/calcite/test/RelBuilderTest.java | 33 ++++++++++++++++++++ 2 files changed, 54 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/calcite/blob/ee283cad/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 00ce6d1..cf9fcb6 100644 --- a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java +++ b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java @@ -1155,6 +1155,24 @@ public class RelBuilder { return true; } + /** Creates a relational expression that reads from an input and throws + * all of the rows away. + * + * <p>Note that this method always pops one relational expression from the + * stack. {@code values}, in contrast, does not pop any relational + * expressions, and always produces a leaf. + * + * <p>The default implementation creates a {@link Values} with the same + * specified row type as the input, and ignores the input entirely. + * But schema-on-query systems such as Drill might override this method to + * create a relation expression that retains the input, just to read its + * schema. + */ + public RelBuilder empty() { + final Frame frame = Stacks.pop(stack); + return values(frame.rel.getRowType()); + } + /** Creates a {@link Values} with a specified row type. * * <p>This method can handle cases that {@link #values(String[], Object...)} @@ -1274,6 +1292,9 @@ public class RelBuilder { } final RexNode offsetNode = offset <= 0 ? null : literal(offset); final RexNode fetchNode = fetch < 0 ? null : literal(fetch); + if (offsetNode == null && fetch == 0) { + return empty(); + } if (offsetNode == null && fetchNode == null && fieldCollations.isEmpty()) { return this; // sort is trivial } http://git-wip-us.apache.org/repos/asf/calcite/blob/ee283cad/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 0b232f4..db13a02 100644 --- a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java +++ b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java @@ -873,6 +873,25 @@ public class RelBuilderTest { assertThat(str(root), is(expected)); } + @Test public void testEmpty() { + // Equivalent SQL: + // SELECT deptno, true FROM dept LIMIT 0 + // optimized to + // VALUES + final RelBuilder builder = RelBuilder.create(config().build()); + RelNode root = + builder.scan("DEPT") + .project(builder.field(0), builder.literal(false)) + .empty() + .build(); + final String expected = + "LogicalValues(tuples=[[]])\n"; + assertThat(str(root), is(expected)); + final String expectedType = + "RecordType(TINYINT NOT NULL DEPTNO, BOOLEAN NOT NULL $f1) NOT NULL"; + assertThat(root.getRowType().getFullTypeString(), is(expectedType)); + } + @Test public void testValues() { // Equivalent SQL: // VALUES (true, 1), (false, -50) AS t(a, b) @@ -1071,6 +1090,20 @@ public class RelBuilderTest { assertThat(str(root), is(expected)); } + @Test public void testSortLimit0() { + // Equivalent SQL: + // SELECT * + // FROM emp + // ORDER BY deptno DESC FETCH 0 + final RelBuilder builder = RelBuilder.create(config().build()); + final RelNode root = + builder.scan("EMP") + .sortLimit(-1, 0, builder.desc(builder.field("DEPTNO"))) + .build(); + final String expected = "LogicalValues(tuples=[[]])\n"; + assertThat(str(root), is(expected)); + } + /** Tests that a sort on a field followed by a limit gives the same * effect as calling sortLimit. *
