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

[BUG] XQuery bug on selecting nodes with last() #4824

Open Twilight-Shuxin opened 1 year ago

Twilight-Shuxin commented 1 year ago

Describe the bug

Given XML document:

<A1 id="1">
  <B1 id="2"></B1>
</A1>

(No index defined)

and XPath query:

//*[last() <= 1]

Exist db returns empty result set

Expected behavior

Should return

<A1 id="1">
   <B1 id="2"/>
</A1>
<B1 id="2"/>

as BaseX, Saxon and Oracle

To Reproduce

xquery version "3.1";

module namespace t="http://exist-db.org/xquery/test";

declare namespace test="http://exist-db.org/xquery/xqsuite";

declare variable $t:XML := document {
    <A><B></B></A>
};

declare
    %test:setUp
function t:setup() {
    xmldb:create-collection("/db", "test"),
    xmldb:store("/db/test", "test.xml", $t:XML)
};

declare
    %test:tearDown
function t:tearDown() {
    xmldb:remove("/db/test")
};

declare
    %test:assertEquals("2")
function t:test-db() {
    count(
        doc("/db/test/test.xml")//*[last() <= 1]
    )
};
  1. Go to Java admin client
  2. Add XML document to collection
  3. Use find command to execute XPath Query
  4. See error

Context (please always complete the following information)

Additional context

Twilight-Shuxin commented 1 year ago

I'm not very sure whether this is considered to be a bug or not, and might not be a common expression? Therefore it might not be of great importance or require a fix. Thanks!

joewiz commented 1 year ago

I can reproduce these results on 6.2.0.

A bug is a bug! Thank you for your reports!

My hunch is that this report is a variation of the earlier ones, and that solving them will solve this.

line-o commented 1 year ago

It is definitely a valid predicate. I am just not sure what it actually does :)

edit: Maybe it selects all elements, if there are less than 2 selected in the current XPath step.

line-o commented 1 year ago

in saxon <A><B></B></A>//*[last() <= 1] returns <B/>

line-o commented 1 year ago

The results in Saxon are ... mixed https://xqueryfiddle.liberty-development.net/bdxZ98

Twilight-Shuxin commented 1 year ago

Thank you very much!

line-o commented 1 year ago

Christian Grün was so kind to explain to me what //*[somePredicate] actually means.

//*[last()] is a shortcut for /descendant-or-self::node()/child::*[last()]. It will give you the last child of each node of a document.

This can only mean that eXistdb is currently not rewriting the shortcut //* to the correct long form.