Пример #1
0
  @Override
  public boolean indexAccessible(final IndexInfo ii) throws QueryException {
    final int es = exprs.length;
    final boolean[] ng = new boolean[es];
    int costs = 0;
    for (final FTExpr expr : exprs) {
      if (!expr.indexAccessible(ii)) return false;
      // use worst costs for estimation, as all index results may need to be scanned
      if (costs < ii.costs) costs = ii.costs;
    }

    ii.costs = costs;
    negated = ng;
    return true;
  }
Пример #2
0
  /**
   * Merges a single predicate with the root expression and returns the resulting expression, or
   * returns a self reference if the expression cannot be merged. This function is e.g. called by
   * {@link Where#optimize}.
   *
   * @param qc query context
   * @param scp variable scope
   * @param root root expression
   * @return expression
   * @throws QueryException query exception
   */
  public Expr merge(final Expr root, final QueryContext qc, final VarScope scp)
      throws QueryException {

    // only one predicate can be rewritten; root expression must yield nodes
    if (preds.length != 1 || !(root.seqType().type instanceof NodeType)) return this;

    final Expr pred = preds[0];
    // a[.] -> a
    if (pred instanceof Context) return root;

    if (!pred.seqType().mayBeNumber()) {
      // a[b] -> a/b
      if (pred instanceof Path) return Path.get(info, root, pred).optimize(qc, scp);

      if (pred instanceof CmpG) {
        final CmpG cmp = (CmpG) pred;
        final Expr expr1 = cmp.exprs[0], expr2 = cmp.exprs[1];
        // only first operand can depend on context
        if (!expr2.has(Flag.CTX)) {
          Expr path = null;
          // a[. = 'x'] -> a = 'x'
          if (expr1 instanceof Context) path = root;
          // a[text() = 'x'] -> a/text() = 'x'
          if (expr1 instanceof Path) path = Path.get(info, root, expr1).optimize(qc, scp);
          if (path != null) return new CmpG(path, expr2, cmp.op, cmp.coll, cmp.sc, cmp.info);
        }
      }

      if (pred instanceof FTContains) {
        final FTContains cmp = (FTContains) pred;
        final FTExpr ftexpr = cmp.ftexpr;
        // only first operand can depend on context
        if (!ftexpr.has(Flag.CTX)) {
          final Expr expr = cmp.expr;
          Expr path = null;
          // a[. contains text 'x'] -> a contains text 'x'
          if (expr instanceof Context) path = root;
          // [text() contains text 'x'] -> a/text() contains text 'x'
          if (expr instanceof Path) path = Path.get(info, root, expr).optimize(qc, scp);
          if (path != null) return new FTContains(path, ftexpr, cmp.info);
        }
      }
    }
    return this;
  }
Пример #3
0
 @Override
 public FTExpr compile(final CompileContext cc) throws QueryException {
   super.compile(cc);
   boolean not = true;
   for (final FTExpr expr : exprs) not &= expr instanceof FTNot;
   if (not) {
     // convert (!A and !B and ...) to !(A or B or ...)
     final int es = exprs.length;
     for (int e = 0; e < es; ++e) exprs[e] = exprs[e].exprs[0];
     return new FTNot(info, new FTOr(info, exprs));
   }
   return this;
 }
Пример #4
0
 @Override
 public boolean has(final Flag flag) {
   for (final FTExpr e : exprs) if (e.has(flag)) return true;
   return false;
 }
Пример #5
0
 /**
  * Checks if sub expressions of a mild not operator violate the grammar.
  *
  * @return result of check
  */
 boolean usesExclude() {
   for (final FTExpr e : exprs) if (e.usesExclude()) return true;
   return false;
 }