Bug #5361
closedBug in XPath optimizer with positional filter, when LHS of filter is empty sequence
100%
Description
Hello,
This is a similar issue and context to #4610.
I'm using the XPath engine of Saxon HE 10.6 (JRE) and inlining statically known variables. The optimizer fails to reduce the following expression to ()
when $foo
is replaced with false()
:
//A[$foo][child::*[2]]
with 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
Note that if you write //A[false()][child::*[2]]
, the parser does some early optimization, prunes the branch, and the optimizer isn't run at all. Only if you use a variable and set its static value to false()
in IndependentContext::bindVariable
, you get the bug. You can find a MWE attached.
Also note that the following work fine:
//A[$foo]/*[2]
//A[$foo=true()][child::*[2]]
I reproduced the issue on Saxon HE 10.2 and 10.6.
While debugging I found that the offending expression is represented like so:
(/)/((descendant::element(Q{}A)[false()])[child::element()[2]])
------------------------------------
Then, the LHS of the FilterExpression (underlined part above) is reduced to ()
. At this point the entire FilterExpression could already be folded to ()
, but optimization of the FilterExpression continues by optimizing the filter child::element()[2]
. This is initially a FilterExpression and is replaced by a SubscriptExpression. Type checking the SubscriptExpression fails with "the context item is absent" (the warning is reported at this point) and the SubscriptExpression becomes error("Axis step child::element() cannot be used here: the context item is absent")[2]
. This shouldn't have to happen as the LHS of the filter is ()
.
A possible fix would be to end the optimization of a FilterExpression as soon as the LHS has been optimized to ()
, without considering the predicate.
Files
Related issues
Updated by Clément Fournier over 2 years ago
- Copied from Bug #4610: Bug in XPath optimizer with positional filter added
Updated by Michael Kay over 2 years ago
Thanks for reporting it. I've reproduced it.
Note that the problem doesn't occur when using the s9api API:
Processor proc = new Processor(false);
XPathCompiler compiler = proc.newXPathCompiler();
compiler.declareVariable(new QName("", "falseVar"), ItemType.BOOLEAN, OccurrenceIndicator.ONE);
XPathSelector exp = compiler.compile("//A[$falseVar=true()][child::*[2]]").load();
The API you are using is a Saxon internal API that's really only retained for legacy reasons. But I'll investigate to see why there's a difference.
Updated by Michael Kay over 2 years ago
The reason for the difference is that the s9api API gives you no way to bind a value to the variable at compile time, it can only be bound at run-time.
Updated by Michael Kay over 2 years ago
In FilterExpression.optimize(), changing
getLhs().optimize(visitor, contextItemType);
to
getLhs().optimize(visitor, contextItemType);
if (Literal.isEmptySequence(getSelectExpression())) {
return getSelectExpression();
}
Updated by Michael Kay over 2 years ago
- Category changed from Internals to XPath conformance
- Status changed from New to Resolved
- Priority changed from Low to Normal
- Applies to branch 11, 9.9, trunk added
- Fix Committed on Branch 10, 11, trunk added
- Fix Committed on Branch deleted (
9.9) - Platforms .NET, Java added
Patch committed on 10.x, 11.x, and 12.x branches.
Updated by Michael Kay over 2 years ago
Note: I think bug #4610 fixed the problem for the case where the reduction of the predicate to false()
happened during the typecheck phase, but not when it happened during the optimize()
phase.
Updated by Debbie Lockett over 2 years ago
- Fixed in Maintenance Release deleted (
10.0)
Updated by Debbie Lockett over 2 years ago
- Fixed in Maintenance Release 10.7 added
Bug fix applied in the Saxon 10.7 maintenance release. (Leaving open awaiting Saxon 11 maintenance release.)
Updated by Clément Fournier over 2 years ago
Thanks for the quick reaction! I understand I should probably use the s9api instead of this legacy API... For optimization purposes though it's really nice to be able to bind variables at compile-time. Are there any plans to add support for that?
Updated by O'Neil Delpratt over 2 years ago
- Status changed from Resolved to Closed
- Fixed in Maintenance Release 11.3 added
- Fixed in Maintenance Release deleted (
10.7)
Bug fix applied in the Saxon 11.3 maintenance release.
Updated by O'Neil Delpratt over 2 years ago
- Fixed in Maintenance Release 10.7 added
Please register to edit this issue