static void equate(Generator gen, Expression expr, QFrame left, QFrame right) { Expression lexpr = left.getExpression(); Expression rexpr = right.getExpression(); List lvals = left.getValues(); List rvals = right.getValues(); List lnull = gen.getNull(lexpr); List rnull = gen.getNull(rexpr); if (lvals.size() != rvals.size()) { if (lvals.size() == 1 && lnull.containsAll(lvals)) { lvals = repeat(lvals.get(0), rvals.size()); } else if (rvals.size() == 1 && rnull.containsAll(rvals)) { rvals = repeat(rvals.get(0), lvals.size()); } else { throw new IllegalStateException( "cardinality mismatch\nlvals: " + lvals + "\nrvals: " + rvals + "\nleft: " + lexpr + "\nright: " + rexpr); } } List lnonnull = gen.getNonNull(lexpr); List rnonnull = gen.getNonNull(rexpr); for (int i = 0; i < lvals.size(); i++) { QValue lval = (QValue) lvals.get(i); QValue rval = (QValue) rvals.get(i); gen.addEquality(expr, lval, rval); if (lnull.contains(lval)) { gen.addNull(expr, rval); } if (lnonnull.contains(lval)) { gen.addNonNull(expr, rval); } if (rnull.contains(rval)) { gen.addNull(expr, lval); } if (rnonnull.contains(rval)) { gen.addNonNull(expr, lval); } } gen.addSufficient(expr); }
static Code emit(Generator gen, Expression lexpr, Expression rexpr) { if (gen.hasFrame(lexpr) && gen.hasFrame(rexpr)) { QFrame lframe = gen.getFrame(lexpr); QFrame rframe = gen.getFrame(rexpr); if (!lframe.isSelect() && !rframe.isSelect()) { List lvals = lframe.getValues(); List rvals = rframe.getValues(); List lnull = gen.getNull(lexpr); List rnull = gen.getNull(rexpr); if (lvals.size() != rvals.size()) { if (lvals.size() == 1 && lnull.containsAll(lvals)) { lvals = repeat(lvals.get(0), rvals.size()); } else if (rvals.size() == 1 && rnull.containsAll(rvals)) { rvals = repeat(rvals.get(0), lvals.size()); } else { throw new IllegalStateException("signature missmatch: " + lvals + ", " + rvals); } } List conds = new ArrayList(); for (int i = 0; i < lvals.size(); i++) { QValue l = (QValue) lvals.get(i); QValue r = (QValue) rvals.get(i); Code lsql = l.emit(); Code rsql = r.emit(); if (lsql.isNull()) { if (!r.isNullable()) { return Code.FALSE; } } else if (rsql.isNull()) { if (!l.isNullable()) { return Code.FALSE; } } if (!lsql.equals(rsql)) { conds.add(emit(lsql, null, rsql, null)); } } if (conds.isEmpty()) { return Code.TRUE; } else { return Code.join(conds, " and "); } } } // XXX: we can to do something smarter than this for // multi column selects Code lsql = lexpr.emit(gen); Code rsql = rexpr.emit(gen); // we need the isEmpty test because we don't want to eliminate // redundent bind var comparison the first time a query is // cached since the sql may not be redundent for subsequent // query executions if (lsql.getBindings().isEmpty() && lsql.equals(rsql)) { return Code.TRUE; } else { return emit(lsql, lexpr, rsql, rexpr); } }