diff --git a/core/src/main/java/org/apache/calcite/rex/RexCall.java b/core/src/main/java/org/apache/calcite/rex/RexCall.java index 498d86ef76c0..d2c4ac295206 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexCall.java +++ b/core/src/main/java/org/apache/calcite/rex/RexCall.java @@ -121,11 +121,12 @@ public RelDataType getType() { switch (getKind()) { case IS_NOT_NULL: return !operands.get(0).getType().isNullable(); - case IS_NOT_FALSE: - case NOT: - return operands.get(0).isAlwaysFalse(); case IS_NOT_TRUE: case IS_FALSE: + case NOT: + return operands.get(0).isAlwaysFalse(); + case IS_NOT_FALSE: + case IS_TRUE: case CAST: return operands.get(0).isAlwaysTrue(); default: @@ -138,6 +139,7 @@ public RelDataType getType() { case IS_NULL: return !operands.get(0).getType().isNullable(); case IS_NOT_TRUE: + case IS_FALSE: case NOT: return operands.get(0).isAlwaysTrue(); case IS_NOT_FALSE: 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 733579d05925..fd257a9ae253 100644 --- a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java +++ b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java @@ -228,6 +228,22 @@ private RexNode isNotNull(RexNode node) { return rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, node); } + private RexNode isFalse(RexNode node) { + return rexBuilder.makeCall(SqlStdOperatorTable.IS_FALSE, node); + } + + private RexNode isTrue(RexNode node) { + return rexBuilder.makeCall(SqlStdOperatorTable.IS_TRUE, node); + } + + private RexNode isNotTrue(RexNode node) { + return rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_TRUE, node); + } + + private RexNode isNotFalse(RexNode node) { + return rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_FALSE, node); + } + private RexNode nullIf(RexNode node1, RexNode node2) { return rexBuilder.makeCall(SqlStdOperatorTable.NULLIF, node1, node2); } @@ -568,7 +584,7 @@ private RexProgramBuilder createProg(int variant) { // $t15 = $14 is true final RexLocalRef t15 = builder.addExpr( - rexBuilder.makeCall(SqlStdOperatorTable.IS_TRUE, t14)); + isTrue(t14)); builder.addCondition(t15); } } @@ -2128,7 +2144,7 @@ private static String getString(ImmutableMap map) { typeFactory.createTypeWithNullability( typeFactory.createSqlType(SqlTypeName.BOOLEAN), true); final RexNode booleanInput = rexBuilder.makeInputRef(booleanNullableType, 0); - final RexNode isFalse = rexBuilder.makeCall(SqlStdOperatorTable.IS_FALSE, booleanInput); + final RexNode isFalse = isFalse(booleanInput); final RexCall result = (RexCall) simplify(isFalse); assertThat(result.getType().isNullable(), is(false)); assertThat(result.getOperator(), is((SqlOperator) SqlStdOperatorTable.IS_FALSE)); @@ -2138,7 +2154,7 @@ private static String getString(ImmutableMap map) { // Make sure that IS_FALSE(IS_FALSE(nullable boolean)) != IS_TRUE(nullable boolean) // IS_FALSE(IS_FALSE(null)) = IS_FALSE(false) = true // IS_TRUE(null) = false - final RexNode isFalseIsFalse = rexBuilder.makeCall(SqlStdOperatorTable.IS_FALSE, isFalse); + final RexNode isFalseIsFalse = isFalse(isFalse); final RexCall result2 = (RexCall) simplify(isFalseIsFalse); assertThat(result2.getType().isNullable(), is(false)); assertThat(result2.getOperator(), is((SqlOperator) SqlStdOperatorTable.IS_NOT_FALSE)); @@ -2170,6 +2186,49 @@ private RexNode simplify(RexNode e) { is(false)); } + @Test public void testIsAlwaysTrueAndFalse() { + final RelDataType type = + typeFactory.createSqlType(SqlTypeName.BOOLEAN); + RexNode inputRef = rexBuilder.makeInputRef(type, 0); + + RexNode isFalseExp = isFalse(isNotNull(isNull(inputRef))); + assertEquals("expected false,but got true in isFalseExp.isAlwaysTrue()", + isFalseExp.isAlwaysTrue(), false); + assertEquals("expected true,but got false in isFalseExp.isAlwaysFalse()", + isFalseExp.isAlwaysFalse(), true); + + RexNode isFalseExp2 = isFalse(not(isNotNull(isNull(inputRef)))); + assertEquals("expected true,but got false in isFalseExp2.isAlwaysTrue()", + isFalseExp2.isAlwaysTrue(), true); + assertEquals("expected false,but got true in isFalseExp2.isAlwaysFalse()", + isFalseExp2.isAlwaysFalse(), false); + + RexNode isTrueExp = isTrue(isNotNull(isNull(inputRef))); + assertEquals("expected true,but got false in isTrueExp.isAlwaysTrue()", + isTrueExp.isAlwaysTrue(), true); + assertEquals("expected false,but got true in isTrueExp.isAlwaysFalse()", + isTrueExp.isAlwaysFalse(), false); + + RexNode isTrueExp2 = isTrue(not(isNotNull(isNull(inputRef)))); + assertEquals("expected false,but got true in isTrueExp2.isAlwaysTrue()", + isTrueExp2.isAlwaysTrue(), false); + assertEquals("expected true,but got false in isTrueExp2.isAlwaysFalse()", + isTrueExp2.isAlwaysFalse(), true); + + RexNode isNotTrueExp = isNotTrue(isNotNull(isNull(inputRef))); + assertEquals("expected false,but got true in isNotTrueExp.isAlwaysTrue()", + isNotTrueExp.isAlwaysTrue(), false); + assertEquals("expected true,but got false in isNotTrueExp.isAlwaysFalse()", + isNotTrueExp.isAlwaysFalse(), true); + + RexNode isNotTrueExp2 = isNotTrue(not(isNotNull(isNull(inputRef)))); + assertEquals("expected true,but got false in isNotTrueExp2.isAlwaysTrue()", + isNotTrueExp2.isAlwaysTrue(), true); + assertEquals("expected false,but got true in isNotTrueExp2.isAlwaysFalse()", + isNotTrueExp2.isAlwaysFalse(), false); + + } + private Comparable eval(RexNode e) { return RexInterpreter.evaluate(e, ImmutableMap.of()); }