This is an automated email from the ASF dual-hosted git repository. zabetak pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/calcite.git
commit 126dc7692d8b3261fba20956093681688e44fe4a Author: Jiatao Tao <[email protected]> AuthorDate: Fri Apr 16 11:50:50 2021 +0800 [CALCITE-4583] Control simplification in `RelBuilder#filter` with `config.simplify()` (Jiatao Tao) Close apache/calcite#2398 --- .../java/org/apache/calcite/tools/RelBuilder.java | 29 ++++++++++++++-------- .../org/apache/calcite/test/RelBuilderTest.java | 24 +++++++++++++++++- .../org/apache/calcite/test/RelOptRulesTest.xml | 5 ++-- 3 files changed, 44 insertions(+), 14 deletions(-) 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 04b7df6..ba1d362 100644 --- a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java +++ b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java @@ -1334,22 +1334,29 @@ public class RelBuilder { * * <p>The predicates are combined using AND, * and optimized in a similar way to the {@link #and} method. - * If the result is TRUE no filter is created. */ + * If simplification is on and the result is TRUE, no filter is created. */ public RelBuilder filter(Iterable<CorrelationId> variablesSet, Iterable<? extends RexNode> predicates) { - final RexNode simplifiedPredicates = - simplifier.simplifyFilterPredicates(predicates); - if (simplifiedPredicates == null) { - return empty(); + final RexNode conjunctionPredicates; + if (config.simplify()) { + conjunctionPredicates = simplifier.simplifyFilterPredicates(predicates); + } else { + conjunctionPredicates = + RexUtil.composeConjunction(simplifier.rexBuilder, predicates); } - if (!simplifiedPredicates.isAlwaysTrue()) { - final Frame frame = stack.pop(); - final RelNode filter = - struct.filterFactory.createFilter(frame.rel, - simplifiedPredicates, ImmutableSet.copyOf(variablesSet)); - stack.push(new Frame(filter, frame.fields)); + if (conjunctionPredicates == null || conjunctionPredicates.isAlwaysFalse()) { + return empty(); } + if (conjunctionPredicates.isAlwaysTrue()) { + return this; + } + + final Frame frame = stack.pop(); + final RelNode filter = + struct.filterFactory.createFilter(frame.rel, + conjunctionPredicates, ImmutableSet.copyOf(variablesSet)); + stack.push(new Frame(filter, frame.fields)); return this; } 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 aee5b9d..b2995c6 100644 --- a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java +++ b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java @@ -3636,9 +3636,13 @@ public class RelBuilderTest { final String expected = "" + "LogicalFilter(condition=[OR(SEARCH($7, Sarg[10, 11, (15..+∞)]), =($2, 'CLERK'))])\n" + " LogicalTableScan(table=[[scott, EMP]])\n"; + final String expectedWithoutSimplify = "" + + "LogicalFilter(condition=[OR(>($7, 15), SEARCH($2, Sarg['CLERK']:CHAR(5)), SEARCH($7, " + + "Sarg[10, 11, 20]))])\n" + + " LogicalTableScan(table=[[scott, EMP]])\n"; assertThat(f.apply(createBuilder()), hasTree(expected)); assertThat(f.apply(createBuilder(c -> c.withSimplify(false))), - hasTree(expected)); + hasTree(expectedWithoutSimplify)); } /** Tests filter builder with correlation variables. */ @@ -3709,6 +3713,24 @@ public class RelBuilderTest { assertThat(root, hasTree("LogicalValues(tuples=[[]])\n")); } + @Test void testFilterWithoutSimplification() { + final RelBuilder builder = createBuilder(c -> c.withSimplify(false)); + final RelNode root = + builder.scan("EMP") + .filter( + builder.or( + builder.literal(null), + builder.and( + builder.equals(builder.field(2), builder.literal(1)), + builder.equals(builder.field(2), builder.literal(2)) + ))) + .build(); + final String expected = "" + + "LogicalFilter(condition=[OR(null:NULL, AND(=($2, 1), =($2, 2)))])\n" + + " LogicalTableScan(table=[[scott, EMP]])\n"; + assertThat(root, hasTree(expected)); + } + @Test void testRelBuilderToString() { final RelBuilder builder = RelBuilder.create(config().build()); builder.scan("EMP"); 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 3dc6ad2..c30446f 100644 --- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml +++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml @@ -3622,7 +3622,8 @@ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], EMPNO0=[$9], ENAME0=[$10], JOB0=[$11], MGR0=[$12], HIREDATE0=[$13], SAL0=[$14], COMM0=[$15], DEPTNO0=[$16], SLACKER0=[$17]) LogicalJoin(condition=[=($16, $7)], joinType=[inner]) LogicalFilter(condition=[SEARCH($7, Sarg[(-∞..4), (4..6), (6..+∞)])]) - LogicalTableScan(table=[[CATALOG, SALES, EMP]]) + LogicalFilter(condition=[NOT(OR(=($7, 4), =($7, 6)))]) + LogicalTableScan(table=[[CATALOG, SALES, EMP]]) LogicalFilter(condition=[SEARCH($7, Sarg[(-∞..4), (4..6), (6..+∞)])]) LogicalTableScan(table=[[CATALOG, SALES, EMP]]) ]]> @@ -11862,7 +11863,7 @@ LogicalProject(EXPR$0=[CASE(true, CAST($7):INTEGER, null:INTEGER)]) <![CDATA[ LogicalProject(EMPNO=[$0]) LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8]) - LogicalFilter(condition=[<($0, CASE(OR(AND(IS NOT NULL($12), <>($9, 0)), AND(<($10, $9), null, <>($9, 0), IS NULL($12))), 10, AND(OR(IS NULL($12), =($9, 0)), OR(>=($10, $9), =($9, 0), IS NOT NULL($12))), 20, 30))]) + LogicalFilter(condition=[<($0, CASE(=(CASE(=($9, 0), false, IS NOT NULL($12), true, <($10, $9), null:BOOLEAN, false), true), 10, =(CASE(=($9, 0), false, IS NOT NULL($12), true, <($10, $9), null:BOOLEAN, false), false), 20, 30))]) LogicalJoin(condition=[=($7, $11)], joinType=[left]) LogicalJoin(condition=[true], joinType=[inner]) LogicalTableScan(table=[[CATALOG, SALES, EMP]])
