This is an automated email from the ASF dual-hosted git repository.
kgyrtkirk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push:
new c462838 [CALCITE-2838] Simplification: Remove redundant IS TRUE/IS
NOT FALSE checks
c462838 is described below
commit c462838f37f02b490088a216773415926688e9f3
Author: Zoltan Haindrich <[email protected]>
AuthorDate: Thu Feb 14 09:15:31 2019 +0100
[CALCITE-2838] Simplification: Remove redundant IS TRUE/IS NOT FALSE checks
Earlier expressions like ((x IS TRUE) IS TRUE) were left as is, the new
behaviour
recognizes if the IS TRUE/IS NOT FALSE check is redundant.
In case ((x IS TRUE) IS TRUE) is a filter expression, it is simplified to
'x'.
---
.../java/org/apache/calcite/rex/RexSimplify.java | 46 ++++++++++++----
.../org/apache/calcite/test/RelOptRulesTest.java | 2 +-
.../org/apache/calcite/test/RexProgramTest.java | 63 ++++++++++++++++++----
.../calcite/test/fuzzer/RexProgramFuzzyTest.java | 7 +--
.../org/apache/calcite/test/RelOptRulesTest.xml | 18 +++----
core/src/test/resources/sql/blank.iq | 4 +-
core/src/test/resources/sql/sub-query.iq | 36 +++----------
7 files changed, 112 insertions(+), 64 deletions(-)
diff --git a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
index 7ae8195..15e3b94 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
@@ -275,7 +275,7 @@ public class RexSimplify {
case IS_FALSE:
case IS_NOT_FALSE:
assert e instanceof RexCall;
- return simplifyIs((RexCall) e);
+ return simplifyIs((RexCall) e, unknownAs);
case EQUALS:
case GREATER_THAN:
case GREATER_THAN_OR_EQUAL:
@@ -534,16 +534,35 @@ public class RexSimplify {
return rexBuilder.makeCall(SqlStdOperatorTable.NOT, a2);
}
- private RexNode simplifyIs(RexCall call) {
+ private RexNode simplifyIs(RexCall call, RexUnknownAs unknownAs) {
final SqlKind kind = call.getKind();
final RexNode a = call.getOperands().get(0);
+ // UnknownAs.FALSE corresponds to x IS TRUE evaluation
+ // UnknownAs.TRUE to x IS NOT FALSE
+ // Note that both UnknownAs.TRUE and UnknownAs.FALSE only changes the
meaning of Unknown
+ // (1) if we are already in UnknownAs.FALSE mode; x IS TRUE can be
simiplified to x
+ // (2) similarily in UnknownAs.TRUE mode ; x IS NOT FALSE can be
simplified to x
+ // (3) x IS FALSE could be rewritten to (NOT x) IS TRUE and from there the
1. rule applies
+ // (4) x IS NOT TRUE can be rewritten to (NOT x) IS NOT FALSE and from
there the 2. rule applies
+ if (kind == SqlKind.IS_TRUE && unknownAs == RexUnknownAs.FALSE) {
+ return simplify(a, unknownAs);
+ }
+ if (kind == SqlKind.IS_FALSE && unknownAs == RexUnknownAs.FALSE) {
+ return simplify(rexBuilder.makeCall(SqlStdOperatorTable.NOT, a),
unknownAs);
+ }
+ if (kind == SqlKind.IS_NOT_FALSE && unknownAs == RexUnknownAs.TRUE) {
+ return simplify(a, unknownAs);
+ }
+ if (kind == SqlKind.IS_NOT_TRUE && unknownAs == RexUnknownAs.TRUE) {
+ return simplify(rexBuilder.makeCall(SqlStdOperatorTable.NOT, a),
unknownAs);
+ }
final RexNode pred = simplifyIsPredicate(kind, a);
if (pred != null) {
return pred;
}
- final RexNode simplified = simplifyIs2(kind, a);
+ final RexNode simplified = simplifyIs2(kind, a, unknownAs);
if (simplified != null) {
return simplified;
}
@@ -567,21 +586,21 @@ public class RexSimplify {
return null;
}
- private RexNode simplifyIs2(SqlKind kind, RexNode a) {
+ private RexNode simplifyIs2(SqlKind kind, RexNode a, RexUnknownAs unknownAs)
{
final RexNode simplified;
switch (kind) {
case IS_NULL:
// x IS NULL ==> FALSE (if x is not nullable)
simplified = simplifyIsNull(a);
if (simplified != null) {
- return simplified;
+ return simplify(simplified, unknownAs);
}
break;
case IS_NOT_NULL:
// x IS NOT NULL ==> TRUE (if x is not nullable)
simplified = simplifyIsNotNull(a);
if (simplified != null) {
- return simplified;
+ return simplify(simplified, unknownAs);
}
break;
case IS_TRUE:
@@ -589,16 +608,21 @@ public class RexSimplify {
// x IS TRUE ==> x (if x is not nullable)
// x IS NOT FALSE ==> x (if x is not nullable)
if (!a.getType().isNullable()) {
- return simplify(a, UNKNOWN);
+ return simplify(a, unknownAs);
+ } else {
+ RexNode newSub =
+ simplify(a, kind == SqlKind.IS_TRUE ? RexUnknownAs.FALSE :
RexUnknownAs.TRUE);
+ if (newSub == a) {
+ return null;
+ }
+ return rexBuilder.makeCall(RexUtil.op(kind), ImmutableList.of(newSub));
}
- break;
case IS_FALSE:
case IS_NOT_TRUE:
// x IS NOT TRUE ==> NOT x (if x is not nullable)
// x IS FALSE ==> NOT x (if x is not nullable)
if (!a.getType().isNullable()) {
- return simplify(rexBuilder.makeCall(SqlStdOperatorTable.NOT, a),
- UNKNOWN);
+ return simplify(rexBuilder.makeCall(SqlStdOperatorTable.NOT, a),
unknownAs);
}
break;
}
@@ -1129,7 +1153,7 @@ public class RexSimplify {
for (RexNode notSatisfiableNullable : notSatisfiableNullables) {
terms.add(
simplifyIs((RexCall)
- rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL,
notSatisfiableNullable)));
+ rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL,
notSatisfiableNullable), UNKNOWN));
}
}
// Add the NOT disjunctions back in.
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 9dca7b1..ef2b705 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -1805,7 +1805,7 @@ public class RelOptRulesTest extends RelOptTestBase {
.addRuleInstance(ReduceExpressionsRule.JOIN_INSTANCE)
.build();
- checkPlanning(new HepPlanner(program),
+ checkPlanUnchanged(new HepPlanner(program),
"select p1 is not distinct from p0 from (values (2, cast(null as
integer))) as t(p0, p1)");
}
diff --git a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
index 3234050..b9e9ba0 100644
--- a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
@@ -299,9 +299,8 @@ public class RexProgramTest extends RexProgramBuilderBase {
assertThat(program.normalize(rexBuilder, simplify).toString(),
is("(expr#0..1=[{inputs}], expr#2=[+($t0, $t1)], expr#3=[1], "
+ "expr#4=[+($t0, $t3)], expr#5=[+($t2, $t4)], "
- + "expr#6=[+($t0, $t4)], expr#7=[5], expr#8=[>($t4, $t7)], "
- + "expr#9=[NOT($t8)], "
- + "a=[$t5], b=[$t6], $condition=[$t9])"));
+ + "expr#6=[+($t0, $t4)], expr#7=[5], expr#8=[<=($t4, $t7)], "
+ + "a=[$t5], b=[$t6], $condition=[$t8])"));
}
/**
@@ -321,9 +320,8 @@ public class RexProgramTest extends RexProgramBuilderBase {
assertThat(program.normalize(rexBuilder, simplify).toString(),
is("(expr#0..1=[{inputs}], expr#2=[+($t0, $t1)], expr#3=[1], "
+ "expr#4=[+($t0, $t3)], expr#5=[+($t2, $t4)], "
- + "expr#6=[+($t0, $t4)], expr#7=[5], expr#8=[>($t4, $t7)], "
- + "expr#9=[NOT($t8)], "
- + "a=[$t5], b=[$t6], $condition=[$t9])"));
+ + "expr#6=[+($t0, $t4)], expr#7=[5], expr#8=[<=($t4, $t7)], "
+ + "a=[$t5], b=[$t6], $condition=[$t8])"));
}
/**
@@ -1801,7 +1799,7 @@ public class RexProgramTest extends RexProgramBuilderBase
{
isTrue(vBool()), literal(1),
isNotTrue(vBool()), literal(1),
literal(2)),
- "CASE(OR(IS TRUE(?0.bool0), IS NOT TRUE(?0.bool0)), 1, 2)");
+ "CASE(OR(?0.bool0, IS NOT TRUE(?0.bool0)), 1, 2)");
}
@Test public void testSimplifyCaseBranchesCollapse2() {
@@ -1909,7 +1907,7 @@ public class RexProgramTest extends RexProgramBuilderBase
{
isTrue(vBool()), vBool(1),
gt(div(vIntNotNull(), literal(2)), literal(1)), vBool(2),
vBool(3))),
- "CASE(IS TRUE(?0.bool0), NOT(?0.bool1), >(/(?0.notNullInt0, 2), 1),
NOT(?0.bool2), NOT(?0.bool3))");
+ "CASE(?0.bool0, NOT(?0.bool1), >(/(?0.notNullInt0, 2), 1),
NOT(?0.bool2), NOT(?0.bool3))");
}
@Test public void testNotRecursion() {
@@ -2434,9 +2432,13 @@ public class RexProgramTest extends
RexProgramBuilderBase {
// "NOT(false)" => "true"
checkSimplify(not(falseLiteral), "true");
// "NOT(IS FALSE(x))" => "IS NOT FALSE(x)"
- checkSimplify(not(isFalse(vBool())), "IS NOT FALSE(?0.bool0)");
+ checkSimplify3(not(isFalse(vBool())),
+ "IS NOT FALSE(?0.bool0)", "IS NOT FALSE(?0.bool0)", "?0.bool0");
// "NOT(IS TRUE(x))" => "IS NOT TRUE(x)"
- checkSimplify(not(isTrue(vBool())), "IS NOT TRUE(?0.bool0)");
+ checkSimplify3(not(isTrue(vBool())),
+ "IS NOT TRUE(?0.bool0)",
+ "IS NOT TRUE(?0.bool0)",
+ "NOT(?0.bool0)");
// "NOT(IS NULL(x))" => "IS NOT NULL(x)"
checkSimplify(not(isNull(vBool())), "IS NOT NULL(?0.bool0)");
// "NOT(IS NOT NULL(x)) => "IS NULL(x)"
@@ -2512,6 +2514,47 @@ public class RexProgramTest extends
RexProgramBuilderBase {
is(false));
}
+ @Test public void testIsNullRecursion() {
+ // make sure that simplifcation is visiting below isX expressions
+ checkSimplify(
+ isNull(or(coalesce(nullBool, trueLiteral), falseLiteral)),
+ "false");
+ }
+
+ @Test public void testRedundantIsTrue() {
+ checkSimplify2(
+ isTrue(isTrue(vBool())),
+ "IS TRUE(?0.bool0)",
+ "?0.bool0"
+ );
+ }
+
+ @Test public void testRedundantIsFalse() {
+ checkSimplify2(
+ isTrue(isFalse(vBool())),
+ "IS FALSE(?0.bool0)",
+ "NOT(?0.bool0)"
+ );
+ }
+
+ @Test public void testRedundantIsNotTrue() {
+ checkSimplify3(
+ isNotFalse(isNotTrue(vBool())),
+ "IS NOT TRUE(?0.bool0)",
+ "IS NOT TRUE(?0.bool0)",
+ "NOT(?0.bool0)"
+ );
+ }
+
+ @Test public void testRedundantIsNotFalse() {
+ checkSimplify3(
+ isNotFalse(isNotFalse(vBool())),
+ "IS NOT FALSE(?0.bool0)",
+ "IS NOT FALSE(?0.bool0)",
+ "?0.bool0"
+ );
+ }
+
/** Unit tests for
* <a
href="https://issues.apache.org/jira/browse/CALCITE-2438">[CALCITE-2438]
* RexCall#isAlwaysTrue returns incorrect result</a>. */
diff --git
a/core/src/test/java/org/apache/calcite/test/fuzzer/RexProgramFuzzyTest.java
b/core/src/test/java/org/apache/calcite/test/fuzzer/RexProgramFuzzyTest.java
index 4b86f5b..e745d49 100644
--- a/core/src/test/java/org/apache/calcite/test/fuzzer/RexProgramFuzzyTest.java
+++ b/core/src/test/java/org/apache/calcite/test/fuzzer/RexProgramFuzzyTest.java
@@ -262,11 +262,12 @@ public class RexProgramFuzzyTest extends
RexProgramBuilderBase {
}
}
}
- if (opt.getType().isNullable() && !node.getType().isNullable()) {
+ if (unknownAs == RexUnknownAs.UNKNOWN
+ && opt.getType().isNullable()
+ && !node.getType().isNullable()) {
fail(nodeToString(node) + " had non-nullable type " + opt.getType()
+ ", and it was optimized to " + nodeToString(opt)
- + " that has nullable type " + opt.getType()
- + ", " + uaf);
+ + " that has nullable type " + opt.getType());
}
if (!SqlTypeUtil.equalSansNullability(typeFactory, node.getType(),
opt.getType())) {
assertEquals(nodeToString(node) + " has different type after
simplification to "
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 8c7e46c..5da4200 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -481,7 +481,7 @@ LogicalProject(DEPTNO=[$0])
<![CDATA[
LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4],
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4],
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
- LogicalFilter(condition=[AND(OR(IS NOT TRUE(<=($0, $9)), =($10, 0)),
OR(<=($10, $11), =($10, 0), IS TRUE(<=($0, $9))), OR(>($0, $9), =($10, 0), IS
TRUE(<=($0, $9)), >($10, $11)))])
+ LogicalFilter(condition=[AND(OR(IS NOT TRUE(<=($0, $9)), =($10, 0)),
OR(<=($10, $11), =($10, 0), <=($0, $9)), OR(>($0, $9), =($10, 0), <=($0, $9),
>($10, $11)))])
LogicalJoin(condition=[true], joinType=[inner])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
LogicalAggregate(group=[{}], m=[MAX($0)], c=[COUNT()], d=[COUNT($0)])
@@ -493,7 +493,7 @@ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3],
HIREDATE=[$4], SAL=[$
<![CDATA[
LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4],
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4],
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
- LogicalFilter(condition=[AND(OR(IS NOT TRUE(<=($0, $9)), =($10, 0)),
OR(<=($10, $11), =($10, 0), IS TRUE(<=($0, $9))), OR(>($0, $9), =($10, 0), IS
TRUE(<=($0, $9)), >($10, $11)))])
+ LogicalFilter(condition=[AND(OR(IS NOT TRUE(<=($0, $9)), =($10, 0)),
OR(<=($10, $11), =($10, 0), <=($0, $9)), OR(>($0, $9), =($10, 0), <=($0, $9),
>($10, $11)))])
LogicalJoin(condition=[true], joinType=[inner])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
LogicalAggregate(group=[{}], m=[MAX($0)], c=[COUNT()], d=[COUNT($0)])
@@ -2241,7 +2241,7 @@ LogicalCalc(expr#0=[{inputs}], expr#1=['TABLE
':VARCHAR(26)], expr#2=['t'
</Resource>
<Resource name="planBefore">
<![CDATA[
-LogicalProject(EXPR$0=[IS TRUE(null:BOOLEAN)])
+LogicalProject(EXPR$0=[false])
LogicalValues(tuples=[[{ 0 }]])
]]>
</Resource>
@@ -2637,7 +2637,7 @@ LogicalFilter(condition=[IS NOT DISTINCT FROM($7, 20)])
</Resource>
<Resource name="planAfter">
<![CDATA[
-LogicalFilter(condition=[IS TRUE(=($7, 20))])
+LogicalFilter(condition=[=($7, 20)])
LogicalTableScan(table=[[scott, EMP]])
]]>
</Resource>
@@ -4551,7 +4551,7 @@ LogicalAggregate(group=[{}], EXPR$0=[COUNT()])
<![CDATA[
LogicalAggregate(group=[{}], EXPR$0=[COUNT()])
LogicalProject($f0=[0])
- LogicalFilter(condition=[IS TRUE(<($0, 10))])
+ LogicalFilter(condition=[<($0, 10)])
LogicalProject(MGR=[$3])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
@@ -8512,7 +8512,7 @@ LogicalProject(DEPTNO=[$0])
<Resource name="planAfter">
<![CDATA[
LogicalProject(SAL=[$5])
- LogicalFilter(condition=[OR(IS NOT TRUE(OR(IS NOT NULL($13), <($11, $10))),
IS TRUE(=($10, 0)))])
+ LogicalFilter(condition=[OR(IS NOT TRUE(OR(IS NOT NULL($13), <($11, $10))),
=($10, 0))])
LogicalJoin(condition=[AND(=($0, $12), =($2, $14))], joinType=[left])
LogicalJoin(condition=[=($2, $9)], joinType=[left])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
@@ -8527,7 +8527,7 @@ LogicalProject(SAL=[$5])
<![CDATA[
LogicalProject(SAL=[$5])
LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4],
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
- LogicalFilter(condition=[OR(IS NOT TRUE(OR(IS NOT NULL($12), <($10, $9))),
IS TRUE(=($9, 0)))])
+ LogicalFilter(condition=[OR(IS NOT TRUE(OR(IS NOT NULL($12), <($10, $9))),
=($9, 0))])
LogicalCorrelate(correlation=[$cor0], joinType=[left],
requiredColumns=[{2}])
LogicalCorrelate(correlation=[$cor0], joinType=[left],
requiredColumns=[{2}])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
@@ -8604,7 +8604,7 @@ LogicalProject(EMPNO=[$1])
<![CDATA[
LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4],
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4],
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
- LogicalFilter(condition=[OR(IS NOT TRUE(OR(IS NOT NULL($12), <($10, $9))),
IS TRUE(=($9, 0)))])
+ LogicalFilter(condition=[OR(IS NOT TRUE(OR(IS NOT NULL($12), <($10, $9))),
=($9, 0))])
LogicalCorrelate(correlation=[$cor0], joinType=[left],
requiredColumns=[{1}])
LogicalCorrelate(correlation=[$cor0], joinType=[left],
requiredColumns=[{1}])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
@@ -8623,7 +8623,7 @@ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2],
MGR=[$3], HIREDATE=[$4], SAL=[$
<Resource name="planAfter">
<![CDATA[
LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4],
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
- LogicalFilter(condition=[OR(IS NOT TRUE(OR(IS NOT NULL($13), <($11, $10))),
IS TRUE(=($10, 0)))])
+ LogicalFilter(condition=[OR(IS NOT TRUE(OR(IS NOT NULL($13), <($11, $10))),
=($10, 0))])
LogicalJoin(condition=[AND(=($0, $12), =($1, $14))], joinType=[left])
LogicalJoin(condition=[=($1, $9)], joinType=[left])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
diff --git a/core/src/test/resources/sql/blank.iq
b/core/src/test/resources/sql/blank.iq
index 80bfe3d..1cae199 100644
--- a/core/src/test/resources/sql/blank.iq
+++ b/core/src/test/resources/sql/blank.iq
@@ -73,9 +73,9 @@ insert into table2 values (NULL, 1), (2, 1);
# Checked on Oracle
!set lateDecorrelate true
select i, j from table1 where table1.j NOT IN (select i from table2 where
table1.i=table2.j);
-EnumerableCalc(expr#0..7=[{inputs}], expr#8=[IS NOT NULL($t7)], expr#9=[<($t4,
$t3)], expr#10=[OR($t8, $t9)], expr#11=[IS NOT TRUE($t10)], expr#12=[0],
expr#13=[=($t3, $t12)], expr#14=[IS TRUE($t13)], expr#15=[IS NULL($t1)],
expr#16=[OR($t11, $t14, $t15)], proj#0..1=[{exprs}], $condition=[$t16])
+EnumerableCalc(expr#0..7=[{inputs}], expr#8=[IS NOT NULL($t7)], expr#9=[<($t4,
$t3)], expr#10=[OR($t8, $t9)], expr#11=[IS NOT TRUE($t10)], expr#12=[0],
expr#13=[=($t3, $t12)], expr#14=[IS NULL($t1)], expr#15=[OR($t11, $t13, $t14)],
proj#0..1=[{exprs}], $condition=[$t15])
EnumerableJoin(condition=[AND(=($0, $6), =($1, $5))], joinType=[left])
- EnumerableCalc(expr#0..4=[{inputs}], expr#5=[IS NOT NULL($t1)],
expr#6=[0], expr#7=[=($t3, $t6)], expr#8=[IS TRUE($t7)], expr#9=[OR($t5, $t8)],
proj#0..4=[{exprs}], $condition=[$t9])
+ EnumerableCalc(expr#0..4=[{inputs}], expr#5=[IS NOT NULL($t1)],
expr#6=[0], expr#7=[=($t3, $t6)], expr#8=[OR($t5, $t7)], proj#0..4=[{exprs}],
$condition=[$t8])
EnumerableJoin(condition=[=($0, $2)], joinType=[left])
EnumerableTableScan(table=[[BLANK, TABLE1]])
EnumerableAggregate(group=[{1}], c=[COUNT()], ck=[COUNT($0)])
diff --git a/core/src/test/resources/sql/sub-query.iq
b/core/src/test/resources/sql/sub-query.iq
index b9f6b3f..c3aa3f2 100644
--- a/core/src/test/resources/sql/sub-query.iq
+++ b/core/src/test/resources/sql/sub-query.iq
@@ -1440,7 +1440,7 @@ select sal from "scott".emp
(0 rows)
!ok
-EnumerableCalc(expr#0..3=[{inputs}], expr#4=[false], expr#5=[=($t2, $t4)],
expr#6=[IS NOT TRUE($t5)], expr#7=[IS NULL($t3)], expr#8=[OR($t6, $t7)],
expr#9=[IS TRUE($t5)], expr#10=[OR($t7, $t9)], expr#11=[AND($t8, $t10)],
SAL=[$t1], $condition=[$t11])
+EnumerableCalc(expr#0..3=[{inputs}], expr#4=[false], expr#5=[=($t2, $t4)],
expr#6=[IS NOT TRUE($t5)], expr#7=[IS NULL($t3)], expr#8=[OR($t6, $t7)],
expr#9=[OR($t7, $t5)], expr#10=[AND($t8, $t9)], SAL=[$t1], $condition=[$t10])
EnumerableJoin(condition=[true], joinType=[left])
EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5])
EnumerableTableScan(table=[[scott, EMP]])
@@ -1482,7 +1482,7 @@ select sal from "scott".emp
(0 rows)
!ok
-EnumerableCalc(expr#0..3=[{inputs}], expr#4=[false], expr#5=[=($t2, $t4)],
expr#6=[IS NOT TRUE($t5)], expr#7=[IS NULL($t3)], expr#8=[OR($t6, $t7)],
expr#9=[IS TRUE($t5)], expr#10=[OR($t7, $t9)], expr#11=[AND($t8, $t10)],
SAL=[$t1], $condition=[$t11])
+EnumerableCalc(expr#0..3=[{inputs}], expr#4=[false], expr#5=[=($t2, $t4)],
expr#6=[IS NOT TRUE($t5)], expr#7=[IS NULL($t3)], expr#8=[OR($t6, $t7)],
expr#9=[OR($t7, $t5)], expr#10=[AND($t8, $t9)], SAL=[$t1], $condition=[$t10])
EnumerableJoin(condition=[true], joinType=[left])
EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5])
EnumerableTableScan(table=[[scott, EMP]])
@@ -1503,7 +1503,7 @@ select sal from "scott".emp
(0 rows)
!ok
-EnumerableCalc(expr#0..3=[{inputs}], expr#4=[false], expr#5=[=($t2, $t4)],
expr#6=[IS NOT TRUE($t5)], expr#7=[IS NULL($t3)], expr#8=[OR($t6, $t7)],
expr#9=[IS TRUE($t5)], expr#10=[OR($t7, $t9)], expr#11=[AND($t8, $t10)],
SAL=[$t1], $condition=[$t11])
+EnumerableCalc(expr#0..3=[{inputs}], expr#4=[false], expr#5=[=($t2, $t4)],
expr#6=[IS NOT TRUE($t5)], expr#7=[IS NULL($t3)], expr#8=[OR($t6, $t7)],
expr#9=[OR($t7, $t5)], expr#10=[AND($t8, $t9)], SAL=[$t1], $condition=[$t10])
EnumerableJoin(condition=[true], joinType=[left])
EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5])
EnumerableTableScan(table=[[scott, EMP]])
@@ -1524,7 +1524,7 @@ select sal from "scott".emp
(0 rows)
!ok
-EnumerableCalc(expr#0..3=[{inputs}], expr#4=[false], expr#5=[=($t2, $t4)],
expr#6=[IS NOT TRUE($t5)], expr#7=[IS NULL($t3)], expr#8=[OR($t6, $t7)],
expr#9=[IS TRUE($t5)], expr#10=[OR($t7, $t9)], expr#11=[AND($t8, $t10)],
SAL=[$t1], $condition=[$t11])
+EnumerableCalc(expr#0..3=[{inputs}], expr#4=[false], expr#5=[=($t2, $t4)],
expr#6=[IS NOT TRUE($t5)], expr#7=[IS NULL($t3)], expr#8=[OR($t6, $t7)],
expr#9=[OR($t7, $t5)], expr#10=[AND($t8, $t9)], SAL=[$t1], $condition=[$t10])
EnumerableJoin(condition=[true], joinType=[left])
EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5])
EnumerableTableScan(table=[[scott, EMP]])
@@ -1747,12 +1747,7 @@ select sal from "scott".emp e
(0 rows)
!ok
-EnumerableCalc(expr#0..4=[{inputs}], expr#5=[false], expr#6=[=($t4, $t5)],
expr#7=[IS NOT TRUE($t6)], expr#8=[IS TRUE($t6)], expr#9=[AND($t7, $t8)],
SAL=[$t1], $condition=[$t9])
- EnumerableJoin(condition=[=($2, $3)], joinType=[left])
- EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5], DEPTNO=[$t7])
- EnumerableTableScan(table=[[scott, EMP]])
- EnumerableCalc(expr#0..2=[{inputs}], expr#3=[false], DEPTNO=[$t0],
$f1=[$t3])
- EnumerableTableScan(table=[[scott, DEPT]])
+EnumerableValues(tuples=[[]])
!plan
# Test filter literal NOT IN null correlated
@@ -1783,12 +1778,7 @@ select sal from "scott".emp e
(0 rows)
!ok
-EnumerableCalc(expr#0..4=[{inputs}], expr#5=[false], expr#6=[=($t4, $t5)],
expr#7=[IS NOT TRUE($t6)], expr#8=[IS TRUE($t6)], expr#9=[AND($t7, $t8)],
SAL=[$t1], $condition=[$t9])
- EnumerableJoin(condition=[=($2, $3)], joinType=[left])
- EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5], DEPTNO=[$t7])
- EnumerableTableScan(table=[[scott, EMP]])
- EnumerableCalc(expr#0..2=[{inputs}], expr#3=[true], DEPTNO=[$t0],
$f1=[$t3])
- EnumerableTableScan(table=[[scott, DEPT]])
+EnumerableValues(tuples=[[]])
!plan
# Test filter null NOT IN required correlated
@@ -1801,12 +1791,7 @@ select sal from "scott".emp e
(0 rows)
!ok
-EnumerableCalc(expr#0..4=[{inputs}], expr#5=[false], expr#6=[=($t4, $t5)],
expr#7=[IS NOT TRUE($t6)], expr#8=[IS TRUE($t6)], expr#9=[AND($t7, $t8)],
SAL=[$t1], $condition=[$t9])
- EnumerableJoin(condition=[=($2, $3)], joinType=[left])
- EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5], DEPTNO=[$t7])
- EnumerableTableScan(table=[[scott, EMP]])
- EnumerableCalc(expr#0..2=[{inputs}], expr#3=[true], DEPTNO=[$t0],
$f1=[$t3])
- EnumerableTableScan(table=[[scott, DEPT]])
+EnumerableValues(tuples=[[]])
!plan
# Test filter null NOT IN nullable correlated
@@ -1819,12 +1804,7 @@ select sal from "scott".emp e
(0 rows)
!ok
-EnumerableCalc(expr#0..4=[{inputs}], expr#5=[false], expr#6=[=($t4, $t5)],
expr#7=[IS NOT TRUE($t6)], expr#8=[IS TRUE($t6)], expr#9=[AND($t7, $t8)],
SAL=[$t1], $condition=[$t9])
- EnumerableJoin(condition=[=($2, $3)], joinType=[left])
- EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5], DEPTNO=[$t7])
- EnumerableTableScan(table=[[scott, EMP]])
- EnumerableCalc(expr#0..2=[{inputs}], expr#3=[true], DEPTNO=[$t0],
$f1=[$t3])
- EnumerableTableScan(table=[[scott, DEPT]])
+EnumerableValues(tuples=[[]])
!plan
# Test filter literal NOT IN required correlated