Exemplo n.º 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;
  }
Exemplo n.º 2
0
 @Override
 public Expr optimize(final QueryContext qc, final VarScope scp) throws QueryException {
   // number of predicates may change in loop
   for (int p = 0; p < preds.length; p++) {
     final Expr pred = preds[p];
     if (pred instanceof CmpG || pred instanceof CmpV) {
       final Cmp cmp = (Cmp) pred;
       if (cmp.exprs[0].isFunction(Function.POSITION)) {
         final Expr e2 = cmp.exprs[1];
         final SeqType st2 = e2.seqType();
         // position() = last() -> last()
         // position() = $n (numeric) -> $n
         if (e2.isFunction(Function.LAST) || st2.one() && st2.type.isNumber()) {
           if (cmp instanceof CmpG && ((CmpG) cmp).op == OpG.EQ
               || cmp instanceof CmpV && ((CmpV) cmp).op == OpV.EQ) {
             qc.compInfo(OPTWRITE, pred);
             preds[p] = e2;
           }
         }
       }
     } else if (pred instanceof And) {
       if (!pred.has(Flag.FCS)) {
         // replace AND expression with predicates (don't swap position tests)
         qc.compInfo(OPTPRED, pred);
         final Expr[] and = ((Arr) pred).exprs;
         final int m = and.length - 1;
         final ExprList el = new ExprList(preds.length + m);
         for (final Expr e : Arrays.asList(preds).subList(0, p)) el.add(e);
         for (final Expr a : and) {
           // wrap test with boolean() if the result is numeric
           el.add(Function.BOOLEAN.get(null, info, a).optimizeEbv(qc, scp));
         }
         for (final Expr e : Arrays.asList(preds).subList(p + 1, preds.length)) el.add(e);
         preds = el.finish();
       }
     } else if (pred instanceof ANum) {
       final ANum it = (ANum) pred;
       final long i = it.itr();
       if (i == it.dbl()) {
         preds[p] = Pos.get(i, info);
       } else {
         qc.compInfo(OPTREMOVE, this, pred);
         return Empty.SEQ;
       }
     } else if (pred.isValue()) {
       if (pred.ebv(qc, info).bool(info)) {
         qc.compInfo(OPTREMOVE, this, pred);
         preds = Array.delete(preds, p--);
       } else {
         // handle statically known predicates
         qc.compInfo(OPTREMOVE, this, pred);
         return Empty.SEQ;
       }
     }
   }
   return this;
 }
Exemplo n.º 3
0
  @Override
  public Expr compile(final QueryContext ctx) throws QueryException {
    for (int e = 0; e < expr.length; e++) expr[e] = expr[e].compile(ctx);

    // compute number of results
    size = 0;
    for (final Expr e : expr) {
      final long c = e.size();
      if (c == -1) {
        size = c;
        break;
      }
      size += c;
    }

    // evaluate sequence type
    type = SeqType.EMP;
    Value[] val = new Value[expr.length];
    for (int v = 0; v < expr.length; v++) {
      final Expr e = expr[v];
      // check if all expressions are values
      if (val != null) {
        if (e.isValue()) val[v] = (Value) e;
        else val = null;
      }
      // skip expression that will not add any results
      if (e.isEmpty()) continue;
      // evaluate sequence type
      final SeqType et = e.type();
      type =
          type == SeqType.EMP
              ? et
              : SeqType.get(
                  et.type == type.type ? et.type : AtomType.ITEM,
                  et.mayBeZero() && type.mayBeZero() ? Occ.ZERO_MORE : Occ.ONE_MORE);
    }

    // return cached integer sequence, cached values or self reference
    Expr e = this;
    final int s = (int) size;
    if (val != null && size <= Integer.MAX_VALUE) {
      if (type.type == AtomType.STR) e = StrSeq.get(val, s);
      else if (type.type == AtomType.BLN) e = BlnSeq.get(val, s);
      else if (type.type == AtomType.FLT) e = FltSeq.get(val, s);
      else if (type.type == AtomType.DBL) e = DblSeq.get(val, s);
      else if (type.type == AtomType.DEC) e = DecSeq.get(val, s);
      else if (type.type == AtomType.BYT) e = BytSeq.get(val, s);
      else if (type.type.instanceOf(AtomType.ITR)) e = IntSeq.get(val, s, type.type);
      else {
        final ValueBuilder vb = new ValueBuilder(s);
        for (final Value v : val) vb.add(v);
        e = vb.value();
      }
    }
    return optPre(e, ctx);
  }
Exemplo n.º 4
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;
 }
Exemplo n.º 5
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);
  }
Exemplo n.º 6
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;
 }
Exemplo n.º 7
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;
  }
Exemplo n.º 8
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;
  }
Exemplo n.º 9
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;
 }