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

Method optimizeEbv

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

Tries to merge consecutive EBV tests. @param or union or intersection @param predicate predicate test @param cc compilation context @return true if evaluation can be skipped @throws QueryException query exception

(final boolean or, final boolean predicate, final CompileContext cc)

Source from the content-addressed store, hash-verified

181 * @throws QueryException query exception
182 */
183 final boolean optimizeEbv(final boolean or, final boolean predicate, final CompileContext cc)
184 throws QueryException {
185
186 final ExprList list = new ExprList(exprs.length);
187 boolean pos = false;
188 for(final Expr expr : exprs) {
189 // pre-evaluate values
190 if(expr instanceof Value && (!predicate || !expr.seqType().mayBeNumber())) {
191 // skip evaluation: true() or $bool → true()
192 if(expr.test(cc.qc, info, 0) == or) return true;
193 // ignore result: true() and $bool → $bool
194 cc.info(QueryText.OPTREMOVE_X_X, expr, (Supplier<?>) this::description);
195 } else if(!pos && list.contains(expr) && !expr.has(Flag.NDT)) {
196 // ignore duplicates: A[$node and $node] → A[$node]
197 cc.info(QueryText.OPTREMOVE_X_X, expr, (Supplier<?>) this::description);
198 } else {
199 list.add(expr);
200 // preserve entries after positional predicates
201 if(predicate && !pos) pos = mayBePositional(expr);
202 }
203 }
204 exprs = list.next();
205
206 if(!(predicate && has(Flag.POS))) {
207 final Class<? extends Arr> clazz = or ? And.class : Or.class;
208 final QueryBiFunction<Boolean, Expr[], Expr> func = (invert, args) ->
209 invert == or ? new And(info, args) : new Or(info, args);
210 final Expr tmp = rewrite(clazz, func, cc);
211 if(tmp != null) {
212 exprs = new Expr[] { tmp };
213 cc.info(QueryText.OPTREWRITE_X_X, (Supplier<?>) this::description, this);
214 }
215 }
216
217 list.add(exprs);
218 for(int l = 0; l < list.size(); l++) {
219 for(int m = l + 1; m < list.size(); m++) {
220 final Expr expr1 = list.get(l), expr2 = list.get(m);
221 if(!expr1.has(Flag.NDT) && !(predicate && expr1.has(Flag.POS))) {
222 // A or not(A) → true()
223 // A[not(B)][B] → ()
224 // empty(A) or exists(A) → true()
225 if(contradict(expr1, expr2, true) || contradict(expr2, expr1, true)) return true;
226
227 // 'a'[. = 'a' or . = 'b'] → 'a'[. = ('a', 'b')]
228 // $v[. != 'a'][. != 'b'] → $v[not(. = ('a', 'b')]
229 final Expr merged = expr1.mergeEbv(expr2, or, cc);
230 if(merged != null) {
231 cc.info(QueryText.OPTSIMPLE_X_X, (Supplier<?>) this::description, this);
232 list.set(l, merged);
233 list.remove(m--);
234 }
235 }
236 }
237 }
238 exprs = list.next();
239
240 // not($a) and not($b) → not($a or $b)

Callers 2

optimizeMethod · 0.45
optimizeMethod · 0.45

Calls 15

seqTypeMethod · 0.95
testMethod · 0.95
hasMethod · 0.95
mayBePositionalMethod · 0.95
hasMethod · 0.95
rewriteMethod · 0.95
contradictMethod · 0.95
mergeEbvMethod · 0.95
argMethod · 0.95
optimizeMethod · 0.95
mayBeNumberMethod · 0.80
infoMethod · 0.65

Tested by

no test coverage detected