@Override public Expr optimize(final QueryContext qc, final VarScope scp) throws QueryException { final Expr c = super.optimize(qc, scp); if (c != this) return c; final int es = exprs.length; final ExprList list = new ExprList(es); for (int i = 0; i < es; i++) { Expr e = exprs[i]; if (e instanceof CmpG) { // merge adjacent comparisons while (i + 1 < es && exprs[i + 1] instanceof CmpG) { final Expr tmp = ((CmpG) e).union((CmpG) exprs[i + 1], qc, scp); if (tmp != null) { e = tmp; i++; } else { break; } } } // expression will always return true if (e == Bln.TRUE) return optPre(Bln.TRUE, qc); // skip expression yielding false if (e != Bln.FALSE) list.add(e); } // all arguments return false if (list.isEmpty()) return optPre(Bln.FALSE, qc); if (es != list.size()) { qc.compInfo(OPTREWRITE_X, this); exprs = list.finish(); } compFlatten(qc); boolean not = true; for (final Expr expr : exprs) { if (!expr.isFunction(Function.NOT)) { not = false; break; } } if (not) { qc.compInfo(OPTREWRITE_X, this); final int el = exprs.length; final Expr[] inner = new Expr[el]; for (int e = 0; e < el; e++) inner[e] = ((Arr) exprs[e]).exprs[0]; final Expr ex = new And(info, inner).optimize(qc, scp); return Function.NOT.get(null, info, ex).optimize(qc, scp); } // return single expression if it yields a boolean return exprs.length == 1 ? compBln(exprs[0], info) : this; }
@Override public Expr optimize(final QueryContext qc, final VarScope scp) throws QueryException { super.optimize(qc, scp); final ExprList el = new ExprList(exprs.length); for (final Expr ex : exprs) { if (ex.isEmpty()) { // remove empty operands (return empty sequence if first value is empty) if (el.isEmpty()) return optPre(qc); qc.compInfo(OPTREMOVE_X_X, this, ex); } else { el.add(ex); } } // ensure that results are always sorted if (el.size() == 1 && iterable) return el.get(0); // replace expressions with optimized list exprs = el.finish(); return this; }