exist icon indicating copy to clipboard operation
exist copied to clipboard

XPath expression ending with concat returns incorrect result when applied to an empty sequence

Open paulmer opened this issue 3 years ago • 2 comments

Describe the bug The following code returns a non-empty sequence of a single item instead of the expected empty sequence:

let $n  := ()
return $n//@a/concat('@', local-name(.), "=", ./string())

The result is:

"@="

Saxon returns the correct result, as does this expression:

(let $n  := ()
return $n//@a) ! concat('@', local-name(.), "=", ./string())

Expected behavior See above.

To Reproduce

This test reports the error:

xquery version "3.1";

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

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

declare
    %test:assertTrue
function t:test() {
    let $n  := ()
    let $result := $n//@a/concat('@', local-name(.), "=", ./string())
    return
       count($result) eq 0
};


Context (please always complete the following information):

  • OS: Mac OS 11, RHEL 7
  • eXist-db version: 5.2
  • Java Version java 11.0.8 2020-07-14 LTS

Additional context

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

paulmer avatar Feb 24 '21 13:02 paulmer

I can confirm the report using 5.3.0-SNAPSHOT. A slightly reduced test:

()/concat(., "foo")

... returns "foo" instead of empty-sequence(). Similarly, (h/t to Jean-Paul Rehr):

() => concat("foo")

... returns "foo".

The xqsuite:

xquery version "3.1";

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

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

declare
    %test:assertEmpty
function t:empty-sequence-path-op() {
    ()/concat(., "foo")
};

declare
    %test:assertEmpty
function t:empty-sequence-arrow-op() {
    () => concat("foo")
};

... returns:

<testsuite package="http://exist-db.org/xquery/test" tests="2" failures="2" errors="0" pending="0">
    <testcase name="empty-sequence-arrow-op" class="t:empty-sequence-arrow-op">
        <failure message="assertEmpty failed." type="failure-error-code-1"/>
        <output>foo</output>
    </testcase>
    <testcase name="empty-sequence-path-op" class="t:empty-sequence-path-op">
        <failure message="assertEmpty failed." type="failure-error-code-1"/>
        <output>foo</output>
    </testcase>
</testsuite>

The part of the report involving the simple map operator doesn't indicate a problem, as eXist also returns the correct result for that expression.

joewiz avatar Feb 24 '21 14:02 joewiz

BaseX also returns the correct result. Its compiling note for the query:

rewrite mixed path to empty sequence: ()/concat(., "foo") -> ()

joewiz avatar Feb 24 '21 14:02 joewiz