Beispiel #1
0
  @Override
  public final Expr optimize(final QueryContext qc, final VarScope scp) throws QueryException {
    final Value v = initial(qc);
    if (v != null && v.isEmpty() || emptyPath(v)) return optPre(qc);

    // merge descendant steps
    Expr e = mergeSteps(qc);
    if (e == this && v != null && v.type == NodeType.DOC) {
      // check index access
      e = index(qc, v);
      // rewrite descendant to child steps
      if (e == this) e = children(qc, v);
    }
    // recompile path if it has changed
    if (e != this) return e.compile(qc, scp);

    // set atomic type for single attribute steps to speed up predicate tests
    if (root == null && steps.length == 1 && steps[0] instanceof Step) {
      final Step curr = (Step) steps[0];
      if (curr.axis == ATTR && curr.test.kind == Kind.URI_NAME) curr.seqType(SeqType.NOD_ZO);
    }

    // choose best path implementation and set type information
    final Path path = get(info, root, steps);
    path.size = path.size(qc);
    path.seqType = SeqType.get(steps[steps.length - 1].seqType().type, size);
    return path;
  }
Beispiel #2
0
  @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);
  }
Beispiel #3
0
 @Override
 public int exprSize() {
   int sz = 1;
   for (final Let lt : copies) sz += lt.exprSize();
   for (final Expr e : expr) sz += e.exprSize();
   return sz;
 }
Beispiel #4
0
  @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;
  }
Beispiel #5
0
 @Override
 public final boolean has(final Flag flag) {
   // first step or root expression will be used as context
   if (flag == Flag.CTX) return root == null || root.has(flag);
   for (final Expr s : steps) if (s.has(flag)) return true;
   return root != null && root.has(flag);
 }
Beispiel #6
0
 @Override
 public boolean accept(final ASTVisitor visitor) {
   if (!visitAll(visitor, specs)) return false;
   for (final Expr ng : preExpr) if (!ng.accept(visitor)) return false;
   for (final Var ng : post) if (!visitor.declared(ng)) return false;
   return true;
 }
Beispiel #7
0
 @Override
 public int exprSize() {
   int sz = 1;
   if (occ != null) for (final Expr o : occ) sz += o.exprSize();
   for (final Expr e : exprs) sz += e.exprSize();
   return sz + query.exprSize();
 }
Beispiel #8
0
 @Override
 public int exprSize() {
   int sz = 0;
   for (final Expr e : preExpr) sz += e.exprSize();
   for (final Expr e : specs) sz += e.exprSize();
   return sz;
 }
Beispiel #9
0
 @Override
 public void checkUp() throws QueryException {
   for (final Let c : copies) c.checkUp();
   final Expr m = expr[0];
   m.checkUp();
   if (!m.isVacuous() && !m.has(Flag.UPD)) throw UPMODIFY.get(info);
   checkNoUp(expr[1]);
 }
Beispiel #10
0
 @Override
 protected Expr opt(final QueryContext qc, final VarScope scp) {
   final Expr e = exprs[0];
   final SeqType st = e.seqType();
   if (!st.mayBeZero()) return e;
   seqType = SeqType.get(st.type, seqType.occ);
   return this;
 }
Beispiel #11
0
  @Override
  public Expr optimize(final QueryContext ctx, final VarScope scp) throws QueryException {
    if (root instanceof Context) {
      ctx.compInfo(OPTREMCTX);
      root = null;
    }

    for (final Expr e : steps) {
      // check for empty steps
      if (e.isEmpty()) return optPre(null, ctx);
    }

    return this;
  }
Beispiel #12
0
  @Override
  public Item item(final QueryContext qc, final InputInfo ii) throws QueryException {
    final QNm name = toQNm(exprs[0], qc, sc, false);
    final long arity = toLong(exprs[1], qc);
    if (arity < 0 || arity > Integer.MAX_VALUE) throw FUNCUNKNOWN_X.get(ii, name);

    try {
      final Expr lit = Functions.getLiteral(name, (int) arity, qc, sc, ii);
      return lit == null ? null : lit.item(qc, ii);
    } catch (final QueryException e) {
      // function not found (in most cases: XPST0017)
      return null;
    }
  }
Beispiel #13
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 #14
0
  @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;
    }
  }
Beispiel #15
0
 @Override
 public void plan(final Serializer ser) throws IOException {
   ser.openElement(this);
   weight.plan(ser);
   expr[0].plan(ser);
   ser.closeElement();
 }
Beispiel #16
0
  /**
   * Checks if the path can be rewritten for iterative evaluation.
   *
   * @param root root expression; can be a {@code null} reference
   * @param steps path steps
   * @return result of check
   */
  private static boolean iterative(final Expr root, final Expr... steps) {
    if (root == null || !root.iterable()) return false;

    final int sl = steps.length;
    for (int s = 0; s < sl; ++s) {
      switch (((Step) steps[s]).axis) {
          // reverse axes - don't iterate
        case ANC:
        case ANCORSELF:
        case PREC:
        case PRECSIBL:
          return false;
          // multiple, unsorted results - only iterate at last step,
          // or if last step uses attribute axis
        case DESC:
        case DESCORSELF:
        case FOLL:
        case FOLLSIBL:
          return s + 1 == sl || s + 2 == sl && ((Step) steps[s + 1]).axis == Axis.ATTR;
          // allow iteration for CHILD, ATTR, PARENT and SELF axes
        default:
      }
    }
    return true;
  }
Beispiel #17
0
  /**
   * Merges expensive descendant-or-self::node() steps.
   *
   * @param qc query context
   * @return original or new expression
   */
  private Expr mergeSteps(final QueryContext qc) {
    boolean opt = false;
    final int sl = steps.length;
    final ExprList stps = new ExprList(sl);
    for (int s = 0; s < sl; s++) {
      final Expr step = steps[s];
      // check for simple descendants-or-self step with succeeding step
      if (s < sl - 1 && step instanceof Step) {
        final Step curr = (Step) step;
        if (curr.simple(DESCORSELF, false)) {
          // check succeeding step
          final Expr next = steps[s + 1];
          // descendant-or-self::node()/child::X -> descendant::X
          if (simpleChild(next)) {
            ((Step) next).axis = DESC;
            opt = true;
            continue;
          }
          // descendant-or-self::node()/(X, Y) -> (descendant::X | descendant::Y)
          Expr e = mergeList(next);
          if (e != null) {
            steps[s + 1] = e;
            opt = true;
            continue;
          }
          // //(X, Y)[text()] -> (/descendant::X | /descendant::Y)[text()]
          if (next instanceof Filter && !next.has(Flag.FCS)) {
            final Filter f = (Filter) next;
            e = mergeList(f.root);
            if (e != null) {
              f.root = e;
              opt = true;
              continue;
            }
          }
        }
      }
      stps.add(step);
    }

    if (opt) {
      qc.compInfo(OPTDESC);
      return get(info, root, stps.finish());
    }
    return this;
  }
Beispiel #18
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 #19
0
  @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);
  }
Beispiel #20
0
  @Override
  public FTExpr inline(final QueryContext qc, final VarScope scp, final Var var, final Expr ex)
      throws QueryException {

    boolean change = occ != null && inlineAll(qc, scp, occ, var, ex);
    final Expr q = query.inline(qc, scp, var, ex);
    if (q != null) {
      query = q;
      change = true;
    }
    return change ? optimize(qc, scp) : null;
  }
Beispiel #21
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 #22
0
  @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;
    }
  }
Beispiel #23
0
 @Override
 public boolean accept(final ASTVisitor visitor) {
   if (root == null) {
     if (!visitor.lock(DBLocking.CTX)) return false;
   } else if (!root.accept(visitor)) {
     return false;
   }
   visitor.enterFocus();
   if (!visitAll(visitor, steps)) return false;
   visitor.exitFocus();
   return true;
 }
Beispiel #24
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;
  }
Beispiel #25
0
 @Override
 public Data data() {
   if (root != null) {
     // data reference
     final Data data = root.data();
     if (data != null) {
       final int sl = steps.length;
       for (int s = 0; s < sl; s++) {
         if (axisStep(s) == null) return null;
       }
       return data;
     }
   }
   return null;
 }
Beispiel #26
0
 @Override
 public FTExpr copy(final QueryContext qc, final VarScope scp, final IntObjMap<Var> vs) {
   final FTWords ftw =
       new FTWords(
           info,
           query.copy(qc, scp, vs),
           mode,
           occ == null ? null : Arr.copyAll(qc, scp, vs, occ));
   if (ftt != null) ftw.ftt = ftt.copy(ftw);
   ftw.tokens = tokens;
   ftw.data = data;
   ftw.first = first;
   ftw.pos = pos;
   ftw.fast = fast;
   return ftw;
 }
Beispiel #27
0
  @Override
  public final Expr inline(final QueryContext qc, final VarScope scp, final Var var, final Expr ex)
      throws QueryException {

    boolean changed = false;
    if (root != null) {
      final Expr rt = root.inline(qc, scp, var, ex);
      if (rt != null) {
        root = rt;
        changed = true;
      }
    }

    final int sl = steps.length;
    for (int s = 0; s < sl; s++) {
      final Expr nw = steps[s].inline(qc, scp, var, ex);
      if (nw != null) {
        steps[s] = nw;
        changed = true;
      }
    }
    return changed ? optimize(qc, scp) : null;
  }
Beispiel #28
0
 @Override
 public GroupBy compile(final QueryContext qc, final VarScope sc) throws QueryException {
   for (final Expr e : preExpr) e.compile(qc, sc);
   for (final Spec b : specs) b.compile(qc, sc);
   return optimize(qc, sc);
 }
Beispiel #29
0
 @Override
 public final int exprSize() {
   int sz = 1;
   for (final Expr e : steps) sz += e.exprSize();
   return root == null ? sz : sz + root.exprSize();
 }
Beispiel #30
0
 @Override
 public VarUsage count(final Var var) {
   final VarUsage inRoot = root == null ? VarUsage.NEVER : root.count(var);
   return VarUsage.sum(var, steps) == VarUsage.NEVER ? inRoot : VarUsage.MORE_THAN_ONCE;
 }