From 2fec4bd441ebf40cedead5dcbda4492addd6d7d6 Mon Sep 17 00:00:00 2001 From: kasiafi <30203062+kasiafi@users.noreply.github.com> Date: Sun, 26 May 2019 19:53:42 +0200 Subject: [PATCH] Simplify OFFSET implementation This change is based on RowNumberNode's property of keeping order of its input. In OFFSET implementation, a RowNumberNode and a FilterNode are used for rows selection. Before this change, if there was ORDER BY in the query, it was handled by one of the specialised rules which ensured that sorting was replicated over RowNumberNode. Since RowNumberNode respects sorted order of its input, it is unnecessary to add a SortNode. --- .../prestosql/sql/planner/PlanOptimizers.java | 24 +--- ...setOverOther.java => ImplementOffset.java} | 13 +-- .../rule/ImplementOffsetOverProjectSort.java | 109 ----------------- .../rule/ImplementOffsetOverProjectTopN.java | 110 ------------------ .../rule/ImplementOffsetOverSort.java | 107 ----------------- .../rule/ImplementOffsetOverTopN.java | 108 ----------------- .../sql/planner/TestLogicalPlanner.java | 58 ++++----- ...verOther.java => TestImplementOffset.java} | 38 +++++- .../TestImplementOffsetOverProjectSort.java | 66 ----------- .../TestImplementOffsetOverProjectTopN.java | 69 ----------- .../rule/TestImplementOffsetOverSort.java | 63 ---------- .../rule/TestImplementOffsetOverTopN.java | 66 ----------- 12 files changed, 68 insertions(+), 763 deletions(-) rename presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/{ImplementOffsetOverOther.java => ImplementOffset.java} (87%) delete mode 100644 presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverProjectSort.java delete mode 100644 presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverProjectTopN.java delete mode 100644 presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverSort.java delete mode 100644 presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverTopN.java rename presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/{TestImplementOffsetOverOther.java => TestImplementOffset.java} (56%) delete mode 100644 presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverProjectSort.java delete mode 100644 presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverProjectTopN.java delete mode 100644 presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverSort.java delete mode 100644 presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverTopN.java diff --git a/presto-main/src/main/java/io/prestosql/sql/planner/PlanOptimizers.java b/presto-main/src/main/java/io/prestosql/sql/planner/PlanOptimizers.java index bef5efdd9ec9..0a4fbc2ef7d8 100644 --- a/presto-main/src/main/java/io/prestosql/sql/planner/PlanOptimizers.java +++ b/presto-main/src/main/java/io/prestosql/sql/planner/PlanOptimizers.java @@ -46,11 +46,7 @@ import io.prestosql.sql.planner.iterative.rule.GatherAndMergeWindows; import io.prestosql.sql.planner.iterative.rule.ImplementBernoulliSampleAsFilter; import io.prestosql.sql.planner.iterative.rule.ImplementFilteredAggregations; -import io.prestosql.sql.planner.iterative.rule.ImplementOffsetOverOther; -import io.prestosql.sql.planner.iterative.rule.ImplementOffsetOverProjectSort; -import io.prestosql.sql.planner.iterative.rule.ImplementOffsetOverProjectTopN; -import io.prestosql.sql.planner.iterative.rule.ImplementOffsetOverSort; -import io.prestosql.sql.planner.iterative.rule.ImplementOffsetOverTopN; +import io.prestosql.sql.planner.iterative.rule.ImplementOffset; import io.prestosql.sql.planner.iterative.rule.InlineProjections; import io.prestosql.sql.planner.iterative.rule.MergeFilters; import io.prestosql.sql.planner.iterative.rule.MergeLimitOverProjectWithSort; @@ -343,23 +339,9 @@ public PlanOptimizers( estimatedExchangesCostCalculator, // Temporary hack: separate optimizer step to avoid the sample node being replaced by filter before pushing // it to table scan node - ImmutableSet.of(new ImplementBernoulliSampleAsFilter())), - new IterativeOptimizer( - ruleStats, - statsCalculator, - estimatedExchangesCostCalculator, ImmutableSet.of( - new ImplementOffsetOverTopN(), - new ImplementOffsetOverProjectTopN(), - new ImplementOffsetOverSort(), - new ImplementOffsetOverProjectSort())), - new IterativeOptimizer( - ruleStats, - statsCalculator, - estimatedExchangesCostCalculator, - // Temporary hack: separate optimizer step to avoid a plan that's missing a SortNode over a RowNumber node - // if the rules fires too early - ImmutableSet.of(new ImplementOffsetOverOther())), + new ImplementBernoulliSampleAsFilter(), + new ImplementOffset())), simplifyOptimizer, new UnaliasSymbolReferences(), new IterativeOptimizer( diff --git a/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverOther.java b/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffset.java similarity index 87% rename from presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverOther.java rename to presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffset.java index 87c2608104e8..9e0a78b1389a 100644 --- a/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverOther.java +++ b/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffset.java @@ -23,8 +23,6 @@ import io.prestosql.sql.planner.plan.OffsetNode; import io.prestosql.sql.planner.plan.ProjectNode; import io.prestosql.sql.planner.plan.RowNumberNode; -import io.prestosql.sql.planner.plan.SortNode; -import io.prestosql.sql.planner.plan.TopNNode; import io.prestosql.sql.tree.ComparisonExpression; import io.prestosql.sql.tree.GenericLiteral; @@ -32,13 +30,12 @@ import static io.prestosql.spi.type.BigintType.BIGINT; import static io.prestosql.sql.planner.plan.Patterns.offset; -import static io.prestosql.sql.planner.plan.Patterns.source; /** * Transforms: *
  * - Offset (row count = x)
- *    - Source (other than Sort, TopN)
+ *    - Source
  * 
* Into: *
@@ -47,12 +44,14 @@
  *       - RowNumber
  *          - Source
  * 
+ * Relies on RowNumberNode's property of keeping order of its input. + * If the query contains an ORDER BY clause, the sorted order + * will be respected when leading rows are removed. */ -public class ImplementOffsetOverOther +public class ImplementOffset implements Rule { - private static final Pattern PATTERN = offset() - .with(source().matching(node -> !(node instanceof TopNNode || node instanceof SortNode))); + private static final Pattern PATTERN = offset(); @Override public Pattern getPattern() diff --git a/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverProjectSort.java b/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverProjectSort.java deleted file mode 100644 index 2fcc7162774c..000000000000 --- a/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverProjectSort.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Licensed 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 io.prestosql.sql.planner.iterative.rule; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import io.prestosql.matching.Capture; -import io.prestosql.matching.Captures; -import io.prestosql.matching.Pattern; -import io.prestosql.spi.block.SortOrder; -import io.prestosql.sql.planner.OrderingScheme; -import io.prestosql.sql.planner.Symbol; -import io.prestosql.sql.planner.iterative.Rule; -import io.prestosql.sql.planner.plan.FilterNode; -import io.prestosql.sql.planner.plan.OffsetNode; -import io.prestosql.sql.planner.plan.ProjectNode; -import io.prestosql.sql.planner.plan.RowNumberNode; -import io.prestosql.sql.planner.plan.SortNode; -import io.prestosql.sql.tree.ComparisonExpression; -import io.prestosql.sql.tree.GenericLiteral; - -import java.util.Optional; - -import static io.prestosql.matching.Capture.newCapture; -import static io.prestosql.spi.type.BigintType.BIGINT; -import static io.prestosql.sql.planner.plan.Patterns.offset; -import static io.prestosql.sql.planner.plan.Patterns.project; -import static io.prestosql.sql.planner.plan.Patterns.sort; -import static io.prestosql.sql.planner.plan.Patterns.source; - -/** - * Transforms: - *
- * - Offset (row count = x)
- *    - Project (prunes sort symbols no longer useful)
- *       - Sort (order by a, b, c)
- * 
- * Into: - *
- * - Project (prunes rowNumber symbol and sort symbols no longer useful)
- *    - Sort (order by rowNumber)
- *       - Filter (rowNumber > x)
- *          - RowNumber
- *             - Sort (order by a, b, c)
- * 
- */ -public class ImplementOffsetOverProjectSort - implements Rule -{ - private static final Capture PROJECT = newCapture(); - private static final Capture SORT = newCapture(); - - private static final Pattern PATTERN = offset() - .with(source().matching( - project().capturedAs(PROJECT).matching(ProjectNode::isIdentity) - .with(source().matching( - sort().capturedAs(SORT))))); - - @Override - public Pattern getPattern() - { - return PATTERN; - } - - @Override - public Result apply(OffsetNode parent, Captures captures, Context context) - { - ProjectNode project = captures.get(PROJECT); - SortNode sort = captures.get(SORT); - - Symbol rowNumberSymbol = context.getSymbolAllocator().newSymbol("row_number", BIGINT); - - RowNumberNode rowNumberNode = new RowNumberNode( - context.getIdAllocator().getNextId(), - sort, - ImmutableList.of(), - rowNumberSymbol, - Optional.empty(), - Optional.empty()); - - FilterNode filterNode = new FilterNode( - context.getIdAllocator().getNextId(), - rowNumberNode, - new ComparisonExpression( - ComparisonExpression.Operator.GREATER_THAN, - rowNumberSymbol.toSymbolReference(), - new GenericLiteral("BIGINT", Long.toString(parent.getCount())))); - - SortNode sortNode = new SortNode( - context.getIdAllocator().getNextId(), - filterNode, - new OrderingScheme(ImmutableList.of(rowNumberSymbol), ImmutableMap.of(rowNumberSymbol, SortOrder.ASC_NULLS_FIRST))); - - ProjectNode projectNode = (ProjectNode) project.replaceChildren(ImmutableList.of(sortNode)); - - return Result.ofPlanNode(projectNode); - } -} diff --git a/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverProjectTopN.java b/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverProjectTopN.java deleted file mode 100644 index 7de6abe9515a..000000000000 --- a/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverProjectTopN.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Licensed 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 io.prestosql.sql.planner.iterative.rule; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import io.prestosql.matching.Capture; -import io.prestosql.matching.Captures; -import io.prestosql.matching.Pattern; -import io.prestosql.spi.block.SortOrder; -import io.prestosql.sql.planner.OrderingScheme; -import io.prestosql.sql.planner.Symbol; -import io.prestosql.sql.planner.iterative.Rule; -import io.prestosql.sql.planner.plan.FilterNode; -import io.prestosql.sql.planner.plan.OffsetNode; -import io.prestosql.sql.planner.plan.ProjectNode; -import io.prestosql.sql.planner.plan.RowNumberNode; -import io.prestosql.sql.planner.plan.SortNode; -import io.prestosql.sql.planner.plan.TopNNode; -import io.prestosql.sql.tree.ComparisonExpression; -import io.prestosql.sql.tree.GenericLiteral; - -import java.util.Optional; - -import static io.prestosql.matching.Capture.newCapture; -import static io.prestosql.spi.type.BigintType.BIGINT; -import static io.prestosql.sql.planner.plan.Patterns.offset; -import static io.prestosql.sql.planner.plan.Patterns.project; -import static io.prestosql.sql.planner.plan.Patterns.source; -import static io.prestosql.sql.planner.plan.Patterns.topN; - -/** - * Transforms: - *
- * - Offset (row count = x)
- *    - Project (prunes sort symbols no longer useful)
- *       - TopN (order by a, b, c)
- * 
- * Into: - *
- * - Project (prunes rowNumber symbol and sort symbols no longer useful)
- *    - Sort (order by rowNumber)
- *       - Filter (rowNumber > x)
- *          - RowNumber
- *             - TopN (order by a, b, c)
- * 
- */ -public class ImplementOffsetOverProjectTopN - implements Rule -{ - private static final Capture PROJECT = newCapture(); - private static final Capture TOPN = newCapture(); - - private static final Pattern PATTERN = offset() - .with(source().matching( - project().capturedAs(PROJECT).matching(ProjectNode::isIdentity) - .with(source().matching( - topN().capturedAs(TOPN))))); - - @Override - public Pattern getPattern() - { - return PATTERN; - } - - @Override - public Result apply(OffsetNode parent, Captures captures, Context context) - { - ProjectNode project = captures.get(PROJECT); - TopNNode topN = captures.get(TOPN); - - Symbol rowNumberSymbol = context.getSymbolAllocator().newSymbol("row_number", BIGINT); - - RowNumberNode rowNumberNode = new RowNumberNode( - context.getIdAllocator().getNextId(), - topN, - ImmutableList.of(), - rowNumberSymbol, - Optional.empty(), - Optional.empty()); - - FilterNode filterNode = new FilterNode( - context.getIdAllocator().getNextId(), - rowNumberNode, - new ComparisonExpression( - ComparisonExpression.Operator.GREATER_THAN, - rowNumberSymbol.toSymbolReference(), - new GenericLiteral("BIGINT", Long.toString(parent.getCount())))); - - SortNode sortNode = new SortNode( - context.getIdAllocator().getNextId(), - filterNode, - new OrderingScheme(ImmutableList.of(rowNumberSymbol), ImmutableMap.of(rowNumberSymbol, SortOrder.ASC_NULLS_FIRST))); - - ProjectNode projectNode = (ProjectNode) project.replaceChildren(ImmutableList.of(sortNode)); - - return Result.ofPlanNode(projectNode); - } -} diff --git a/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverSort.java b/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverSort.java deleted file mode 100644 index cf5b695f9b21..000000000000 --- a/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverSort.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed 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 io.prestosql.sql.planner.iterative.rule; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import io.prestosql.matching.Capture; -import io.prestosql.matching.Captures; -import io.prestosql.matching.Pattern; -import io.prestosql.spi.block.SortOrder; -import io.prestosql.sql.planner.OrderingScheme; -import io.prestosql.sql.planner.Symbol; -import io.prestosql.sql.planner.iterative.Rule; -import io.prestosql.sql.planner.plan.Assignments; -import io.prestosql.sql.planner.plan.FilterNode; -import io.prestosql.sql.planner.plan.OffsetNode; -import io.prestosql.sql.planner.plan.ProjectNode; -import io.prestosql.sql.planner.plan.RowNumberNode; -import io.prestosql.sql.planner.plan.SortNode; -import io.prestosql.sql.tree.ComparisonExpression; -import io.prestosql.sql.tree.GenericLiteral; - -import java.util.Optional; - -import static io.prestosql.matching.Capture.newCapture; -import static io.prestosql.spi.type.BigintType.BIGINT; -import static io.prestosql.sql.planner.plan.Patterns.offset; -import static io.prestosql.sql.planner.plan.Patterns.sort; -import static io.prestosql.sql.planner.plan.Patterns.source; - -/** - * Transforms: - *
- * - Offset (row count = x)
- *    - Sort (order by a, b, c)
- * 
- * Into: - *
- * - Project (prune rowNumber symbol)
- *    - Sort (order by rowNumber)
- *       - Filter (rowNumber > x)
- *          - RowNumber
- *             - Sort (order by a, b, c)
- * 
- */ -public class ImplementOffsetOverSort - implements Rule -{ - private static final Capture SORT = newCapture(); - - private static final Pattern PATTERN = offset() - .with(source().matching( - sort().capturedAs(SORT))); - - @Override - public Pattern getPattern() - { - return PATTERN; - } - - @Override - public Result apply(OffsetNode parent, Captures captures, Context context) - { - SortNode sort = captures.get(SORT); - - Symbol rowNumberSymbol = context.getSymbolAllocator().newSymbol("row_number", BIGINT); - - RowNumberNode rowNumberNode = new RowNumberNode( - context.getIdAllocator().getNextId(), - sort, - ImmutableList.of(), - rowNumberSymbol, - Optional.empty(), - Optional.empty()); - - FilterNode filterNode = new FilterNode( - context.getIdAllocator().getNextId(), - rowNumberNode, - new ComparisonExpression( - ComparisonExpression.Operator.GREATER_THAN, - rowNumberSymbol.toSymbolReference(), - new GenericLiteral("BIGINT", Long.toString(parent.getCount())))); - - SortNode sortNode = new SortNode( - context.getIdAllocator().getNextId(), - filterNode, - new OrderingScheme(ImmutableList.of(rowNumberSymbol), ImmutableMap.of(rowNumberSymbol, SortOrder.ASC_NULLS_FIRST))); - - ProjectNode projectNode = new ProjectNode( - context.getIdAllocator().getNextId(), - sortNode, - Assignments.identity(sort.getOutputSymbols())); - - return Result.ofPlanNode(projectNode); - } -} diff --git a/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverTopN.java b/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverTopN.java deleted file mode 100644 index 03f0f8b3c6f7..000000000000 --- a/presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ImplementOffsetOverTopN.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Licensed 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 io.prestosql.sql.planner.iterative.rule; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import io.prestosql.matching.Capture; -import io.prestosql.matching.Captures; -import io.prestosql.matching.Pattern; -import io.prestosql.spi.block.SortOrder; -import io.prestosql.sql.planner.OrderingScheme; -import io.prestosql.sql.planner.Symbol; -import io.prestosql.sql.planner.iterative.Rule; -import io.prestosql.sql.planner.plan.Assignments; -import io.prestosql.sql.planner.plan.FilterNode; -import io.prestosql.sql.planner.plan.OffsetNode; -import io.prestosql.sql.planner.plan.ProjectNode; -import io.prestosql.sql.planner.plan.RowNumberNode; -import io.prestosql.sql.planner.plan.SortNode; -import io.prestosql.sql.planner.plan.TopNNode; -import io.prestosql.sql.tree.ComparisonExpression; -import io.prestosql.sql.tree.GenericLiteral; - -import java.util.Optional; - -import static io.prestosql.matching.Capture.newCapture; -import static io.prestosql.spi.type.BigintType.BIGINT; -import static io.prestosql.sql.planner.plan.Patterns.offset; -import static io.prestosql.sql.planner.plan.Patterns.source; -import static io.prestosql.sql.planner.plan.Patterns.topN; - -/** - * Transforms: - *
- * - Offset (row count = x)
- *    - TopN (order by a, b, c)
- * 
- * Into: - *
- * - Project (prune rowNumber symbol)
- *    - Sort (order by rowNumber)
- *       - Filter (rowNumber > x)
- *          - RowNumber
- *             - TopN (order by a, b, c)
- * 
- */ -public class ImplementOffsetOverTopN - implements Rule -{ - private static final Capture TOPN = newCapture(); - - private static final Pattern PATTERN = offset() - .with(source().matching( - topN().capturedAs(TOPN))); - - @Override - public Pattern getPattern() - { - return PATTERN; - } - - @Override - public Result apply(OffsetNode parent, Captures captures, Context context) - { - TopNNode topN = captures.get(TOPN); - - Symbol rowNumberSymbol = context.getSymbolAllocator().newSymbol("row_number", BIGINT); - - RowNumberNode rowNumberNode = new RowNumberNode( - context.getIdAllocator().getNextId(), - topN, - ImmutableList.of(), - rowNumberSymbol, - Optional.empty(), - Optional.empty()); - - FilterNode filterNode = new FilterNode( - context.getIdAllocator().getNextId(), - rowNumberNode, - new ComparisonExpression( - ComparisonExpression.Operator.GREATER_THAN, - rowNumberSymbol.toSymbolReference(), - new GenericLiteral("BIGINT", Long.toString(parent.getCount())))); - - SortNode sortNode = new SortNode( - context.getIdAllocator().getNextId(), - filterNode, - new OrderingScheme(ImmutableList.of(rowNumberSymbol), ImmutableMap.of(rowNumberSymbol, SortOrder.ASC_NULLS_FIRST))); - - ProjectNode projectNode = new ProjectNode( - context.getIdAllocator().getNextId(), - sortNode, - Assignments.identity(topN.getOutputSymbols())); - - return Result.ofPlanNode(projectNode); - } -} diff --git a/presto-main/src/test/java/io/prestosql/sql/planner/TestLogicalPlanner.java b/presto-main/src/test/java/io/prestosql/sql/planner/TestLogicalPlanner.java index 9e6caaff836e..fdd207fcb074 100644 --- a/presto-main/src/test/java/io/prestosql/sql/planner/TestLogicalPlanner.java +++ b/presto-main/src/test/java/io/prestosql/sql/planner/TestLogicalPlanner.java @@ -102,7 +102,6 @@ import static io.prestosql.sql.planner.plan.JoinNode.DistributionType.REPLICATED; import static io.prestosql.sql.planner.plan.JoinNode.Type.INNER; import static io.prestosql.sql.planner.plan.JoinNode.Type.LEFT; -import static io.prestosql.sql.tree.SortItem.NullOrdering.FIRST; import static io.prestosql.sql.tree.SortItem.NullOrdering.LAST; import static io.prestosql.sql.tree.SortItem.Ordering.ASCENDING; import static io.prestosql.sql.tree.SortItem.Ordering.DESCENDING; @@ -879,7 +878,7 @@ public void testOffset() strictProject( ImmutableMap.of("name", new ExpressionMatcher("name")), filter( - "(row_num > BIGINT '2')", + "row_num > BIGINT '2'", rowNumber( pattern -> pattern .partitionBy(ImmutableList.of()), @@ -892,43 +891,36 @@ public void testOffset() any( strictProject( ImmutableMap.of("name", new ExpressionMatcher("name")), - any( - sort( - ImmutableList.of(sort("row_num", ASCENDING, FIRST)), - any( - filter( - "(row_num > BIGINT '2')", - rowNumber( - pattern -> pattern - .partitionBy(ImmutableList.of()), - any( - sort( - ImmutableList.of(sort("regionkey", ASCENDING, LAST)), - any( - tableScan("nation", ImmutableMap.of("NAME", "name", "REGIONKEY", "regionkey")))))) - .withAlias("row_num", new RowNumberSymbolMatcher())))))))); + filter( + "row_num > BIGINT '2'", + rowNumber( + pattern -> pattern + .partitionBy(ImmutableList.of()), + anyTree( + sort( + ImmutableList.of(sort("regionkey", ASCENDING, LAST)), + any( + tableScan("nation", ImmutableMap.of("NAME", "name", "REGIONKEY", "regionkey")))))) + .withAlias("row_num", new RowNumberSymbolMatcher()))))); assertPlan( "SELECT name FROM nation ORDER BY regionkey OFFSET 2 ROWS FETCH NEXT 5 ROWS ONLY", any( strictProject( ImmutableMap.of("name", new ExpressionMatcher("name")), - any( - sort( - ImmutableList.of(sort("row_num", ASCENDING, FIRST)), + filter( + "row_num > BIGINT '2'", + rowNumber( + pattern -> pattern + .partitionBy(ImmutableList.of()), any( - filter( - "(row_num > BIGINT '2')", - rowNumber( - pattern -> pattern - .partitionBy(ImmutableList.of()), - topN( - 7, - ImmutableList.of(sort("regionkey", ASCENDING, LAST)), - TopNNode.Step.FINAL, - anyTree( - tableScan("nation", ImmutableMap.of("NAME", "name", "REGIONKEY", "regionkey"))))) - .withAlias("row_num", new RowNumberSymbolMatcher())))))))); + topN( + 7, + ImmutableList.of(sort("regionkey", ASCENDING, LAST)), + TopNNode.Step.FINAL, + anyTree( + tableScan("nation", ImmutableMap.of("NAME", "name", "REGIONKEY", "regionkey")))))) + .withAlias("row_num", new RowNumberSymbolMatcher()))))); assertPlan( "SELECT name FROM nation OFFSET 2 ROWS FETCH NEXT 5 ROWS ONLY", @@ -936,7 +928,7 @@ public void testOffset() strictProject( ImmutableMap.of("name", new ExpressionMatcher("name")), filter( - "(row_num > BIGINT '2')", + "row_num > BIGINT '2'", rowNumber( pattern -> pattern .partitionBy(ImmutableList.of()), diff --git a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverOther.java b/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffset.java similarity index 56% rename from presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverOther.java rename to presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffset.java index 27c1049a5da3..741eada368d5 100644 --- a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverOther.java +++ b/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffset.java @@ -23,16 +23,19 @@ import static io.prestosql.sql.planner.assertions.PlanMatchPattern.filter; import static io.prestosql.sql.planner.assertions.PlanMatchPattern.rowNumber; +import static io.prestosql.sql.planner.assertions.PlanMatchPattern.sort; import static io.prestosql.sql.planner.assertions.PlanMatchPattern.strictProject; import static io.prestosql.sql.planner.assertions.PlanMatchPattern.values; +import static io.prestosql.sql.tree.SortItem.NullOrdering.FIRST; +import static io.prestosql.sql.tree.SortItem.Ordering.ASCENDING; -public class TestImplementOffsetOverOther +public class TestImplementOffset extends BaseRuleTest { @Test - public void testReplaceOffsetOverOther() + public void testReplaceOffsetOverValues() { - tester().assertThat(new ImplementOffsetOverOther()) + tester().assertThat(new ImplementOffset()) .on(p -> { Symbol a = p.symbol("a"); Symbol b = p.symbol("b"); @@ -44,11 +47,38 @@ public void testReplaceOffsetOverOther() strictProject( ImmutableMap.of("a", new ExpressionMatcher("a"), "b", new ExpressionMatcher("b")), filter( - "(row_num > BIGINT '2')", + "row_num > BIGINT '2'", rowNumber( pattern -> pattern .partitionBy(ImmutableList.of()), values("a", "b")) .withAlias("row_num", new RowNumberSymbolMatcher())))); } + + @Test + public void testReplaceOffsetOverSort() + { + tester().assertThat(new ImplementOffset()) + .on(p -> { + Symbol a = p.symbol("a"); + Symbol b = p.symbol("b"); + return p.offset( + 2, + p.sort( + ImmutableList.of(a), + p.values(a, b))); + }) + .matches( + strictProject( + ImmutableMap.of("a", new ExpressionMatcher("a"), "b", new ExpressionMatcher("b")), + filter( + "row_num > BIGINT '2'", + rowNumber( + pattern -> pattern + .partitionBy(ImmutableList.of()), + sort( + ImmutableList.of(sort("a", ASCENDING, FIRST)), + values("a", "b"))) + .withAlias("row_num", new RowNumberSymbolMatcher())))); + } } diff --git a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverProjectSort.java b/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverProjectSort.java deleted file mode 100644 index 9fbd324e81c7..000000000000 --- a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverProjectSort.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed 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 io.prestosql.sql.planner.iterative.rule; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import io.prestosql.sql.planner.Symbol; -import io.prestosql.sql.planner.assertions.ExpressionMatcher; -import io.prestosql.sql.planner.assertions.RowNumberSymbolMatcher; -import io.prestosql.sql.planner.iterative.rule.test.BaseRuleTest; -import io.prestosql.sql.planner.plan.Assignments; -import org.testng.annotations.Test; - -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.filter; -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.rowNumber; -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.sort; -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.strictProject; -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.values; -import static io.prestosql.sql.tree.SortItem.NullOrdering.FIRST; -import static io.prestosql.sql.tree.SortItem.Ordering.ASCENDING; - -public class TestImplementOffsetOverProjectSort - extends BaseRuleTest -{ - @Test - public void testReplaceOffsetOverProjectSort() - { - tester().assertThat(new ImplementOffsetOverProjectSort()) - .on(p -> { - Symbol a = p.symbol("a"); - Symbol b = p.symbol("b"); - return p.offset( - 2, - p.project( - Assignments.identity(b), - p.sort( - ImmutableList.of(a), - p.values(a, b)))); - }) - .matches( - strictProject( - ImmutableMap.of("b", new ExpressionMatcher("b")), - sort( - ImmutableList.of(sort("row_num", ASCENDING, FIRST)), - filter( - "(row_num > BIGINT '2')", - rowNumber( - pattern -> pattern - .partitionBy(ImmutableList.of()), - sort( - ImmutableList.of(sort("a", ASCENDING, FIRST)), - values("a", "b"))) - .withAlias("row_num", new RowNumberSymbolMatcher()))))); - } -} diff --git a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverProjectTopN.java b/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverProjectTopN.java deleted file mode 100644 index 0e3e5ce6558f..000000000000 --- a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverProjectTopN.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed 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 io.prestosql.sql.planner.iterative.rule; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import io.prestosql.sql.planner.Symbol; -import io.prestosql.sql.planner.assertions.ExpressionMatcher; -import io.prestosql.sql.planner.assertions.RowNumberSymbolMatcher; -import io.prestosql.sql.planner.iterative.rule.test.BaseRuleTest; -import io.prestosql.sql.planner.plan.Assignments; -import org.testng.annotations.Test; - -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.filter; -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.rowNumber; -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.sort; -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.strictProject; -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.topN; -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.values; -import static io.prestosql.sql.tree.SortItem.NullOrdering.FIRST; -import static io.prestosql.sql.tree.SortItem.Ordering.ASCENDING; - -public class TestImplementOffsetOverProjectTopN - extends BaseRuleTest -{ - @Test - public void testReplaceOffsetOverProjectTopN() - { - tester().assertThat(new ImplementOffsetOverProjectTopN()) - .on(p -> { - Symbol a = p.symbol("a"); - Symbol b = p.symbol("b"); - return p.offset( - 2, - p.project( - Assignments.identity(b), - p.topN( - 5, - ImmutableList.of(a), - p.values(a, b)))); - }) - .matches( - strictProject( - ImmutableMap.of("b", new ExpressionMatcher("b")), - sort( - ImmutableList.of(sort("row_num", ASCENDING, FIRST)), - filter( - "(row_num > BIGINT '2')", - rowNumber( - pattern -> pattern - .partitionBy(ImmutableList.of()), - topN( - 5, - ImmutableList.of(sort("a", ASCENDING, FIRST)), - values("a", "b"))) - .withAlias("row_num", new RowNumberSymbolMatcher()))))); - } -} diff --git a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverSort.java b/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverSort.java deleted file mode 100644 index e2a1c261ec8b..000000000000 --- a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverSort.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed 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 io.prestosql.sql.planner.iterative.rule; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import io.prestosql.sql.planner.Symbol; -import io.prestosql.sql.planner.assertions.ExpressionMatcher; -import io.prestosql.sql.planner.assertions.RowNumberSymbolMatcher; -import io.prestosql.sql.planner.iterative.rule.test.BaseRuleTest; -import org.testng.annotations.Test; - -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.filter; -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.rowNumber; -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.sort; -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.strictProject; -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.values; -import static io.prestosql.sql.tree.SortItem.NullOrdering.FIRST; -import static io.prestosql.sql.tree.SortItem.Ordering.ASCENDING; - -public class TestImplementOffsetOverSort - extends BaseRuleTest -{ - @Test - public void testReplaceOffsetOverSort() - { - tester().assertThat(new ImplementOffsetOverSort()) - .on(p -> { - Symbol a = p.symbol("a"); - Symbol b = p.symbol("b"); - return p.offset( - 2, - p.sort( - ImmutableList.of(a), - p.values(a, b))); - }) - .matches( - strictProject( - ImmutableMap.of("a", new ExpressionMatcher("a"), "b", new ExpressionMatcher("b")), - sort( - ImmutableList.of(sort("row_num", ASCENDING, FIRST)), - filter( - "(row_num > BIGINT '2')", - rowNumber( - pattern -> pattern - .partitionBy(ImmutableList.of()), - sort( - ImmutableList.of(sort("a", ASCENDING, FIRST)), - values("a", "b"))) - .withAlias("row_num", new RowNumberSymbolMatcher()))))); - } -} diff --git a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverTopN.java b/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverTopN.java deleted file mode 100644 index 399eec970860..000000000000 --- a/presto-main/src/test/java/io/prestosql/sql/planner/iterative/rule/TestImplementOffsetOverTopN.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed 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 io.prestosql.sql.planner.iterative.rule; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import io.prestosql.sql.planner.Symbol; -import io.prestosql.sql.planner.assertions.ExpressionMatcher; -import io.prestosql.sql.planner.assertions.RowNumberSymbolMatcher; -import io.prestosql.sql.planner.iterative.rule.test.BaseRuleTest; -import org.testng.annotations.Test; - -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.filter; -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.rowNumber; -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.sort; -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.strictProject; -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.topN; -import static io.prestosql.sql.planner.assertions.PlanMatchPattern.values; -import static io.prestosql.sql.tree.SortItem.NullOrdering.FIRST; -import static io.prestosql.sql.tree.SortItem.Ordering.ASCENDING; - -public class TestImplementOffsetOverTopN - extends BaseRuleTest -{ - @Test - public void testReplaceOffsetOverTopN() - { - tester().assertThat(new ImplementOffsetOverTopN()) - .on(p -> { - Symbol a = p.symbol("a"); - Symbol b = p.symbol("b"); - return p.offset( - 2, - p.topN( - 5, - ImmutableList.of(a), - p.values(a, b))); - }) - .matches( - strictProject( - ImmutableMap.of("a", new ExpressionMatcher("a"), "b", new ExpressionMatcher("b")), - sort( - ImmutableList.of(sort("row_num", ASCENDING, FIRST)), - filter( - "(row_num > BIGINT '2')", - rowNumber( - pattern -> pattern - .partitionBy(ImmutableList.of()), - topN( - 5, - ImmutableList.of(sort("a", ASCENDING, FIRST)), - values("a", "b"))) - .withAlias("row_num", new RowNumberSymbolMatcher()))))); - } -}