Bug #2451
closedExceptions from Saxon-EE optimization
100%
Description
Some XQuery similar to this one was mistyped by omitting "or" before the quantified expression:
declare function local:f($x, $y)
{
let $a := $x
where empty($y) (every $i in $x satisfies $i = $y)
return $a
};
local:f("x", ())
The optimizer throws this exception:
java.lang.NullPointerException
at net.sf.saxon.expr.flwor.FLWORExpression.optimize(FLWORExpression.java:558)
at net.sf.saxon.expr.parser.ExpressionVisitor.optimize(ExpressionVisitor.java:244)
at net.sf.saxon.query.XQueryFunction.optimize(XQueryFunction.java:471)
at net.sf.saxon.query.XQueryFunctionLibrary.optimizeGlobalFunctions(XQueryFunctionLibrary.java:326)
at net.sf.saxon.query.QueryModule.optimizeGlobalFunctions(QueryModule.java:1208)
at net.sf.saxon.expr.instruct.Executable.fixupQueryModules(Executable.java:597)
at net.sf.saxon.query.XQueryParser.makeXQueryExpression(XQueryParser.java:159)
at net.sf.saxon.query.StaticQueryContext.compileQuery(StaticQueryContext.java:571)
at net.sf.saxon.query.StaticQueryContext.compileQuery(StaticQueryContext.java:634)
at net.sf.saxon.s9api.XQueryCompiler.compile(XQueryCompiler.java:592)
at net.sf.saxon.Query.compileQuery(Query.java:787)
at net.sf.saxon.Query.doQuery(Query.java:340)
at net.sf.saxon.Query.main(Query.java:111)
With the "or" in place, i.e.
declare function local:f($x, $y)
{
let $a := $x
where empty($y) or (every $i in $x satisfies $i = $y)
return $a
};
local:f("x", ())
there is an exception, too:
java.lang.ClassCastException: net.sf.saxon.expr.Literal cannot be cast to net.sf.saxon.expr.VariableReference
at com.saxonica.ee.optim.IndexedLookupExpression.replaceOperand(IndexedLookupExpression.java:204)
at net.sf.saxon.expr.parser.ExpressionTool.inlineVariableReferences(ExpressionTool.java:1300)
at net.sf.saxon.expr.parser.ExpressionTool.inlineVariableReferences(ExpressionTool.java:1303)
at net.sf.saxon.expr.Assignation.replaceVariable(Assignation.java:470)
at net.sf.saxon.expr.LetExpression.optimize(LetExpression.java:231)
at net.sf.saxon.expr.parser.ExpressionVisitor.optimize(ExpressionVisitor.java:244)
at net.sf.saxon.expr.BinaryExpression.optimize(BinaryExpression.java:90)
at net.sf.saxon.expr.BooleanExpression.optimize(BooleanExpression.java:105)
at net.sf.saxon.expr.OrExpression.optimize(OrExpression.java:55)
at net.sf.saxon.expr.parser.ExpressionVisitor.optimize(ExpressionVisitor.java:244)
at net.sf.saxon.expr.flwor.FLWORExpression$7.processExpression(FLWORExpression.java:490)
at net.sf.saxon.expr.flwor.WhereClause.processSubExpressions(WhereClause.java:111)
at net.sf.saxon.expr.flwor.FLWORExpression.optimize(FLWORExpression.java:488)
at net.sf.saxon.expr.parser.ExpressionVisitor.optimize(ExpressionVisitor.java:244)
at net.sf.saxon.expr.LetExpression.optimize(LetExpression.java:198)
at net.sf.saxon.expr.parser.ExpressionVisitor.optimize(ExpressionVisitor.java:244)
at net.sf.saxon.expr.LetExpression.optimize(LetExpression.java:198)
at net.sf.saxon.expr.parser.ExpressionVisitor.optimize(ExpressionVisitor.java:244)
at com.saxonica.ee.optim.OptimizerEE.tryInlineFunctionCall(OptimizerEE.java:1053)
at net.sf.saxon.expr.UserFunctionCall.optimize(UserFunctionCall.java:343)
at net.sf.saxon.query.XQueryExpression.<init>(XQueryExpression.java:81)
at com.saxonica.ee.optim.XQueryExpressionEE.<init>(XQueryExpressionEE.java:54)
at com.saxonica.config.EnterpriseConfiguration.makeXQueryExpression(EnterpriseConfiguration.java:1526)
at net.sf.saxon.query.XQueryParser.makeXQueryExpression(XQueryParser.java:173)
at net.sf.saxon.query.StaticQueryContext.compileQuery(StaticQueryContext.java:571)
at net.sf.saxon.query.StaticQueryContext.compileQuery(StaticQueryContext.java:634)
at net.sf.saxon.s9api.XQueryCompiler.compile(XQueryCompiler.java:592)
at net.sf.saxon.Query.compileQuery(Query.java:787)
at net.sf.saxon.Query.doQuery(Query.java:340)
at net.sf.saxon.Query.main(Query.java:111)
Tested from command line using Saxon-EE 9.6.0.7J.
Updated by Michael Kay about 9 years ago
- Category set to XQuery conformance
- Status changed from New to In Progress
- Assignee set to Michael Kay
- Found in version changed from Saxon-EE 9.6.0.7J to 9.6
Problem reproduced (in 9.6 branch).
Test case added to QT3 test suite as prod/QuanitifiedExpr/quantexpr-66
Updated by Michael Kay about 9 years ago
Note, I would have expected this to fail with a static type error, on the grounds that empty() cannot return a function item. So there are two problems here: the crash during the optimization phase, and the failure to detect the type error.
The crash during optimization is fairly simple: optimize() is called with contextItemType==null, which is legitimate indicating that the context item is known to be undefined, but the optimize method on FLWORExpression fails to allow for this possibility. The optimize() method has decided that the "where" clause depends on the focus, which at first site seems odd, but that's because it thinks it is dealing with a dynamic function call, and dynamic function calls are capable of calling focus-dependent functions such as position() or last(). Fixed that with a patch to FLWORExpression.optimize().
The failure to detect a static type error is because in cases where the required type is a function type, the code (in TypeChecker.staticTyepCheck()) always attempts run-time function coercion. Clearly there is no point in attempting run-time function coercion unless the supplied value is also a function. This is on a widely used code path and the only impact is quality of diagnostics, so I will not fix this on the 9.6 branch. It is already fixed in 9.7, where the code for dynamic function calls has been simplified and rationalized.
Updated by Michael Kay about 9 years ago
The second problem (with the "or" operator) has been added to QT3 as test quantexpr-67. It fails in 9.6 but not in 9.7. We've had related problems before: the IndexedLookupExpression is used when the optimizer decides it's worth creating an index for a sequence-valued variable, but this goes wrong if the variable is subsequently inlined.
The reason it doesn't fail in 9.7 isn't because the problem has been solved, it's because for some reason we don't generate the IndexedLookupExpression in the first place. What's happening here is that OptimizerEE.optimizeGeneralComparison() does nothing if the supplied expression is a GeneralComparisonEE, presumably on the grounds that no further optimization is possible, and this prevents us reaching the code that looks for the possibility of indexing. The code that causes indexing to be invoked in 9.6 is in GeneralComparisonEE.optimize(), and for some reason this is commented out in 9.7.
Updated by Michael Kay about 9 years ago
Now fixed as far as 9.6 is concerned. I generalized the code for IndexedLookupExpression so it can handle the case where the lhs operator is not a variable reference, on both the interpreted and bytecode paths. (Note, the submitted test cases are insufficient to fully test this, because the query gets optimized out of existence and the run-time execution is trivial).
Updated by Michael Kay about 9 years ago
- Status changed from In Progress to Resolved
Coming back to this, as far as I can see all the issues have been resolved.
Updated by O'Neil Delpratt almost 9 years ago
- Status changed from Resolved to Closed
- % Done changed from 0 to 100
- Fixed in version set to 9.6.0.8
Bug fix applied in the Saxon 9.6.0.8 maintenance release
Updated by O'Neil Delpratt almost 9 years ago
- Applies to branch 9.6 added
- Fix Committed on Branch 9.6 added
- Fixed in Maintenance Release 9.6.0.8 added
Please register to edit this issue