Skip to content

Commit 1425c5d

Browse files
line-oJuri Leino
authored and
Juri Leino
committed
[fix] simple predicates evaluating to empty sequences
Fixes eXist-db#2445 By definition the following Xpaths must evaluate to an empty sequence - `<a/>[self::b]` - `<a/>/@b/c` - `<a/>/text()/b` Instead of throwing an Exception the staticReturnType of the current step and the contextInfo returnType are set to Type.EMPTY.
1 parent 7da2ecd commit 1425c5d

File tree

1 file changed

+49
-27
lines changed

1 file changed

+49
-27
lines changed

exist-core/src/main/java/org/exist/xquery/LocationStep.java

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -263,40 +263,62 @@ public void analyze(final AnalyzeContextInfo contextInfo) throws XPathException
263263
this.axis = Constants.DESCENDANT_AXIS;
264264
}
265265

266+
final Expression contextStep;
267+
final LocationStep cStep;
268+
final NodeTest stepTest;
269+
final NodeTest contextStepTest;
270+
266271
// static analysis for empty-sequence
267272
switch (axis) {
268273
case Constants.SELF_AXIS:
269-
if (getTest().getType() != Type.NODE) {
270-
final Expression contextStep = contextInfo.getContextStep();
271-
if (contextStep instanceof LocationStep cStep) {
272-
273-
// WM: the following checks will only work on simple filters like //a[self::b], so we
274-
// have to make sure they are not applied to more complex expression types
275-
if (parent.getSubExpressionCount() == 1 && !Type.subTypeOf(getTest().getType(), cStep.getTest().getType())) {
276-
throw new XPathException(this,
277-
ErrorCodes.XPST0005, "Got nothing from self::" + getTest() + ", because parent node kind " + Type.getTypeName(cStep.getTest().getType()));
278-
}
274+
if (getTest().getType() == Type.NODE) {
275+
break;
276+
}
279277

280-
if (parent.getSubExpressionCount() == 1 && !(cStep.getTest().isWildcardTest() || getTest().isWildcardTest()) && !cStep.getTest().equals(getTest())) {
281-
throw new XPathException(this,
282-
ErrorCodes.XPST0005, "Self::" + getTest() + " called on set of nodes which do not contain any nodes of this name.");
283-
}
284-
}
278+
// WM: the following checks will only work on simple filters like //a[self::b], so we
279+
// have to make sure they are not applied to more complex expression types
280+
if (parent.getSubExpressionCount() > 1) {
281+
break;
282+
}
283+
284+
contextStep = contextInfo.getContextStep();
285+
if (!(contextStep instanceof LocationStep cStep)) {
286+
break;
287+
}
288+
289+
stepTest = getTest();
290+
contextStepTest = cStep.getTest();
291+
292+
if (!Type.subTypeOf(stepTest.getType(), contextStepTest.getType())) {
293+
// return empty sequence
294+
contextInfo.setStaticType(Type.EMPTY);
295+
staticReturnType = Type.EMPTY;
296+
break;
297+
}
298+
299+
if (!stepTest.isWildcardTest() &&
300+
!contextStepTest.isWildcardTest() &&
301+
!contextStepTest.equals(stepTest)) {
302+
// return empty sequence
303+
contextInfo.setStaticType(Type.EMPTY);
304+
staticReturnType = Type.EMPTY;
285305
}
286306
break;
287-
// case Constants.DESCENDANT_AXIS:
307+
// case Constants.DESCENDANT_AXIS:
288308
case Constants.DESCENDANT_SELF_AXIS:
289-
final Expression contextStep = contextInfo.getContextStep();
290-
if (contextStep instanceof LocationStep cStep) {
291-
292-
if ((
293-
cStep.getTest().getType() == Type.ATTRIBUTE ||
294-
cStep.getTest().getType() == Type.TEXT
295-
)
296-
&& cStep.getTest() != getTest()) {
297-
throw new XPathException(this,
298-
ErrorCodes.XPST0005, "Descendant-or-self::" + getTest() + " from an attribute gets nothing.");
299-
}
309+
contextStep = contextInfo.getContextStep();
310+
if (!(contextStep instanceof LocationStep cStep)) {
311+
break;
312+
}
313+
314+
stepTest = getTest();
315+
contextStepTest = cStep.getTest();
316+
317+
if ((contextStepTest.getType() == Type.ATTRIBUTE || contextStepTest.getType() == Type.TEXT) &&
318+
contextStepTest != stepTest) {
319+
// return empty sequence
320+
contextInfo.setStaticType(Type.EMPTY);
321+
staticReturnType = Type.EMPTY;
300322
}
301323
break;
302324
// case Constants.PARENT_AXIS:

0 commit comments

Comments
 (0)