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

Method optPred

basex-core/src/main/java/org/basex/query/expr/CmpG.java:328–388  ·  view source on GitHub ↗

Optimizes this expression as predicate. @param cc compilation context @return resulting expression @throws QueryException query exception

(final CompileContext cc)

Source from the content-addressed store, hash-verified

326 * @throws QueryException query exception
327 */
328 private Expr optPred(final CompileContext cc) throws QueryException {
329 final Value val = cc.qc.focus.value;
330 if(val == null) return this;
331
332 final Expr expr1 = exprs[0], expr2 = exprs[1];
333 if(val.seqType().type instanceof final NodeType nt && nt.kind() != Kind.NODE &&
334 expr1 instanceof final ContextFn fn &&
335 expr2 instanceof final Value value && op == CmpOp.EQ) {
336 // skip functions that do not refer to the current context value
337 if(fn.exprs.length > 0 && !(fn.exprs[0] instanceof ContextValue)) return this;
338
339 final ArrayList<QNm> qnames = new ArrayList<>();
340 Scope scope = null;
341 if(expr2.seqType().type.isStringOrUntyped()) {
342 // local-name() eq 'a' → self::*:a
343 if(LOCAL_NAME.is(fn)) {
344 scope = Scope.LOCAL;
345 for(final Item item : value) {
346 final byte[] name = item.string(info);
347 if(XMLToken.isNCName(name)) qnames.add(new QNm(name));
348 }
349 } else if(NAMESPACE_URI.is(fn)) {
350 // namespace-uri() = ('URI1', 'URI2') → self::Q{URI1}* | self::Q{URI2}*
351 for(final Item item : value) {
352 final byte[] uri = item.string(info);
353 if(Token.eq(Token.normalize(uri), uri)) qnames.add(new QNm(Token.cpToken(':'), uri));
354 }
355 if(qnames.size() == value.size()) scope = Scope.URI;
356 } else if(NAME.is(fn)) {
357 // (db-without-ns)[name() = 'city'] → (db-without-ns)[self::city]
358 final Data data = cc.qc.focus.value.data();
359 final byte[] dataNs = data != null ? data.defaultNs() : null;
360 if(dataNs != null && dataNs.length == 0) {
361 scope = Scope.LOCAL;
362 for(final Item item : value) {
363 final byte[] name = item.string(info);
364 if(XMLToken.isNCName(name)) qnames.add(new QNm(name));
365 }
366 }
367 }
368 } else if(NODE_NAME.is(fn) && expr2.seqType().type == BasicType.QNAME) {
369 // node-name() = #prefix:local → self::prefix:local
370 scope = NameTest.Scope.FULL;
371 for(final Item item : value) {
372 qnames.add((QNm) item);
373 }
374 }
375
376 if(scope != null) {
377 final ExprList paths = new ExprList(2);
378 for(final QNm qname : qnames) {
379 final Test test = Test.get(nt.kind(), qname, scope, sc().elemNS);
380 final Expr step = Step.self(cc, null, info, test);
381 if(step != Empty.VALUE) paths.add(Path.get(cc, info, null, step));
382 }
383 return paths.isEmpty() ? Bln.FALSE : paths.size() == 1 ? paths.get(0) :
384 new Union(info, paths.finish()).optimize(cc);
385 }

Callers 1

simplifyForMethod · 0.95

Calls 15

seqTypeMethod · 0.95
isNCNameMethod · 0.95
eqMethod · 0.95
normalizeMethod · 0.95
cpTokenMethod · 0.95
defaultNsMethod · 0.95
getMethod · 0.95
selfMethod · 0.95
getMethod · 0.95
seqTypeMethod · 0.65
kindMethod · 0.65
isStringOrUntypedMethod · 0.65

Tested by

no test coverage detected