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

declare context item should not allow a sequence #4946

Open thvitt opened 1 year ago

thvitt commented 1 year ago

As far as I understand from digging through the XQuery specification, the initial context item declared with declare context item should be a singleton. At least, when declaring a static type, only an ItemType is possible ([31]), and the default type is item(). The relevant specification section 4.17 further states

During query evaluation, a singleton focus is created in the dynamic context for the evaluation of the QueryBody in the main module, and for the initializing expression of every variable declaration in every module. The context item of this singleton focus is called the initial context item, […]

What is the problem

It’s probably more a minor source of confusion than a serious problem.

The following example query:

xquery version "3.1";

declare context item := (document {<test1/>}, document {<test2/>});

<result>{.}</result>

seems to run the query body once on every item in the sequence declared as context item, the result is:

<result>
    <test1/>
</result>
<result>
    <test2/>
</result>

What did you expect

An error, if I understand the spec correctly.

Saxon-HE 9.9.1.5J fails with

Query processing failed: A sequence of more than one item is not allowed as the context item (doc(), doc())

when confronted with the same query.

BaseX 9.7.2 says

Error:
Stopped at /home/tv/basex/file, 3/67:
[XPTY0004] Cannot treat document-node()+ as item(): (document { ... }, document { ... }).

Context information

line-o commented 1 year ago

Basex raises error XPTY0004 as a sequence of length > 1 does not match item().

BaseX 10.6 [Standalone]
Try 'help' to get more information.
> XQUERY declare context item := (document {<test1/>}, document {<test2/>}); <result>{.}</result>
Stopped at *path/to/script*, 1/67:
[XPTY0004] Cannot treat document-node()+ as item(): (document { ... }, document { ... }).\
joewiz commented 1 year ago

I can reproduce the bug with eXist 6.2.0 and 7.0.0-SNAPSHOT.

XQTS has a test for this, contextDecl-033, which we are failing: https://github.com/w3c/qt3tests/blob/master/prod/ContextItemDecl.xml#L198-L205. So I think a PR that shows this test as passing would do the trick.

As a naive attempt at a fix, I tried editing eXist's parser (XQuery.g), changing e1:expr to e1:exprSingle (see 0001-Restrict-context-item-declaration-to-exprSingle.patch). But after recompiling eXist with this change, the sample query failed to raise an error and instead returned the same results as described above.