Skip to content

Commit

Permalink
[CALCITE-6878] Implement FilterSortTransposeRule
Browse files Browse the repository at this point in the history
  • Loading branch information
xiedeyantu committed Mar 9, 2025
1 parent 48648b3 commit 8ea0df9
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,11 @@ private CoreRules() {}
public static final FilterTableScanRule FILTER_SCAN =
FilterTableScanRule.Config.DEFAULT.toRule();

/** Rule that transforms a {@link Filter} on top of a {@link Sort}
* into a {@link Sort} on top of a {@link Filter}. */
public static final FilterSortTransposeRule FILTER_SORT_TRANSPOSE =
FilterSortTransposeRule.Config.DEFAULT.toRule();

/** Rule that matches a {@link Filter} on an
* {@link org.apache.calcite.adapter.enumerable.EnumerableInterpreter} on a
* {@link TableScan}. */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you 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 org.apache.calcite.rel.rules;

import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelRule;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Filter;
import org.apache.calcite.rel.core.Sort;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.tools.RelBuilder;
import org.apache.calcite.tools.RelBuilderFactory;

import org.immutables.value.Value;

/**
* Rule that transforms a {@link Filter} on top of a {@link Sort}
* into a {@link Sort} on top of a {@link Filter}.
*/
@Value.Enclosing
public class FilterSortTransposeRule
extends RelRule<FilterSortTransposeRule.Config>
implements TransformationRule {
protected FilterSortTransposeRule(FilterSortTransposeRule.Config config) {
super(config);
}

@Deprecated // to be removed before 2.0
public FilterSortTransposeRule(RelBuilderFactory relBuilderFactory) {
this(FilterSortTransposeRule.Config.DEFAULT.withRelBuilderFactory(relBuilderFactory)
.as(FilterSortTransposeRule.Config.class));
}

@Override public void onMatch(RelOptRuleCall call) {
final Filter filter = call.rel(0);
final Sort sort = call.rel(1);
final RelBuilder builder = call.builder();

final RexNode condition = filter.getCondition();

RelNode newSort = builder.push(sort.getInput())
.filter(condition)
.sort(sort.getCollation())
.build();

call.transformTo(newSort);
}

/** Rule configuration. */
@Value.Immutable
public interface Config extends RelRule.Config {
Config DEFAULT = ImmutableFilterSortTransposeRule.Config.of()
.withOperandSupplier(f ->
f.operand(Filter.class)
.oneInput(s ->
s.operand(Sort.class).anyInputs()));

@Override default FilterSortTransposeRule toRule() {
return new FilterSortTransposeRule(this);
}
}
}
13 changes: 13 additions & 0 deletions core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,19 @@ private static boolean skipItem(RexNode expr) {
.check();
}

/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-6878">[CALCITE-6878]
* Add the planner rule that pushes the Filter past a Sort</a>. */
@Test void testFilterSortTranspose() {
final Function<RelBuilder, RelNode> relFn = b -> b
.scan("EMP")
.project(b.field(0))
.sort(b.field(0))
.filter(b.lessThan(b.field(0), b.literal(10)))
.build();
relFn(relFn).withRule(CoreRules.FILTER_SORT_TRANSPOSE).check();
}

@Test void testReduceOrCaseWhen() {
HepProgramBuilder builder = new HepProgramBuilder();
builder.addRuleClass(ReduceExpressionsRule.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5391,6 +5391,24 @@ LogicalProject(DEPTNO=[$7])
Sample(mode=[system], rate=[0.5], repeatableSeed=[10])
LogicalFilter(condition=[>($7, 10)])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
</Resource>
</TestCase>
<TestCase name="testFilterSortTranspose">
<Resource name="planBefore">
<![CDATA[
LogicalFilter(condition=[<($0, 10)])
LogicalSort(sort0=[$0], dir0=[ASC])
LogicalProject(EMPNO=[$0])
LogicalTableScan(table=[[scott, EMP]])
]]>
</Resource>
<Resource name="planAfter">
<![CDATA[
LogicalSort(sort0=[$0], dir0=[ASC])
LogicalFilter(condition=[<($0, 10)])
LogicalProject(EMPNO=[$0])
LogicalTableScan(table=[[scott, EMP]])
]]>
</Resource>
</TestCase>
Expand Down

0 comments on commit 8ea0df9

Please sign in to comment.