Skip to content

Commit e3cb994

Browse files
committed
[fix] simple predicates evaluating to empty sequences
Fixes #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 18593f2 commit e3cb994

File tree

1 file changed

+51
-29
lines changed

1 file changed

+51
-29
lines changed

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

Lines changed: 51 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -260,42 +260,64 @@ public void analyze(final AnalyzeContextInfo contextInfo) throws XPathException
260260
this.axis = Constants.DESCENDANT_AXIS;
261261
}
262262

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

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

0 commit comments

Comments
 (0)