This is an automated email from the ASF dual-hosted git repository.
mbudiu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push:
new e20a9a5523 [CALCITE-6647] SortUnionTransposeRule should not push SORT
past a UNION when SORT's fetch is DynamicParam
e20a9a5523 is described below
commit e20a9a552342799bec03550945d75898a1d652fd
Author: Xiong Duan <[email protected]>
AuthorDate: Sat Nov 16 09:11:20 2024 +0800
[CALCITE-6647] SortUnionTransposeRule should not push SORT past a UNION
when SORT's fetch is DynamicParam
---
.../calcite/rel/rules/SortUnionTransposeRule.java | 5 ++-
.../org/apache/calcite/test/RelOptRulesTest.java | 27 +++++++++++++
.../org/apache/calcite/test/RelOptRulesTest.xml | 45 ++++++++++++++++++++++
3 files changed, 76 insertions(+), 1 deletion(-)
diff --git
a/core/src/main/java/org/apache/calcite/rel/rules/SortUnionTransposeRule.java
b/core/src/main/java/org/apache/calcite/rel/rules/SortUnionTransposeRule.java
index 0716b51440..e85d4f6f1b 100644
---
a/core/src/main/java/org/apache/calcite/rel/rules/SortUnionTransposeRule.java
+++
b/core/src/main/java/org/apache/calcite/rel/rules/SortUnionTransposeRule.java
@@ -23,6 +23,7 @@ import org.apache.calcite.rel.core.Sort;
import org.apache.calcite.rel.core.Union;
import org.apache.calcite.rel.metadata.RelMdUtil;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
+import org.apache.calcite.rex.RexDynamicParam;
import org.apache.calcite.tools.RelBuilderFactory;
import org.immutables.value.Value;
@@ -66,11 +67,13 @@ public class SortUnionTransposeRule
@Override public boolean matches(RelOptRuleCall call) {
final Sort sort = call.rel(0);
final Union union = call.rel(1);
- // We only apply this rule if Union.all is true and Sort.offset is null.
+ // We only apply this rule if Union.all is true, Sort.offset is null and
Sort.fetch is not
+ // a dynamic param.
// There is a flag indicating if this rule should be applied when
// Sort.fetch is null.
return union.all
&& sort.offset == null
+ && !(sort.fetch instanceof RexDynamicParam)
&& (config.matchNullFetch() || sort.fetch != null);
}
diff --git a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
index 203174f39e..cca3a70634 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -89,6 +89,8 @@ import org.apache.calcite.rel.rules.PushProjector;
import org.apache.calcite.rel.rules.ReduceExpressionsRule;
import
org.apache.calcite.rel.rules.ReduceExpressionsRule.ProjectReduceExpressionsRule;
import org.apache.calcite.rel.rules.SingleValuesOptimizationRules;
+import org.apache.calcite.rel.rules.SortProjectTransposeRule;
+import org.apache.calcite.rel.rules.SortUnionTransposeRule;
import org.apache.calcite.rel.rules.SpatialRules;
import org.apache.calcite.rel.rules.UnionMergeRule;
import org.apache.calcite.rel.rules.ValuesReduceRule;
@@ -5111,6 +5113,31 @@ class RelOptRulesTest extends RelOptTestBase {
.checkUnchanged();
}
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-6647">[CALCITE-6647]
+ * SortUnionTransposeRule should not push SORT past a UNION when SORT's
fetch is DynamicParam
+ </a>. */
+ @Test void testSortWithDynamicParam() {
+ HepProgramBuilder builder = new HepProgramBuilder();
+ builder.addRuleClass(SortProjectTransposeRule.class);
+ builder.addRuleClass(SortUnionTransposeRule.class);
+ HepPlanner hepPlanner = new HepPlanner(builder.build());
+ hepPlanner.addRule(CoreRules.SORT_PROJECT_TRANSPOSE);
+ hepPlanner.addRule(CoreRules.SORT_UNION_TRANSPOSE);
+ final String sql = "SELECT x.sal\n"
+ + "FROM (SELECT emp1.sal\n"
+ + " FROM (SELECT sal\n"
+ + " from emp\n"
+ + " LIMIT ?) AS emp1\n"
+ + " UNION ALL\n"
+ + " SELECT emp2.sal\n"
+ + " FROM (SELECT sal\n"
+ + " from emp\n"
+ + " LIMIT ?) AS emp2) AS x\n"
+ + "LIMIT ?";
+ sql(sql).withPlanner(hepPlanner).check();
+ }
+
@Test void testReduceCasts() {
// Disable simplify in RelBuilder so that there are casts in 'before';
// The resulting plan should have no cast expressions
diff --git
a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
index da6e4936c4..01b40a44e0 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -15623,6 +15623,51 @@ LogicalSort(sort0=[$0], dir0=[ASC], fetch=[0])
LogicalSort(sort0=[$0], dir0=[ASC], fetch=[0])
LogicalProject(NAME=[$1])
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testSortWithDynamicParam">
+ <Resource name="sql">
+ <![CDATA[SELECT x.sal
+FROM (SELECT emp1.sal
+ FROM (SELECT sal
+ from emp
+ LIMIT ?) AS emp1
+ UNION ALL
+ SELECT emp2.sal
+ FROM (SELECT sal
+ from emp
+ LIMIT ?) AS emp2) AS x
+LIMIT ?]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalSort(fetch=[?2])
+ LogicalProject(SAL=[$0])
+ LogicalUnion(all=[true])
+ LogicalProject(SAL=[$0])
+ LogicalSort(fetch=[?0])
+ LogicalProject(SAL=[$5])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+ LogicalProject(SAL=[$0])
+ LogicalSort(fetch=[?1])
+ LogicalProject(SAL=[$5])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(SAL=[$0])
+ LogicalSort(fetch=[?2])
+ LogicalUnion(all=[true])
+ LogicalProject(SAL=[$0])
+ LogicalProject(SAL=[$5])
+ LogicalSort(fetch=[?0])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+ LogicalProject(SAL=[$0])
+ LogicalProject(SAL=[$5])
+ LogicalSort(fetch=[?1])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
</Resource>
</TestCase>