EE Optimisations introduce bug when dealing with multiple predicates
Optimisations where the order of predicates are significant are introducing bugs for one of my clients between their development environment (Saxon 9.9 PE) and their production server (Saxon 9.9EE).
The example included in the XSL file (attached) is a good example: one predicate restricts to map entries within a map, the second filters by the presence of a map key within the child map. In PE, this works as expected. In EE, parentheses need to be added.
The problem is exacerbated by the way this is reported: unfortunately I can't yet replicate this part in the simplified code attached, but the error is reported as "E [Saxon-EE 10.3] (External): Internal error: no value for variable $vv:v0 at line 30 of file:/....xsl" - worryingly, in 10.3, this error is thrown even with the parentheses in place, even though the parentheses bypass the problem in 9.9 and 10.
The code where this error is thrown occurs in an xsl:iterate statement within another xsl:iterate statement, if that helps.
#2 Updated by Michael Kay 6 months ago
I see the error reported in 10.3 as
Type error at char 58 in expression in xsl:variable/@select on line 25 column 110 of bug-report.xsl: XPTY0004 The items on the LHS of the '?' operator must be maps or arrays; but value (110) was supplied
I think it's perhaps unfortunate that the specification allows predicates to be reordered; it's certainly a reasonable user expectation that the first predicate can be used as a "guard" for the second in this way. But the language spec is explicit that it is allowed: see §2.3.4:
The expression in the following example cannot raise a casting error if it is evaluated exactly as written (i.e., left to right). Since neither predicate depends on the context position, an implementation might choose to reorder the predicates to achieve better performance (for example, by taking advantage of an index). This reordering could cause the expression to raise an error.
$N[@x castable as xs:date][xs:date(@x) gt xs:date("2000-01-01")]
To avoid unexpected errors caused by expression rewrite, tests that are designed to prevent dynamic errors should be expressed using conditional expressions. For example, the above expression can be written as follows:
$N[if (@x castable as xs:date) then xs:date(@x) gt xs:date("2000-01-01") else false()]
Saxon has an experimental extension to help with this use case: in the expression
A andThen B, it's guaranteed that B won't be evaluated unless A is true.
Please register to edit this issue