Hi,
To resume an exchange with BaseX members :
The issue is JAVA Bindings for BAseX version <= 7.7, illustrated by the following XQUERY code
import module namespace set = "java.util.HashSet";{
let $loop := for $i in 1 to 128 return set:add($i)
let $loop := for $i in 1 to 128 return set:add($i) return set:size() }
returning .. 129 (expected 128)
Explanation : (courtesy by Christian Gruen)
- The set:add function is no integer-specific function, so it allows all types of objects as argument. - This is why the XQuery item will not be explicitly cast to an integer; instead, the original Java XQuery Item object will be passed on to the Java function. - In BaseX, the first items of type xs:integer and in the range of 0-127 are cachedhttps://github.com/BaseXdb/basex/blob/master/basex-core/src/main/java/org/basex/query/value/item/Int.java. This means that if an integer like 84 is requested twice, the returned item will have the same reference in memory. - This is different for integers larger than 127: in this case, new references will be created. As XQuery items have nohashCode() function, their memory reference will be used when calculating the hash code.
WorkAround :
preferred : Last Stable Release 7.8 solves the issue.
Other workaround :
- Use the map:module to simulate HashSet (well, I do confess that I do not know how to achieve this)
- wrap the JAVA Class in order to manage directly this issue (by forcing cast operation in your wrapper), then import your wrapper as a module in BAseX