private SqlExpr other(SqlExpr node, SqlExpr compare, Class<? extends BinarySqlOperator> type) { if (type.isInstance(node)) { BinarySqlOperator cast = type.cast(node); SqlExpr left = cast.getLeftArg(); SqlExpr right = cast.getRightArg(); if (left.equals(compare)) return right; if (right.equals(compare)) return left; } return null; }
@Override public void meet(SqlIsNull node) throws RuntimeException { super.meet(node); SqlExpr arg = node.getArg(); if (arg instanceof SqlNull) { replace(node, new TrueValue()); } else if (arg instanceof SqlConstant<?>) { replace(node, new FalseValue()); } else if (arg instanceof SqlCase) { SqlExpr rep = null; SqlExpr prev = null; SqlCase scase = (SqlCase) arg; for (Entry entry : scase.getEntries()) { SqlExpr condition = entry.getCondition(); if (rep == null) { rep = and(condition.clone(), isNull(entry.getResult().clone())); prev = not(condition.clone()); } else { rep = or(rep, and(and(prev.clone(), condition.clone()), isNull(entry.getResult().clone()))); prev = and(prev, not(condition.clone())); } } replace(node, or(rep, prev.clone())); } }
@Override public void meet(SqlAnd node) throws RuntimeException { super.meet(node); SqlExpr left = node.getLeftArg(); SqlExpr right = node.getRightArg(); if (left instanceof FalseValue || right instanceof FalseValue) { replace(node, new FalseValue()); } else if (left instanceof TrueValue && right instanceof TrueValue) { replace(node, new TrueValue()); } else if (left instanceof TrueValue) { replace(node, right.clone()); } else if (right instanceof TrueValue) { replace(node, left.clone()); } else if (right instanceof SqlNull || left instanceof SqlNull) { replace(node, new SqlNull()); } else if (right instanceof SqlNot && ((SqlNot) right).getArg().equals(left)) { replace(node, new FalseValue()); } else if (left instanceof SqlNot && ((SqlNot) left).getArg().equals(right)) { replace(node, new FalseValue()); } }
@Override public void meet(SqlOr node) throws RuntimeException { super.meet(node); SqlExpr left = node.getLeftArg(); SqlExpr right = node.getRightArg(); if (left instanceof TrueValue || right instanceof TrueValue) { replace(node, new TrueValue()); } else if (left instanceof FalseValue && right instanceof FalseValue) { replace(node, new FalseValue()); } else if (left instanceof FalseValue) { replace(node, right.clone()); } else if (right instanceof FalseValue) { replace(node, left.clone()); } else if (right instanceof SqlNull && andAllTheWay(node)) { replace(node, left.clone()); } else if (left instanceof SqlNull && andAllTheWay(node)) { replace(node, right.clone()); } else if (right instanceof SqlNull && left instanceof SqlNull) { replace(node, new SqlNull()); } else if (left instanceof SqlNull && right instanceof SqlOr) { SqlOr r = (SqlOr) right; SqlExpr rleft = r.getLeftArg(); SqlExpr rright = r.getRightArg(); if (rleft instanceof SqlNull || rright instanceof SqlNull) { replace(node, right.clone()); } } else if (right instanceof SqlNull && left instanceof SqlOr) { SqlOr l = (SqlOr) left; SqlExpr lleft = l.getLeftArg(); SqlExpr lright = l.getRightArg(); if (lleft instanceof SqlNull || lright instanceof SqlNull) { replace(node, left.clone()); } } else if (right instanceof SqlNull && left instanceof SqlAnd) { // value IS NOT NULL AND value = ? OR NULL // -> value = ? SqlAnd l = (SqlAnd) left; SqlExpr lleft = l.getLeftArg(); SqlExpr lright = l.getRightArg(); SqlExpr isNotNull = arg(arg(lleft, SqlNot.class), SqlIsNull.class); SqlExpr isNotEq = other(lright, isNotNull, SqlEq.class); if (isNotEq instanceof SqlConstant) { replace(node, lright); } } }
private void replace(SqlExpr before, SqlExpr after) { before.replaceWith(after); after.visit(this); }
public void optimize(SqlExpr sqlExpr) { sqlExpr.visit(this); }