@Override public final Expr compile(final QueryContext qc, final VarScope scp) throws QueryException { if (root != null) root = root.compile(qc, scp); // no steps if (steps.length == 0) return root == null ? new Context(info) : root; final Value init = qc.value, cv = initial(qc); final boolean doc = cv != null && cv.type == NodeType.DOC; qc.value = cv; try { final int sl = steps.length; for (int s = 0; s < sl; s++) { Expr e = steps[s]; // axis step: if input is a document, its type is temporarily generalized final boolean as = e instanceof Step; if (as && s == 0 && doc) cv.type = NodeType.NOD; e = e.compile(qc, scp); if (e.isEmpty()) return optPre(qc); steps[s] = e; // no axis step: invalidate context value if (!as) qc.value = null; } } finally { if (doc) cv.type = NodeType.DOC; qc.value = init; } // optimize path return optimize(qc, scp); }
@Override public final Expr optimize(final QueryContext qc, final VarScope scp) throws QueryException { final Value v = initial(qc); if (v != null && v.isEmpty() || emptyPath(v)) return optPre(qc); // merge descendant steps Expr e = mergeSteps(qc); if (e == this && v != null && v.type == NodeType.DOC) { // check index access e = index(qc, v); // rewrite descendant to child steps if (e == this) e = children(qc, v); } // recompile path if it has changed if (e != this) return e.compile(qc, scp); // set atomic type for single attribute steps to speed up predicate tests if (root == null && steps.length == 1 && steps[0] instanceof Step) { final Step curr = (Step) steps[0]; if (curr.axis == ATTR && curr.test.kind == Kind.URI_NAME) curr.seqType(SeqType.NOD_ZO); } // choose best path implementation and set type information final Path path = get(info, root, steps); path.size = path.size(qc); path.seqType = SeqType.get(steps[steps.length - 1].seqType().type, size); return path; }
@Override public final Expr compile(final QueryContext ctx, final VarScope scp) throws QueryException { if (root != null) setRoot(ctx, root.compile(ctx, scp)); final Value v = ctx.value; try { ctx.value = root(ctx); return compilePath(ctx, scp); } finally { ctx.value = v; } }
@Override public Expr compile(final QueryContext qc, final VarScope scp) throws QueryException { ts = ts.compile(qc, scp); // static condition: return branch in question if (ts.isValue()) { final Value val = ts.value(qc); for (final TypeCase tc : cases) { if (tc.matches(val)) return optPre(tc.compile(qc, scp, (Value) ts).expr, qc); } } // compile branches for (final TypeCase tc : cases) tc.compile(qc, scp); return optimize(qc, scp); }
@Override public FTWords compile(final QueryContext qc, final VarScope scp) throws QueryException { if (occ != null) { final int ol = occ.length; for (int o = 0; o < ol; ++o) occ[o] = occ[o].compile(qc, scp); } // compile only once if (tokens == null) { query = query.compile(qc, scp); if (query.isValue()) tokens = tokens(qc); // choose fast evaluation for default settings fast = mode == FTMode.ANY && tokens != null && occ == null; if (ftt == null) ftt = new FTTokenizer(this, qc); } return this; }
@Override public final Expr compile(final QueryContext ctx, final VarScope scp) throws QueryException { // invalidate current context value (will be overwritten by filter) final Value cv = ctx.value; try { root = root.compile(ctx, scp); // return empty root if (root.isEmpty()) return optPre(null, ctx); // convert filters without numeric predicates to axis paths if (root instanceof AxisPath && !super.has(Flag.FCS)) return ((AxisPath) root.copy(ctx, scp)).addPreds(ctx, scp, preds).compile(ctx, scp); // optimize filter expressions ctx.value = null; final Expr e = super.compile(ctx, scp); if (e != this) return e; // no predicates.. return root; otherwise, do some advanced compilations return preds.length == 0 ? root : opt(ctx); } finally { ctx.value = cv; } }
@Override public GroupBy compile(final QueryContext qc, final VarScope sc) throws QueryException { for (final Expr e : preExpr) e.compile(qc, sc); for (final Spec b : specs) b.compile(qc, sc); return optimize(qc, sc); }