예제 #1
0
 @Override
 public VarUsage count(final Var v) {
   final VarUsage inPreds = super.count(v), inRoot = root.count(v);
   if (inPreds == VarUsage.NEVER) return inRoot;
   final long sz = root.size();
   return sz >= 0 && sz <= 1 || root.type().zeroOrOne()
       ? inRoot.plus(inPreds)
       : VarUsage.MORE_THAN_ONCE;
 }
예제 #2
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;
  }
예제 #3
0
  @Override
  public Expr optimize(final QueryContext ctx, final VarScope scp) throws QueryException {
    final int ar = expr.length - 1;
    final Expr f = expr[ar];
    final Type t = f.type().type;
    if (t instanceof FuncType) {
      final FuncType ft = (FuncType) t;
      if (ft.args != null && ft.args.length != ar) throw INVARITY.get(info, f, ar);
      if (ft.ret != null) type = ft.ret;
    }

    if (f instanceof XQFunctionExpr) {
      // maps can only contain fully evaluated Values, so this is safe
      if (allAreValues() && f instanceof Map) return optPre(value(ctx), ctx);

      // try to inline the function
      if (!(f instanceof FuncItem && comesFrom((FuncItem) f)) && !updating) {
        final Expr[] args = Arrays.copyOf(expr, expr.length - 1);
        final Expr inl = ((XQFunctionExpr) f).inlineExpr(args, ctx, scp, info);
        if (inl != null) return inl;
      }
    }
    return this;
  }