exist icon indicating copy to clipboard operation
exist copied to clipboard

[BUG] XQuery simple node selection return duplicate nodes

Open Twilight-Shuxin opened this issue 2 years ago • 6 comments

Describe the bug

Given XML document:

<A1 id="1">
  <B2 id="2">1</B2>
  <C1 id="3">
    <B2 id="4">1</B2>
  </C1>
</A1>

and XPath query: //*//B2

Exist db returns

<B2 id="2">1</B2>
<B2 id="4">1</B2>
<B2 id="4">1</B2>

Expected behavior

Should return

<B2 id="2">1</B2>
<B2 id="4">1</B2>

as BaseX and Saxon

To Reproduce

  1. Go to Java admin client
  2. Add XML document to collection
  3. Use find command to execute XPath Query
  4. See error (shows there are three hits)

Context (please always complete the following information)

  • Build: latest development version built from source, commit b700a92
  • Java: 17
  • OS: [Windows]

Additional context

  • How is eXist-db installed? Jar installer
  • Any custom changes in e.g. conf.xml? No

Twilight-Shuxin avatar Mar 20 '23 11:03 Twilight-Shuxin

Are there any indexes defined?

dizzzz avatar Mar 20 '23 19:03 dizzzz

I can reproduce this in eXist 6.2.0:

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 {
    <A1 id="1">
        <B2 id="2">1</B2>
        <C1 id="3">
            <B2 id="4">1</B2>
        </C1>
    </A1>
};

declare
    %test:setUp
function t:setup() {
    let $testCol := xmldb:create-collection("/db", "test")
    return
        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() {
    doc("/db/test/test.xml")//*//B2
    => count()
};

The test result showing the failure:

<testsuite errors="0" failures="1" package="http://exist-db.org/xquery/test" pending="0" tests="1"
    time="PT0.002S" timestamp="2023-03-20T16:39:05.398-04:00">
    <testcase class="t:test" name="test">
        <failure message="assertEquals failed." type="failure-error-code-1">2</failure>
        <output>3</output>
    </testcase>
</testsuite>

joewiz avatar Mar 20 '23 20:03 joewiz

@joewiz Thanks for the test case :-)

One request - If you wouldn't mind... Could you avoid arrow operators in your XQSuite tests unless they are absolutely necessary please, as it makes it much easier for me to debug with the Java debugger. Additional things to avoid unless necessary are: maps, arrays, partial functions, higher-order-functions, simple mapping operator, arrow operator, string constructors. Basically the simpler the query (e.g. as close to XQuery 1.0 as possible) the easier it is for me to debug (with the Java debugger).

adamretter avatar Mar 20 '23 21:03 adamretter

Are there any indexes defined?

There is no index defined :)

Twilight-Shuxin avatar Mar 21 '23 02:03 Twilight-Shuxin

@adamretter Good to know! With that in mind, here's a new revision. Besides eliminating the arrow operator, I trimmed the test XML file, and added an in-memory test, which passes.

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/>
        <C>
            <B/>
        </C>
    </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")//*//B
    )
};

declare
    %test:assertEquals("2")
function t:test-mem() {
    count(
        $t:XML//*//B
    )
};

The results:

<testsuite errors="0" failures="1" package="http://exist-db.org/xquery/test" pending="0" tests="2"
    time="PT0.002S" timestamp="2023-03-20T23:24:56.365-04:00">
    <testcase class="t:test-db" name="test-db">
        <failure message="assertEquals failed." type="failure-error-code-1">2</failure>
        <output>3</output>
    </testcase>
    <testcase class="t:test-mem" name="test-mem"/>
</testsuite>

joewiz avatar Mar 21 '23 03:03 joewiz

@adamretter are you actively working on this issue?

line-o avatar Apr 04 '23 11:04 line-o