When the intersect expression is called on elements stored in the database, eXist throws the following unexpected error on functions whose signatures indicate their return type must be element():
Return type of function name_of_function. exerr:ERROR Type error: expected type: element(); got: node()
When called on elements, the intersect expression should not cause functions that expect to return an element to throw an error.
To Reproduce
The following xqsuite tests the effect of intersect on nodes stored in the database and in memory. It shows that a bug affects intersect when used on nodes stored in the database, when functions declare that they return element(). The bug is not exhibited with affect in-memory nodes.
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 {
<root>
<x/>
<y/>
<z/>
</root>
};
declare
%test:setUp
function t:setup() {
let $testCol := xmldb:create-collection("/db", "test")
return
xmldb:store($testCol, "test.xml", $t:XML)
};
declare
%test:tearDown
function t:tearDown() {
xmldb:remove("/db/test")
};
declare
%test:assertEquals("<y/>")
function t:intersect-no-return-type-db() {
let $root := doc("/db/test/test.xml")/root
let $seq1 := ($root/x, $root/y)
let $seq2 := ($root/y, $root/z)
let $intersect := $seq1 intersect $seq2
return
$intersect
};
declare
%test:assertEquals("<y/>")
function t:intersect-element-return-type-db() as element() {
let $root := doc("/db/test/test.xml")/root
let $seq1 := ($root/x, $root/y)
let $seq2 := ($root/y, $root/z)
let $intersect := $seq1 intersect $seq2
return
$intersect
};
declare
%test:assertEquals("<y/>")
function t:intersect-no-return-type-mem() {
let $root := $t:XML/root
let $seq1 := ($root/x, $root/y)
let $seq2 := ($root/y, $root/z)
let $intersect := $seq1 intersect $seq2
return
$intersect
};
declare
%test:assertEquals("<y/>")
function t:intersect-element-return-type-mem() as element() {
let $root := $t:XML/root
let $seq1 := ($root/x, $root/y)
let $seq2 := ($root/y, $root/z)
let $intersect := $seq1 intersect $seq2
return
$intersect
};
This xqsuite returns the following error:
<testsuite package="http://exist-db.org/xquery/test" timestamp="2022-02-26T01:05:11.139-05:00"
tests="4" failures="0" errors="1" pending="0" time="PT0.002S">
<testcase name="intersect-element-return-type-db" class="t:intersect-element-return-type-db">
<error type="err:XPTY0004"
message="It is a type error if, during the static analysis phase, an expression is found to have a static type that is not appropriate for the context in which the expression occurs, or during the dynamic evaluation phase, the dynamic type of a value does not match a required type as specified by the matching rules in 2.5.4 SequenceType Matching. Return type of function 't:intersect-element-return-type-db'. exerr:ERROR Type error: expected type: element(); got: node()"
/>
</testcase>
<testcase name="intersect-element-return-type-mem" class="t:intersect-element-return-type-mem"/>
<testcase name="intersect-no-return-type-db" class="t:intersect-no-return-type-db"/>
<testcase name="intersect-no-return-type-mem" class="t:intersect-no-return-type-mem"/>
</testsuite>
In my tests, the other constructor expressions—union and except—do not have this problem.
Screenshots
n/a
Context (please always complete the following information):
Digging back into the history of the code, it appears that the code applying "toNodeSet" to the inputs for the case of persistent data (i.e., data stored in the database) was added here:
Describe the bug
When the
intersect
expression is called on elements stored in the database, eXist throws the following unexpected error on functions whose signatures indicate their return type must beelement()
:I believe the error is related to this line in the eXist source code: https://github.com/eXist-db/exist/blob/5bc6a35fd6d4a91742637aefe4ad53c2324284ee/exist-core/src/main/java/org/exist/xquery/Intersect.java#L48
Expected behavior
When called on elements, the
intersect
expression should not cause functions that expect to return an element to throw an error.To Reproduce
The following xqsuite tests the effect of
intersect
on nodes stored in the database and in memory. It shows that a bug affectsintersect
when used on nodes stored in the database, when functions declare that they returnelement()
. The bug is not exhibited with affect in-memory nodes.This xqsuite returns the following error:
In my tests, the other constructor expressions—
union
andexcept
—do not have this problem.Screenshots
n/a
Context (please always complete the following information):
Additional context
conf.xml
? none