/** * Create an unanalyzed predicate that checks if elements >= i are equal or both sides are null. * * <p>The predicate has the form ((lhs[i] is null && rhs[i] is null) || ( lhs[i] is not null && * rhs[i] is not null && lhs[i] = rhs[i])) && <createEqualsAux(i + 1)> */ private Expr createNullMatchingEqualsAux( List<Expr> elements, int i, TupleId inputTid, ExprSubstitutionMap bufferedSmap) { if (i > elements.size() - 1) return new BoolLiteral(true); // compare elements[i] Expr lhs = elements.get(i); Preconditions.checkState(lhs.isBound(inputTid)); Expr rhs = lhs.substitute(bufferedSmap, analyzer_, false); Expr bothNull = new CompoundPredicate( Operator.AND, new IsNullPredicate(lhs, false), new IsNullPredicate(rhs, false)); Expr lhsEqRhsNotNull = new CompoundPredicate( Operator.AND, new CompoundPredicate( Operator.AND, new IsNullPredicate(lhs, true), new IsNullPredicate(rhs, true)), new BinaryPredicate(BinaryPredicate.Operator.EQ, lhs, rhs)); Expr remainder = createNullMatchingEqualsAux(elements, i + 1, inputTid, bufferedSmap); return new CompoundPredicate( CompoundPredicate.Operator.AND, new CompoundPredicate(Operator.OR, bothNull, lhsEqRhsNotNull), remainder); }