Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions core/src/main/java/org/apache/calcite/rex/RexSimplify.java
Original file line number Diff line number Diff line change
Expand Up @@ -2139,6 +2139,25 @@ private <C extends Comparable<C>> RexNode simplifyAnd2ForUnknownAsFalse(
strongOperands.add(rexFieldAccess);
}
}
// Also probe sub-expressions coming from IS_NOT_NULL(...) predicates that
// are not bare input refs or field accesses (e.g. CAST calls); without
// this, IS_NOT_NULL(CAST(x)) AND (CAST(x) + 1) < 10 would not be absorbed
for (RexNode operand : notNullOperands) {
if (operand instanceof RexInputRef
|| operand instanceof RexFieldAccess
|| strongOperands.contains(operand)
|| !RexUtil.isDeterministic(operand)) {
continue;
}
final Strong strong = new Strong() {
@Override public boolean isNull(RexNode node) {
return node.equals(operand) || super.isNull(node);
}
};
if (strong.isNotTrue(term)) {
strongOperands.add(operand);
}
}
}
// If one column should be null and is in a comparison predicate,
// it is not satisfiable.
Expand Down
36 changes: 36 additions & 0 deletions core/src/test/java/org/apache/calcite/rex/RexProgramTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.SqlSpecialOperator;
import org.apache.calcite.sql.fun.SqlLibraryOperators;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.sql.type.OperandTypes;
import org.apache.calcite.sql.type.ReturnTypes;
Expand Down Expand Up @@ -3025,6 +3026,41 @@ trueLiteral, literal(1),
checkSimplifyUnchanged(div(cast(vVarchar(), tInt(false)), nullInt));
}

/**
* Test cases for <a href="https://issues.apache.org/jira/browse/CALCITE-7758">[CALCITE-7758]
* RexSimplify does not absorb redundant IS NOT NULL on non-input-ref sub-expressions
* in AND simplification</a>.
*/
@Test void testSimplifyIsNotNullAndStrongExpression() {
// "unsafe" cast: (CAST(a) + 1) < 10 AND IS_NOT_NULL(CAST(a)) ==> (CAST(a) + 1) < 10
checkSimplifyFilter(
and(
lt(plus(cast(vVarchar(), tDouble(true)), literal(1)), literal(10)),
isNotNull(cast(vVarchar(), tDouble(true)))),
"<(+(CAST(?0.varchar0):DOUBLE, 1), 10)");

// safe cast: (CAST(a) + 1) < 10 AND IS_NOT_NULL(CAST(a)) ==> (CAST(a) + 1) < 10
checkSimplifyFilter(
and(
lt(plus(cast(vInt(), tDouble(true)), literal(1)), literal(10)),
isNotNull(cast(vInt(), tDouble(true)))),
"<(+(CAST(?0.int0):DOUBLE, 1), 10)");

// op that can return NULL on non-NULL args:
// IS_NOT_NULL(REGEXP_SUBSTR(myField, '[xw]yz')) AND REGEXP_SUBSTR(myField, '[xw]yz') = 'xyz'
// ==> REGEXP_SUBSTR(myField, '[xw]yz') = 'xyz'
checkSimplifyFilter(
and(
isNotNull(
rexBuilder.makeCall(
SqlLibraryOperators.REGEXP_SUBSTR, vVarchar(), literal("[xw]yz"))),
eq(
rexBuilder.makeCall(
SqlLibraryOperators.REGEXP_SUBSTR, vVarchar(), literal("[xw]yz")),
literal("xyz"))),
"=(REGEXP_SUBSTR(?0.varchar0, '[xw]yz'), 'xyz')");
}

/**
* Test cases for <a href="https://issues.apache.org/jira/browse/CALCITE-7722">[CALCITE-7722]
* RexSimplify IS [NOT] NULL on a safe operator with Strong policy ANY and unsafe operands
Expand Down
Loading