eXist-db / exist

eXist Native XML Database and Application Platform
https://exist-db.org
GNU Lesser General Public License v2.1
428 stars 179 forks source link

Type error: eXist misreads an XPath node sequence with a predicate as xs:boolean [BUG] #3289

Open ebeshero opened 4 years ago

ebeshero commented 4 years ago

This issue may be related to https://github.com/eXist-db/exist/issues/2159 (where I first posted about it). I'm seeing a buggy error in which eXist seems to be misreading and XPath node sequence as xs:boolean, with this error: "Type error: the sequence cannot be converted into a node set. Item type is xs:boolean." This seems to be a misreading of a certain kind of syntax, which I'll document here.

Context:

I generate the same error when running a query in eXist-dB 4.2.1 and in eXist 5.2. I don't see the error when running the same query in oXygen version 22 with Saxon-HE XQuery 9.9.1.5.

Test File and Query to generate the error

Here is a simple XML test file and a query to generate the error.

1) Here's a simple XML file for the query (from my students, with marked data about dates and times of rocket launches): This contains a couple of elements with attribute nodes holding date-time data.

2) Here's an XQuery script to try (change the doc() function to wherever you're storing the test file.).

xquery version "3.1";
let $testDoc := doc('/db/testQuery/sts135.xml')
let $launchAndLand := $testDoc//*[@*[name() ! contains(., 'DateTime')]]
return $launchAndLand

The error message generated in eXist-db is: exerr:ERROR: Type error: the sequence cannot be converted into a node set. Item type is xs:boolean

ebeshero commented 4 years ago

I've also been testing a little further some combinations in oXygen with Saxon-HE XQuery 9.9.1.5

1) This (probably quite properly) doesn't work anywhere, since several elements contain more than one attribute.

//*[@* ! name() ! contains(., 'DateTime')]

2) This syntax doesn't work in eXist, but does work in oXygen (and this is what I think is a bug):

//*[@*[name() ! contains(., 'DateTime')]]

3) This syntax works in both oXygen and eXist:

//*[@* ! name()[contains(., 'DateTime')]]

also

//*[@*[name()[contains(., 'DateTime')]]]
adamretter commented 4 years ago

@ebeshero I think your problem is similar to #2159 but slightly different. It is likewise a problem with a bad optimisation in predicates and a missing context-item dependency, but the interaction is between the predicate evaluation and expressions other than fn:not.

Again, I think we need input from @wolfgangmm here as I think he authored these optimisations...

line-o commented 4 years ago

Because //*[@* ! name()[contains(., 'DateTime')]] works, it is likely the datatype of the context item that is the problem.

What do you think?

line-o commented 4 years ago

likely related issue https://github.com/eXist-db/exist/issues/3240

line-o commented 4 years ago

//*[@*[contains(name(.), 'DateTime')]] works as well

line-o commented 4 years ago

another working version is //@*[name() ! contains(., 'DateTime')]/.. This is a hint that my previous assumption, the datatype in combination with the simple map operator, cannot be the sole reason.

line-o commented 4 years ago

I agree with @adamretter that optimisation of predicate evaluation is the root-cause of this behaviour.