@Override public Value value(final QueryContext ctx) throws QueryException { final int o = (int) ctx.resources.output.size(); final Updates updates = ctx.resources.updates(); final ContextModifier tmp = updates.mod; final TransformModifier pu = new TransformModifier(); updates.mod = pu; try { for (final Let fo : copies) { final Iter ir = ctx.iter(fo.expr); Item i = ir.next(); if (!(i instanceof ANode) || ir.next() != null) throw UPCOPYMULT.get(fo.info, fo.var.name); // copy node to main memory data instance i = ((ANode) i).dbCopy(ctx.context.options); // add resulting node to variable ctx.set(fo.var, i, info); pu.addData(i.data()); } final Value v = ctx.value(expr[0]); if (!v.isEmpty()) throw BASEX_MOD.get(info); updates.prepare(); updates.apply(); return ctx.value(expr[1]); } finally { ctx.resources.output.size(o); updates.mod = tmp; } }
/** * Checks if the predicates are successful for the specified item. * * @param it item to be checked * @param qc query context * @return result of check * @throws QueryException query exception */ protected final boolean preds(final Item it, final QueryContext qc) throws QueryException { if (preds.length == 0) return true; // set context value and position final Value cv = qc.value; try { if (qc.scoring) { double s = 0; for (final Expr p : preds) { qc.value = it; final Item i = p.test(qc, info); if (i == null) return false; s += i.score(); } it.score(Scoring.avg(s, preds.length)); } else { for (final Expr p : preds) { qc.value = it; if (p.test(qc, info) == null) return false; } } return true; } finally { qc.value = cv; } }
@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 Iter iter(final QueryContext ctx) throws QueryException { final Iter iter = ctx.iter(root); final Value cv = ctx.value; final long cs = ctx.size; final long cp = ctx.pos; // cache results to support last() function final ItemCache ic = new ItemCache(); for (Item i; (i = iter.next()) != null; ) ic.add(i); // evaluate predicates for (final Expr p : pred) { final long is = ic.size(); ctx.size = is; ctx.pos = 1; int c = 0; for (int s = 0; s < is; ++s) { ctx.value = ic.get(s); if (p.test(ctx, input) != null) ic.set(ic.get(s), c++); ctx.pos++; } ic.size(c); } ctx.value = cv; ctx.size = cs; ctx.pos = cp; return ic; }
@Override public final Expr inline(final QueryContext ctx, final VarScope scp, final Var v, final Expr e) throws QueryException { final Value oldVal = ctx.value; try { ctx.value = root(ctx); final Expr rt = root == null ? null : root.inline(ctx, scp, v, e); if (rt != null) { setRoot(ctx, rt); ctx.value = oldVal; ctx.value = root(ctx); } boolean change = rt != null; for (int i = 0; i < steps.length; i++) { final Expr nw = steps[i].inline(ctx, scp, v, e); if (nw != null) { steps[i] = nw; change = true; } } return change ? optimize(ctx, scp) : null; } finally { ctx.value = oldVal; } }
@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 { final Value init = qc.value; // never compile predicates with empty sequence as context value (#1016) if (init != null && init.isEmpty()) qc.value = null; try { final int pl = preds.length; for (int p = 0; p < pl; ++p) preds[p] = preds[p].compile(qc, scp).optimizeEbv(qc, scp); return this; } finally { qc.value = init; } }
@Override public NodeIter iter(final QueryContext ctx) throws QueryException { final Value v = checkCtx(ctx); if (!v.type.isNode()) NODESPATH.thrw(input, AxisStep.this, v.type); final AxisIter ai = axis.iter((ANode) v); final NodeCache nc = new NodeCache(); for (ANode n; (n = ai.next()) != null; ) if (test.eval(n)) nc.add(n.finish()); // evaluate predicates for (final Expr p : preds) { ctx.size = nc.size(); ctx.pos = 1; int c = 0; for (int n = 0; n < nc.size(); ++n) { ctx.value = nc.get(n); final Item i = p.test(ctx, input); if (i != null) { // assign score value nc.get(n).score(i.score()); nc.item[c++] = nc.get(n); } ctx.pos++; } nc.size(c); } return nc; }
@Override Value[] evalArgs(final QueryContext ctx) throws QueryException { final int al = expr.length - 1; final Value[] args = new Value[al]; for (int a = 0; a < al; ++a) args[a] = ctx.value(expr[a]); return args; }
@Override public final Value value(final QueryContext qc) throws QueryException { final int es = exprs.length; final Value[] args = new Value[es]; for (int e = 0; e < es; ++e) args[e] = qc.value(exprs[e]); return toValue(eval(args, qc), qc, sc); }
@Override public Item item(final QueryContext ctx, final InputInfo ii) throws QueryException { Map map = Map.EMPTY; for (int i = 0; i < expr.length; i++) { map = map.insert(checkItem(expr[i], ctx), ctx.value(expr[++i]), ii); } return map; }
@Override public final Expr comp(final QueryContext ctx) throws QueryException { root = checkUp(root, ctx).comp(ctx); // return empty root if (root.empty()) return optPre(null, ctx); // convert filters without position predicates to axis paths if (root instanceof AxisPath && !super.uses(Use.POS)) return ((AxisPath) root).copy().addPreds(pred).comp(ctx); final Value cv = ctx.value; ctx.value = null; final Expr e = super.comp(ctx); ctx.value = cv; if (e != this) return e; // no predicates.. return root; otherwise, do some advanced compilations return pred.length == 0 ? root : comp2(ctx); }
@Override public Iter iter(final QueryContext ctx) throws QueryException { final Value seq = ctx.value(ts); for (final TypeCase c : cases) { final Iter iter = c.iter(ctx, seq); if (iter != null) return iter; } // will never happen throw Util.notexpected(); }
@Override public Value value(final QueryContext ctx) throws QueryException { checkHeight(ctx); // cache arguments, evaluate function and reset variable scope final VarStack cs = addArgs(ctx, args(ctx)); final Value v = ctx.value(func); ctx.vars.reset(cs); return v; }
@Override public Iter iter(final QueryContext qc) throws QueryException { final Value seq = qc.value(ts); for (final TypeCase tc : cases) { final Iter iter = tc.iter(qc, seq); if (iter != null) return iter; } // will never happen throw Util.notExpected(); }
@Override public Value value(final QueryContext qc) throws QueryException { // don't catch errors from error handlers try { return qc.value(expr); } catch (final QueryException ex) { if (!ex.isCatchable()) throw ex; for (final Catch c : catches) if (c.matches(ex)) return c.value(qc, ex); throw ex; } }
/** * Checks if the predicates are successful for the specified item. * * @param it item to be checked * @param ctx query context * @return result of check * @throws QueryException query exception */ public boolean preds(final Item it, final QueryContext ctx) throws QueryException { // set context item and position ctx.value = it; for (final Expr p : pred) { final Item i = p.test(ctx, input); if (i == null) return false; // item accepted.. adopt last scoring value it.score(i.score()); } return true; }
@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 Iter iter(final QueryContext ctx) throws QueryException { final Value cv = ctx.value; final long cs = ctx.size; final long cp = ctx.pos; try { Value r = root != null ? ctx.value(root) : cv; if (!cache || citer == null || lvalue.type != NodeType.DOC || r.type != NodeType.DOC || !((ANode) lvalue).is((ANode) r)) { lvalue = r; citer = new NodeCache().random(); if (r != null) { final Iter ir = ctx.iter(r); while ((r = ir.next()) != null) { ctx.value = r; iter(0, citer, ctx); } } else { ctx.value = null; iter(0, citer, ctx); } citer.sort(); } else { citer.reset(); } return citer; } finally { ctx.value = cv; ctx.size = cs; ctx.pos = cp; } }
/** * Recursive step iterator. * * @param l current step * @param nc node cache * @param ctx query context * @throws QueryException query exception */ private void iter(final int l, final NodeCache nc, final QueryContext ctx) throws QueryException { // cast is safe (steps will always return a {@link NodIter} instance final NodeIter ni = (NodeIter) ctx.iter(steps[l]); final boolean more = l + 1 != steps.length; for (ANode node; (node = ni.next()) != null; ) { if (more) { ctx.value = node; iter(l + 1, nc, ctx); } else { ctx.checkStop(); nc.add(node); } } }
@Override protected final Expr compPath(final QueryContext ctx) throws QueryException { for (final Expr s : steps) checkUp(s, ctx); // merge two axis paths if (root instanceof AxisPath) { Expr[] st = ((AxisPath) root).steps; root = ((AxisPath) root).root; for (final Expr s : steps) st = Array.add(st, s); steps = st; // refresh root context ctx.compInfo(OPTMERGE); ctx.value = root(ctx); } final AxisStep s = voidStep(steps); if (s != null) COMPSELF.thrw(input, s); for (int i = 0; i != steps.length; ++i) { final Expr e = steps[i].comp(ctx); if (!(e instanceof AxisStep)) return e; steps[i] = e; } optSteps(ctx); // retrieve data reference final Data data = ctx.data(); if (data != null && ctx.value.type == NodeType.DOC) { // check index access Expr e = index(ctx, data); // check children path rewriting if (e == this) e = children(ctx, data); // return optimized expression if (e != this) return e.comp(ctx); } // analyze if result set can be cached - no predicates/variables... cache = root != null && !uses(Use.VAR); // if applicable, use iterative evaluation final Path path = finish(ctx); // heuristics: wrap with filter expression if only one result is expected return size() != 1 ? path : new Filter(input, this, Pos.get(1, size(), input)).comp2(ctx); }
/** * Sends an event to the registered sessions. * * @param ctx query context * @return event result * @throws QueryException query exception */ private Item event(final QueryContext ctx) throws QueryException { final byte[] name = checkStr(expr[0], ctx); final ArrayOutput ao = new ArrayOutput(); try { // run serialization final Serializer ser = Serializer.get(ao, ctx.serProp(true)); final ValueIter ir = ctx.value(expr[1]).iter(); for (Item it; (it = ir.next()) != null; ) it.serialize(ser); ser.close(); } catch (final SerializerException ex) { throw ex.getCause(input); } catch (final IOException ex) { SERANY.thrw(input, ex); } // throw exception if event is unknown if (!ctx.context.events.notify(ctx.context, name, ao.toArray())) { NOEVENT.thrw(input, name); } return null; }
@Override public Value value(final QueryContext ctx) throws QueryException { final Value val = ctx.value(expr); final long len = val.size(); if (len == 0) { if (type.mayBeZero()) return val; throw XPEMPTY.thrw(input, desc()); } if (type.zeroOrOne()) { if (len > 1) throw NOTREATS.thrw(input, desc(), type); final Item it = val.itemAt(0); if (!it.type.instance(type.type)) NOTREAT.thrw(input, desc(), type, it.type); return it; } for (long i = 0; i < len; i++) { final Item it = val.itemAt(i); if (!it.type.instance(type.type)) NOTREAT.thrw(input, desc(), type, it.type); } return val; }
@Override public Value value(final QueryContext ctx) throws QueryException { final ValueBuilder vb = new ValueBuilder(); for (final Expr e : expr) vb.add(ctx.value(e)); return vb.value(); }
@Override public Value value(final QueryContext qc) throws QueryException { final Value val = qc.value(exprs[0]); if (val.isEmpty()) throw ONEORMORE.get(info); return val; }