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

Method mergeStep

basex-core/src/main/java/org/basex/query/expr/path/Path.java:1042–1091  ·  view source on GitHub ↗

Merges adjacent steps. @param curr current step @param next next step @param prev previous step (can be null) @param cc compilation context @return merged expression or null @throws QueryException query exception

(final Step curr, final Expr next, final Expr prev,
      final CompileContext cc)

Source from the content-addressed store, hash-verified

1040 * @throws QueryException query exception
1041 */
1042 private static Expr mergeStep(final Step curr, final Expr next, final Expr prev,
1043 final CompileContext cc) throws QueryException {
1044
1045 // do not merge if current step contains positional predicates
1046 if(curr.mayBePositional()) return null;
1047
1048 // merge self steps: child::*/self::a → child::a
1049 final Step nxt = next instanceof final Step stp ? stp : null;
1050 if(nxt != null && nxt.axis == SELF && !nxt.mayBePositional()) {
1051 final Test test = curr.test.intersect(nxt.test);
1052 return test == null ? null :
1053 Step.get(cc, prev, curr.info(), curr.axis, test, ExprList.concat(curr.exprs, nxt.exprs));
1054 }
1055
1056 // merge descendant-or-self step
1057 if(curr.axis != DESCENDANT_OR_SELF || curr.exprs.length > 0 ||
1058 !curr.test.kind.oneOf(Kind.NODE, Kind.JNODE, Kind.GNODE)) return null;
1059
1060 // examples:
1061 // - descendant-or-self::node()/* → descendant::*
1062 // - descendant-or-self::node()/descendant::* → descendant::*
1063 // - descendant-or-self::node()/descendant-or-self::* → descendant-or-self::*
1064 final Axis merged = mergedAxis(nxt);
1065 if(merged != null) return Step.get(cc, prev, nxt.info(), merged, nxt.test, nxt.exprs);
1066
1067 // function for merging steps inside union expressions
1068 final QueryFunction<Expr, Expr> rewrite = expr -> {
1069 if(expr instanceof Union) {
1070 final Axis axis = commonAxis(expr.args());
1071 if(axis != null) {
1072 for(final Expr path : expr.args()) {
1073 final Path p = (Path) path;
1074 final Step s = (Step) p.steps[0];
1075 p.steps[0] = Step.get(cc, prev, s.info(), axis, s.test, s.exprs);
1076 }
1077 return expr.optimize(cc);
1078 }
1079 }
1080 return null;
1081 };
1082 // descendant-or-self::node()/(* | text()) → (descendant::text() | (descendant::*)
1083 if(next instanceof Union) return rewrite.apply(next);
1084
1085 // descendant-or-self::node()/(text()|*)[..] → (descendant::text() | descendant::*)[..]
1086 if(next instanceof final Filter filter && !filter.mayBePositional()) {
1087 final Expr expr = rewrite.apply(filter.root);
1088 if(expr != null) return Filter.get(cc, filter.info(), expr, filter.exprs);
1089 }
1090 return null;
1091 }
1092
1093 /**
1094 * Returns a merged axis for a step preceded by a descendant-or-self step.

Callers 1

mergeStepsMethod · 0.95

Calls 12

getMethod · 0.95
concatMethod · 0.95
mergedAxisMethod · 0.95
commonAxisMethod · 0.95
argsMethod · 0.95
optimizeMethod · 0.95
getMethod · 0.95
intersectMethod · 0.65
infoMethod · 0.65
oneOfMethod · 0.65
applyMethod · 0.65
mayBePositionalMethod · 0.45

Tested by

no test coverage detected