Esempio n. 1
0
  /**
   * 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;
    }
  }
Esempio 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;
 }
Esempio n. 3
0
  @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;
  }
Esempio n. 4
0
 @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;
   }
 }
Esempio n. 5
0
 @Override
 public Value value(final QueryContext qc) throws QueryException {
   if (seqType().zeroOrOne()) {
     final Value v = item(qc, info);
     return v == null ? Empty.SEQ : v;
   }
   return qc.iter(this).value();
 }
Esempio n. 6
0
 @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;
   }
 }
Esempio n. 7
0
 @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;
 }
Esempio n. 8
0
 /**
  * Adds an optimization info for pre-evaluating the specified expression.
  *
  * @param ex optimized expression
  * @param qc query context
  * @return optimized expression
  */
 protected final Expr optPre(final Expr ex, final QueryContext qc) {
   if (ex != this) qc.compInfo(OPTPRE_X, this);
   return ex == null ? Empty.SEQ : ex;
 }
Esempio n. 9
0
  /**
   * Evaluates the specified function and creates a response.
   *
   * @throws Exception exception (including unexpected ones)
   */
  void create() throws Exception {
    // bind variables
    final StaticFunc sf = function.function;
    final Expr[] args = new Expr[sf.args.length];
    function.bind(http, args, error);

    // wrap function with a function call
    final MainModule mm = new MainModule(sf, args);

    // assign main module and http context and register process
    query.mainModule(mm);
    query.http(http);
    query.context.register(query);

    String redirect = null, forward = null;
    RestXqRespBuilder resp = null;
    try {
      // compile and evaluate query
      query.compile();
      final Iter iter = query.iter();
      Item item = iter.next();

      // handle response element
      if (item != null && item instanceof ANode) {
        final ANode node = (ANode) item;
        // send redirect to browser
        if (REST_REDIRECT.eq(node)) {
          final ANode ch = node.children().next();
          if (ch == null || ch.type != NodeType.TXT) throw function.error(NO_VALUE, node.name());
          redirect = string(ch.string()).trim();
          return;
        }
        // server-side forwarding
        if (REST_FORWARD.eq(node)) {
          final ANode ch = node.children().next();
          if (ch == null || ch.type != NodeType.TXT) throw function.error(NO_VALUE, node.name());
          forward = string(ch.string()).trim();
          return;
        }
        if (REST_RESPONSE.eq(node)) {
          resp = new RestXqRespBuilder();
          resp.build(node, function, iter, http);
          return;
        }
      }

      // HEAD method must return a single response element
      if (function.methods.size() == 1 && function.methods.contains(HTTPMethod.HEAD.name()))
        throw function.error(HEAD_METHOD);

      // serialize result
      final SerializerOptions sp = function.output;
      http.sopts(sp);
      http.initResponse();
      final Serializer ser = Serializer.get(http.res.getOutputStream(), sp);
      for (; item != null; item = iter.next()) ser.serialize(item);
      ser.close();

    } finally {
      query.close();
      query.context.unregister(query);

      if (redirect != null) {
        http.res.sendRedirect(redirect);
      } else if (forward != null) {
        http.req.getRequestDispatcher(forward).forward(http.req, http.res);
      } else if (resp != null) {
        if (resp.status != 0) http.status(resp.status, resp.message, resp.error);
        http.res.getOutputStream().write(resp.cache.toArray());
      }
    }
  }