MCPcopy Create free account
hub / github.com/BaseXdb/basex / rewrite

Method rewrite

basex-core/src/main/java/org/basex/query/expr/Arr.java:281–327  ·  view source on GitHub ↗

Rewrites logical and set expressions. @param inverse inverse operator @param newExpr function for creating a new expression @param cc compilation context @return optimized expression or null @throws QueryException query exception

(final Class<? extends Arr> inverse,
      final QueryBiFunction<Boolean, Expr[], Expr> newExpr, final CompileContext cc)

Source from the content-addressed store, hash-verified

279 * @throws QueryException query exception
280 */
281 final Expr rewrite(final Class<? extends Arr> inverse,
282 final QueryBiFunction<Boolean, Expr[], Expr> newExpr, final CompileContext cc)
283 throws QueryException {
284
285 // skip if only one operand is left, or if children have no operands that can be optimized
286 if(exprs.length < 2 || !((Checks<Expr>) inverse::isInstance).any(exprs))
287 return null;
288
289 // check if expressions have common operands
290 final java.util.function.Function<Expr, ExprList> entries = ex ->
291 new ExprList().add(inverse.isInstance(ex) ? ex.args() : new Expr[] { ex });
292 final int el = exprs.length;
293 final ExprList lefts = new ExprList().add(entries.apply(exprs[0]));
294 for(int e = 1; e < el && !lefts.isEmpty(); ++e) {
295 final ExprList curr = entries.apply(exprs[e]);
296 for(int c = lefts.size() - 1; c >= 0; c--) {
297 if(!curr.contains(lefts.get(c))) lefts.remove(c);
298 }
299 }
300 if(lefts.isEmpty()) return null;
301
302 // common operands found: recombine expressions
303 final QueryBiFunction<Boolean, Expr[], Expr> f = (invert, args) ->
304 args.length == 1 ? args[0] : newExpr.apply(invert, args).optimize(cc);
305
306 final Expr left = f.apply(true, lefts.toArray());
307 final ExprList rights = new ExprList(exprs.length);
308 for(final Expr expr : exprs) {
309 final ExprList curr = entries.apply(expr).removeAll(lefts);
310 if(curr.isEmpty()) {
311 // no additional tests: return common tests
312 // A intersect (A union B) → A
313 // (A and B) or (A and B and C) → A
314 return left.seqType().type instanceof NodeType && !left.ddo() ?
315 cc.function(Function.DISTINCT_ORDERED_NODES, info, left) : left;
316 } else if(curr.size() == 1) {
317 // single additional test: add this test
318 // (A and B) or (A and C) → A and (B or C)
319 rights.add(curr.get(0));
320 } else {
321 // multiple additional tests: simplify expression
322 // (A and B) or (A and C and D) → A and (B or (C and D))
323 rights.add(f.apply(true, curr.finish()));
324 }
325 }
326 return f.apply(true, new Expr[] { left, f.apply(false, rights.finish()) });
327 }
328
329 /**
330 * Checks if the specified expression may be positional.

Callers 4

optimizeEbvMethod · 0.95
optMethod · 0.45
optimizeMethod · 0.45
optMethod · 0.45

Calls 15

seqTypeMethod · 0.95
ddoMethod · 0.95
anyMethod · 0.80
addMethod · 0.65
argsMethod · 0.65
applyMethod · 0.65
sizeMethod · 0.65
containsMethod · 0.65
getMethod · 0.65
removeMethod · 0.65
isEmptyMethod · 0.45
optimizeMethod · 0.45

Tested by

no test coverage detected