Bug #4610
closedBug in XPath optimizer with positional filter
100%
Description
Hello,
I'm using the XPath engine of Saxon HE 9.8 (JRE). The optimizer fails to optimize the following form of expression
//A[true() = false()]/*[2]
with this exception
net.sf.saxon.trans.XPathException: Axis step child::element() cannot be used here: the context item is absent
at net.sf.saxon.expr.AxisExpression.typeCheck(AxisExpression.java:115)
at net.sf.saxon.expr.Operand.typeCheck(Operand.java:185)
at net.sf.saxon.expr.Expression.typeCheckChildren(Expression.java:554)
at net.sf.saxon.expr.SubscriptExpression.typeCheck(SubscriptExpression.java:58)
at net.sf.saxon.expr.FilterExpression.optimize(FilterExpression.java:446)
at net.sf.saxon.expr.Operand.optimize(Operand.java:200)
at net.sf.saxon.expr.SlashExpression.optimize(SlashExpression.java:345)
at net.sf.saxon.expr.Operand.optimize(Operand.java:200)
at net.sf.saxon.expr.sort.DocumentSorter.optimize(DocumentSorter.java:95)
at net.sf.saxon.sxpath.XPathEvaluator.createExpression(XPathEvaluator.java:141)
Here is the optimizer trace:
OPT : At line 1 of
OPT : Replaced general comparison by value comparison
OPT : Expression after rewrite: true() eq false()
OPT : At line 1 of
OPT : Filter expression eliminated because predicate is always false
OPT : Expression after rewrite: ()
OPT : At line 1 of
OPT : Rewriting numeric filter expression with constant subscript
OPT : Expression after rewrite: child::element()[2]
OPT : At line 1 of
OPT : Rewrote Filter Expression as:
OPT : Expression after rewrite: child::element()[2]
The following all work and are reduced to the empty sequence:
//A[true() = false()]/*[1]
//A[false()]/*[2]
()/*[2]
The latter two being the reduction steps that the optimization of the offending query is supposed to take.
The reason is not that I'm writing literally true() = false()
, but I'm inlining some statically known variables.
On Saxon HE 9, this doesn't cause an exception but the following warning:
Warning on line 1 column 5
Evaluation will always throw a dynamic error: Axis step child::element() cannot be used here:
the context item is absent
and the evaluation does not throw a dynamic error.
I didn't test on previous versions of Saxon.
For reference, context around line 115 is the following:
public Expression typeCheck(ExpressionVisitor visitor, ContextItemStaticInfo contextInfo) throws XPathException {
boolean noWarnings = ...;
doneTypeCheck = true;
if (contextInfo.getItemType() == ErrorType.getInstance()) {
XPathException err = new XPathException("Axis step " + toString() +
" cannot be used here: the context item is absent");
// ...
throw err;
}
...
This should probably have another check for whether the contextInfo is the empty sequence.
Related issues
Updated by Michael Kay over 4 years ago
Reproduced on 9.8, giving
Type error on line 1 column 24 of file:/Users/mike/Desktop/temp/:
XPDY0002: Axis step child::element() cannot be used here: the context item is absent
Static error(s) in query
On 9.9 this is reduced to a warning:
Warning on line 1 column 24 of file:/Users/mike/Desktop/temp/:
Evaluation will always throw a dynamic error: Axis step child::element() cannot be used
here: the context item is absent
And on 10.0 the query succeeds with no error or warning.
So it looks as if the problem has been fixed in later releases.
Updated by Michael Kay over 4 years ago
Rather than resting on this one, I decided to investigate why 10.0 is not reporting the warning, and it turns out that the constant ValueExpression
true() eq false()
is not being optimised to false()
. I've fixed this, and sure enough, we now get the warning.
So now we need to fix the warning.
I think we can do this with a minor change to the sequence of operations. Currently optimization of a path expression A/B works as follows:
- Optimize A
- Determine the static type S of the post-optimization A.
- Optimize B, supplying S as the context item type
- If either A or B, post optimization, is literal
()
, reduce the entire expression to literal()
.
The warning occurs during step 3, and can be avoided if we test whether A is literal ()
before doing step 3.
Updated by Michael Kay over 4 years ago
- Category set to Internals
- Status changed from New to Resolved
- Assignee set to Michael Kay
- Applies to branch 10 added
- Fix Committed on Branch 10, 9.9 added
Patched SlashExpression.optimize()
on both the 9.9 and 10 branches, and OptimizerEE.optimizeValueComparison()
on the 10 branch only.
We're not making any further changes on the 9.8 branch unless there's something extremely severe.
Updated by Michael Kay over 4 years ago
Fixing the code in optimizeValueComparison has exposed another bug in code which previously wasn't being executed. The symptom is
java.lang.NullPointerException
at net.sf.saxon.expr.CompareToIntegerConstant.effectiveBooleanValue(CompareToIntegerConstant.java:122)
at net.sf.saxon.expr.CompareToConstant.evaluateItem(CompareToConstant.java:102)
at net.sf.saxon.expr.CompareToConstant.evaluateItem(CompareToConstant.java:24)
in QT3 test case -s:prod-ValueComp -t:value-comp-eq-int-4
which does 40 eq xs:integer(/works/employee[830]/hours)
, with the path expression returning an empty sequence. We shouldn't be generating a CompareToIntegerConstant
expression if the other operand is capable of returning an empty sequence, but the cardinality test is wrong.
Updated by O'Neil Delpratt about 4 years ago
- % Done changed from 0 to 100
- Fixed in Maintenance Release 10.2 added
Bug fix applied in the Saxon 10.2 maintenance release.
Updated by O'Neil Delpratt about 4 years ago
- Status changed from Resolved to Closed
- Fixed in Maintenance Release 9.9.1.8 added
Bug fix applied on the Saxon 9.9.1.8 maintenance release.
Updated by Clément Fournier over 2 years ago
- Copied to Bug #5361: Bug in XPath optimizer with positional filter, when LHS of filter is empty sequence added
Please register to edit this issue