Пример #1
0
  @Override
  public Value value(final QueryContext ctx) throws QueryException {
    final int o = (int) ctx.resources.output.size();
    final Updates updates = ctx.resources.updates();
    final ContextModifier tmp = updates.mod;
    final TransformModifier pu = new TransformModifier();
    updates.mod = pu;

    try {
      for (final Let fo : copies) {
        final Iter ir = ctx.iter(fo.expr);
        Item i = ir.next();
        if (!(i instanceof ANode) || ir.next() != null) throw UPCOPYMULT.get(fo.info, fo.var.name);

        // copy node to main memory data instance
        i = ((ANode) i).dbCopy(ctx.context.options);
        // add resulting node to variable
        ctx.set(fo.var, i, info);
        pu.addData(i.data());
      }
      final Value v = ctx.value(expr[0]);
      if (!v.isEmpty()) throw BASEX_MOD.get(info);

      updates.prepare();
      updates.apply();
      return ctx.value(expr[1]);
    } finally {
      ctx.resources.output.size(o);
      updates.mod = tmp;
    }
  }
Пример #2
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;
  }
Пример #3
0
  /**
   * Returns the specified function literal.
   *
   * @param name function name
   * @param arity number of arguments
   * @param dyn dynamic invocation flag
   * @param ctx query context
   * @param ii input info
   * @return literal function expression
   * @throws QueryException query exception
   */
  public static FItem get(
      final QNm name,
      final long arity,
      final boolean dyn,
      final QueryContext ctx,
      final InputInfo ii)
      throws QueryException {

    final Expr[] args = new Expr[(int) arity];
    final Var[] vars = new Var[args.length];
    for (int i = 0; i < args.length; i++) {
      vars[i] = ctx.uniqueVar(ii, null);
      args[i] = new VarRef(ii, vars[i]);
    }

    final TypedFunc f = get(name, args, dyn, ctx, ii);
    if (f == null) {
      if (!dyn) FUNCUNKNOWN.thrw(ii, name + "#" + arity);
      return null;
    }

    // compile the function if it hasn't been done statically
    if (dyn && f.fun instanceof UserFuncCall) {
      final UserFunc usf = ((UserFuncCall) f.fun).func();
      if (usf != null && usf.declared) usf.compile(ctx);
    }

    final FuncType ft = f.type;
    return new FuncItem(name, vars, f.fun, ft, false);
  }
Пример #4
0
 @Override
 Value[] evalArgs(final QueryContext ctx) throws QueryException {
   final int al = expr.length - 1;
   final Value[] args = new Value[al];
   for (int a = 0; a < al; ++a) args[a] = ctx.value(expr[a]);
   return args;
 }
Пример #5
0
  /**
   * Extracts entries from the archive.
   *
   * @param ctx query context
   * @return text entries
   * @throws QueryException query exception
   */
  private TokenList extract(final QueryContext ctx) throws QueryException {
    final B64 archive = (B64) checkType(checkItem(expr[0], ctx), AtomType.B64);
    TokenSet hs = null;
    if (expr.length > 1) {
      // filter result to specified entries
      hs = new TokenSet();
      final Iter names = ctx.iter(expr[1]);
      for (Item en; (en = names.next()) != null; ) {
        hs.add(checkElmStr(en).string(info));
      }
    }

    final TokenList tl = new TokenList();
    final ArchiveIn in = ArchiveIn.get(archive.input(info), info);
    try {
      while (in.more()) {
        final ZipEntry ze = in.entry();
        if (ze.isDirectory()) continue;
        if (hs == null || hs.delete(token(ze.getName())) != 0) tl.add(in.read());
      }
    } catch (final IOException ex) {
      Util.debug(ex);
      ARCH_FAIL.thrw(info, ex);
    } finally {
      in.close();
    }
    return tl;
  }
Пример #6
0
 @Override
 public Item item(final QueryContext ctx, final InputInfo ii) throws QueryException {
   Map map = Map.EMPTY;
   for (int i = 0; i < expr.length; i++) {
     map = map.insert(checkItem(expr[i], ctx), ctx.value(expr[++i]), ii);
   }
   return map;
 }
Пример #7
0
 /**
  * Returns all tokens of the query.
  *
  * @param qc query context
  * @return token list
  * @throws QueryException query exception
  */
 private TokenList tokens(final QueryContext qc) throws QueryException {
   final TokenList tl = new TokenList();
   final Iter ir = qc.iter(query);
   for (byte[] qu; (qu = nextToken(ir)) != null; ) {
     // skip empty tokens if not all results are needed
     if (qu.length != 0 || mode == FTMode.ALL || mode == FTMode.ALL_WORDS) tl.add(qu);
   }
   return tl;
 }
Пример #8
0
 @Override
 public Iter iter(final QueryContext qc) throws QueryException {
   final Value seq = qc.value(ts);
   for (final TypeCase tc : cases) {
     final Iter iter = tc.iter(qc, seq);
     if (iter != null) return iter;
   }
   // will never happen
   throw Util.notExpected();
 }
Пример #9
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;
   }
 }
Пример #10
0
  /**
   * Creates a new archive.
   *
   * @param ctx query context
   * @return archive
   * @throws QueryException query exception
   */
  private B64 create(final QueryContext ctx) throws QueryException {
    final Iter entr = ctx.iter(expr[0]);
    final Iter cont = ctx.iter(expr[1]);
    final Item opt = expr.length > 2 ? expr[2].item(ctx, info) : null;
    final TokenMap map = new FuncParams(Q_OPTIONS, info).parse(opt);

    final byte[] f = map.get(FORMAT);
    final String format = f != null ? string(lc(f)) : "zip";
    final ArchiveOut out = ArchiveOut.get(format, info);
    // check algorithm
    final byte[] alg = map.get(ALGORITHM);
    int level = ZipEntry.DEFLATED;
    if (alg != null) {
      if (format.equals("zip") && !eq(alg, STORED, DEFLATE)
          || format.equals("gzip") && !eq(alg, DEFLATE)) {
        ARCH_SUPP.thrw(info, ALGORITHM, alg);
      }
      if (eq(alg, STORED)) level = ZipEntry.STORED;
      else if (eq(alg, DEFLATE)) level = ZipEntry.DEFLATED;
    }
    out.level(level);

    try {
      int e = 0;
      int c = 0;
      Item en, cn;
      while (true) {
        en = entr.next();
        cn = cont.next();
        if (en == null || cn == null) break;
        if (out instanceof GZIPOut && c > 0)
          ARCH_ONE.thrw(info, format.toUpperCase(Locale.ENGLISH));
        add(checkElmStr(en), cn, out, level);
        e++;
        c++;
      }
      // count remaining entries
      if (cn != null) do c++; while (cont.next() != null);
      if (en != null) do e++; while (entr.next() != null);
      if (e != c) throw ARCH_DIFF.thrw(info, e, c);
    } catch (final IOException ex) {
      Util.debug(ex);
      throw ARCH_FAIL.thrw(info, ex);
    } finally {
      out.close();
    }
    return new B64(out.toArray());
  }
Пример #11
0
  /**
   * Updates an archive.
   *
   * @param ctx query context
   * @return updated archive
   * @throws QueryException query exception
   */
  private B64 update(final QueryContext ctx) throws QueryException {
    final B64 archive = (B64) checkType(checkItem(expr[0], ctx), AtomType.B64);
    // entries to be updated
    final TokenObjMap<Item[]> hm = new TokenObjMap<Item[]>();

    final Iter entr = ctx.iter(expr[1]);
    final Iter cont = ctx.iter(expr[2]);
    int e = 0;
    int c = 0;
    Item en, cn;
    while (true) {
      en = entr.next();
      cn = cont.next();
      if (en == null || cn == null) break;
      hm.add(checkElmStr(en).string(info), new Item[] {en, cn});
      e++;
      c++;
    }
    // count remaining entries
    if (cn != null) do c++; while (cont.next() != null);
    if (en != null) do e++; while (entr.next() != null);
    if (e != c) ARCH_DIFF.thrw(info, e, c);

    final ArchiveIn in = ArchiveIn.get(archive.input(info), info);
    final ArchiveOut out = ArchiveOut.get(in.format(), info);
    try {
      if (in instanceof GZIPIn) ARCH_MODIFY.thrw(info, in.format().toUpperCase(Locale.ENGLISH));
      // delete entries to be updated
      while (in.more()) if (!hm.contains(token(in.entry().getName()))) out.write(in);
      // add new and updated entries
      for (final byte[] h : hm) {
        if (h == null) continue;
        final Item[] it = hm.get(h);
        add(it[0], it[1], out, ZipEntry.DEFLATED);
      }
    } catch (final IOException ex) {
      Util.debug(ex);
      ARCH_FAIL.thrw(info, ex);
    } finally {
      in.close();
      out.close();
    }
    return new B64(out.toArray());
  }
Пример #12
0
  @Override
  public Expr optimize(final QueryContext qc, final VarScope scp) throws QueryException {
    super.optimize(qc, scp);

    final ExprList el = new ExprList(exprs.length);
    for (final Expr ex : exprs) {
      if (ex.isEmpty()) {
        // remove empty operands (return empty sequence if first value is empty)
        if (el.isEmpty()) return optPre(qc);
        qc.compInfo(OPTREMOVE_X_X, this, ex);
      } else {
        el.add(ex);
      }
    }
    // ensure that results are always sorted
    if (el.size() == 1 && iterable) return el.get(0);
    // replace expressions with optimized list
    exprs = el.finish();
    return this;
  }
Пример #13
0
  /**
   * Deletes files from an archive.
   *
   * @param ctx query context
   * @return updated archive
   * @throws QueryException query exception
   */
  private B64 delete(final QueryContext ctx) throws QueryException {
    final B64 archive = (B64) checkType(checkItem(expr[0], ctx), AtomType.B64);
    // entries to be deleted
    final TokenObjMap<Item[]> hm = new TokenObjMap<Item[]>();
    final Iter names = ctx.iter(expr[1]);
    for (Item en; (en = names.next()) != null; ) {
      hm.add(checkElmStr(en).string(info), null);
    }

    final ArchiveIn in = ArchiveIn.get(archive.input(info), info);
    final ArchiveOut out = ArchiveOut.get(in.format(), info);
    try {
      if (in instanceof GZIPIn) ARCH_MODIFY.thrw(info, in.format().toUpperCase(Locale.ENGLISH));
      while (in.more()) if (!hm.contains(token(in.entry().getName()))) out.write(in);
    } catch (final IOException ex) {
      Util.debug(ex);
      ARCH_FAIL.thrw(info, ex);
    } finally {
      in.close();
      out.close();
    }
    return new B64(out.toArray());
  }
Пример #14
0
  /**
   * Returns an instance of a with the specified name and number of arguments, or {@code null}.
   *
   * @param name name of the function
   * @param args optional arguments
   * @param dyn compile-/run-time flag
   * @param ctx query context
   * @param ii input info
   * @return function instance
   * @throws QueryException query exception
   */
  public static TypedFunc get(
      final QNm name,
      final Expr[] args,
      final boolean dyn,
      final QueryContext ctx,
      final InputInfo ii)
      throws QueryException {

    // get namespace and local name
    // parse data type constructors
    if (eq(name.uri(), XSURI)) {
      final byte[] ln = name.local();
      final AtomType type = AtomType.find(name, false);
      if (type == null) {
        final Levenshtein ls = new Levenshtein();
        for (final AtomType t : AtomType.values()) {
          if (t.par != null
              && t != AtomType.NOT
              && t != AtomType.AAT
              && t != AtomType.BIN
              && ls.similar(lc(ln), lc(t.string()), 0))
            FUNSIMILAR.thrw(ii, name.string(), t.string());
        }
      }
      // no constructor function found, or abstract type specified
      if (type == null || type == AtomType.NOT || type == AtomType.AAT) {
        FUNCUNKNOWN.thrw(ii, name.string());
      }

      if (args.length != 1) FUNCTYPE.thrw(ii, name.string());
      final SeqType to = SeqType.get(type, Occ.ZERO_ONE);
      return TypedFunc.constr(new Cast(ii, args[0], to), to);
    }

    // pre-defined functions
    final StandardFunc fun = Functions.get().get(name, args, ii);
    if (fun != null) {
      if (!ctx.sc.xquery3 && fun.xquery3()) FEATURE30.thrw(ii);
      for (final Function f : Function.UPDATING) {
        if (fun.sig == f) {
          ctx.updating(true);
          break;
        }
      }
      return new TypedFunc(fun, fun.sig.type(args.length));
    }

    // user-defined function
    final TypedFunc tf = ctx.funcs.get(name, args, ii);
    if (tf != null) return tf;

    // Java function (only allowed with administrator permissions)
    final JavaMapping jf = JavaMapping.get(name, args, ctx, ii);
    if (jf != null) return TypedFunc.java(jf);

    // add user-defined function that has not been declared yet
    if (!dyn && FuncType.find(name) == null) return ctx.funcs.add(name, args, ii, ctx);

    // no function found
    return null;
  }