* @param expr
* @param tableAlias
* @return
*/
public static boolean isNullRejectingExpression(AbstractExpression expr, String tableAlias) {
ExpressionType exprType = expr.getExpressionType();
if (exprType == ExpressionType.CONJUNCTION_AND) {
assert(expr.m_left != null && expr.m_right != null);
return isNullRejectingExpression(expr.m_left, tableAlias) || isNullRejectingExpression(expr.m_right, tableAlias);
} else if (exprType == ExpressionType.CONJUNCTION_OR) {
assert(expr.m_left != null && expr.m_right != null);
return isNullRejectingExpression(expr.m_left, tableAlias) && isNullRejectingExpression(expr.m_right, tableAlias);
} else if (exprType == ExpressionType.OPERATOR_NOT) {
assert(expr.m_left != null);
// "NOT ( P and Q )" is as null-rejecting as "NOT P or NOT Q"
// "NOT ( P or Q )" is as null-rejecting as "NOT P and NOT Q"
// Handling AND and OR expressions requires a "negated" flag to the recursion that tweaks
// (switches?) the handling of ANDs and ORs to enforce the above equivalences.
if (expr.m_left.getExpressionType() == ExpressionType.OPERATOR_IS_NULL) {
return containsMatchingTVE(expr, tableAlias);
} else if (expr.m_left.getExpressionType() == ExpressionType.CONJUNCTION_AND ||
expr.m_left.getExpressionType() == ExpressionType.CONJUNCTION_OR) {
assert(expr.m_left.m_left != null && expr.m_left.m_right != null);
// Need to test for an existing child NOT and skip it.
// e.g. NOT (P AND NOT Q) --> (NOT P) OR NOT NOT Q --> (NOT P) OR Q
AbstractExpression tempLeft = null;
if (expr.m_left.m_left.getExpressionType() != ExpressionType.OPERATOR_NOT) {
tempLeft = new OperatorExpression(ExpressionType.OPERATOR_NOT, expr.m_left.m_left, null);
} else {
assert(expr.m_left.m_left.m_left != null);
tempLeft = expr.m_left.m_left.m_left;
}
AbstractExpression tempRight = null;
if (expr.m_left.m_right.getExpressionType() != ExpressionType.OPERATOR_NOT) {
tempRight = new OperatorExpression(ExpressionType.OPERATOR_NOT, expr.m_left.m_right, null);
} else {
assert(expr.m_left.m_right.m_left != null);
tempRight = expr.m_left.m_right.m_left;
}
ExpressionType type = (expr.m_left.getExpressionType() == ExpressionType.CONJUNCTION_AND) ?
ExpressionType.CONJUNCTION_OR : ExpressionType.CONJUNCTION_AND;
AbstractExpression tempExpr = new OperatorExpression(type, tempLeft, tempRight);
return isNullRejectingExpression(tempExpr, tableAlias);
} else if (expr.m_left.getExpressionType() == ExpressionType.OPERATOR_NOT) {
// It's probably safe to assume that HSQL will have stripped out other double negatives,