Beispiel #1
0
  @Override
  public Expr inline(final QueryContext qc, final VarScope scp, final Var var, final Expr ex)
      throws QueryException {

    boolean change = false;
    try {
      final Expr sub = expr.inline(qc, scp, var, ex);
      if (sub != null) {
        if (sub.isValue()) return optPre(sub, qc);
        expr = sub;
        change = true;
      }
    } catch (final QueryException qe) {
      if (!qe.isCatchable()) throw qe;
      for (final Catch c : catches) {
        if (c.matches(qe)) {
          // found a matching clause, inline variable and error message
          final Catch nw = c.inline(qc, scp, var, ex);
          return optPre((nw == null ? c : nw).asExpr(qe, qc, scp), qc);
        }
      }
      throw qe;
    }

    for (final Catch c : catches) change |= c.inline(qc, scp, var, ex) != null;
    return change ? this : null;
  }
Beispiel #2
0
 /**
  * Returns the root of the current context or {@code null}.
  *
  * @param ctx query context
  * @return root
  */
 final Value root(final QueryContext ctx) {
   final Value v = ctx != null ? ctx.value : null;
   // no root specified: return context, if it does not reference a document
   // as e.g. happens in //a(b|c)
   if (root == null) return v == null || v.type != NodeType.DOC ? v : null;
   // root is value: return root
   if (root.isValue()) return (Value) root;
   // no root reference, no context: return null
   if (!(root instanceof Root) || v == null) return null;
   // return context sequence or root of current context
   return v.size() == 1 ? Root.root(v) : v;
 }
Beispiel #3
0
  @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);
  }
Beispiel #4
0
 /**
  * Returns the initial context value of a path or {@code null}.
  *
  * @param qc query context (may be @code null)
  * @return root
  */
 private Value initial(final QueryContext qc) {
   // current context value
   final Value v = qc != null ? qc.value : null;
   // no root or context expression: return context
   if (root == null || root instanceof Context) return v;
   // root reference
   if (root instanceof Root) return v != null && v instanceof Item ? Root.root(v) : v;
   // root is value: return root
   if (root.isValue()) return (Value) root;
   // data reference
   final Data d = root.data();
   if (d != null) return new DBNode(d, 0, Data.ELEM);
   // otherwise, return null
   return null;
 }
Beispiel #5
0
  @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;
  }
Beispiel #6
0
  /**
   * Compiles the filter expression, excluding the root node.
   *
   * @param ctx query context
   * @return compiled expression
   */
  private Expr opt(final QueryContext ctx) {
    // evaluate return type
    final SeqType t = root.type();

    // determine number of results and type
    final long s = root.size();
    if (s != -1) {
      if (pos != null) {
        size = Math.max(0, s + 1 - pos.min) - Math.max(0, s - pos.max);
      } else if (last) {
        size = s > 0 ? 1 : 0;
      }
      // no results will remain: return empty sequence
      if (size == 0) return optPre(null, ctx);
      type = SeqType.get(t.type, size);
    } else {
      type = SeqType.get(t.type, t.zeroOrOne() ? Occ.ZERO_ONE : Occ.ZERO_MORE);
    }

    // no numeric predicates.. use simple iterator
    if (!super.has(Flag.FCS)) return new IterFilter(this);

    // one single position() or last() function specified: return single value
    if (preds.length == 1
        && (last || pos != null)
        && root.isValue()
        && t.one()
        && (last || pos.min == 1 && pos.max == 1)) return optPre(root, ctx);

    // only choose deterministic and context-independent offsets; e.g., skip:
    // (1 to 10)[random:integer(10)]  or  (1 to 10)[.]
    boolean off = false;
    if (preds.length == 1) {
      final Expr p = preds[0];
      final SeqType st = p.type();
      off = st.type.isNumber() && st.zeroOrOne() && !p.has(Flag.CTX) && !p.has(Flag.NDT);
      if (off) type = SeqType.get(type.type, Occ.ZERO_ONE);
    }

    // iterator for simple numeric predicate
    return off || useIterator() ? new IterPosFilter(this, off) : this;
  }
Beispiel #7
0
 /**
  * Returns true if all arguments are values.
  *
  * @return result of check
  */
 protected final boolean allAreValues() {
   for (final Expr e : exprs) if (!e.isValue()) return false;
   return true;
 }