Skip to content

Commit 23a4823

Browse files
authored
Merge pull request #3738 from evolvedbinary/hotfix/map-mutability
Switch map:merge from use-last to use-first as per XQuery spec
2 parents d9be168 + a05df92 commit 23a4823

File tree

3 files changed

+15
-30
lines changed

3 files changed

+15
-30
lines changed

exist-core/src/main/java/org/exist/xquery/functions/map/AbstractMapType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,4 +241,4 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro
241241
return map.get((AtomicValue) args[0].itemAt(0));
242242
}
243243
}
244-
}
244+
}

exist-core/src/main/java/org/exist/xquery/functions/map/MapFunction.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,12 +259,10 @@ private Sequence merge(final Sequence[] args) throws XPathException {
259259
throw new XPathException(this, ErrorCodes.FOJS0005, "value for duplicates key was not recognised: " + mapValue.getStringValue());
260260
}
261261
} else {
262-
// TODO(AR) the XQ3.1 spec says that the default for fn:merge#2 should be USE_FIRST... this needs to be revised in a major release of eXist-db
263-
mergeDuplicates = MergeDuplicates.USE_LAST;
262+
mergeDuplicates = MergeDuplicates.USE_FIRST;
264263
}
265264
} else {
266-
// TODO(AR) the XQ3.1 spec says that the default for fn:merge#1 should be USE_FIRST... this needs to be revised in a major release of eXist-db
267-
mergeDuplicates = MergeDuplicates.USE_LAST;
265+
mergeDuplicates = MergeDuplicates.USE_FIRST;
268266
}
269267

270268
final Sequence maps = args[0];

exist-core/src/test/xquery/maps/maps.xqm

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -196,23 +196,17 @@ function mt:createWithSingleKey() {
196196
$map("Su")
197197
};
198198

199-
(:~
200-
: TODO(AR) implicit behaviour of map:merge according to XQ3.1 specification should be use-first not use-last
201-
:)
202199
declare
203-
%test:assertEquals("Saturday", "Caturday")
204-
function mt:merge-duplicate-keys-use-last-implicit-1() {
200+
%test:assertEquals("Saturday", "Saturday")
201+
function mt:merge-duplicate-keys-use-first-implicit-1() {
205202
let $specialWeek := map:merge(($mt:integerKeys, map { 7 : "Caturday" }))
206203
return
207204
($mt:integerKeys(7), $specialWeek(7))
208205
};
209206

210-
(:~
211-
: TODO(AR) implicit behaviour of map:merge according to XQ3.1 specification should be use-first not use-last
212-
:)
213207
declare
214-
%test:assertEquals("Saturday", "Saturday")
215-
function mt:merge-duplicate-keys-use-last-implicit-2() {
208+
%test:assertEquals("Saturday", "Caturday")
209+
function mt:merge-duplicate-keys-use-first-implicit-2() {
216210
let $specialWeek := map:merge((map { 7 : "Caturday" }, $mt:integerKeys))
217211
return
218212
($mt:integerKeys(7), $specialWeek(7))
@@ -588,10 +582,10 @@ declare
588582
%test:assertEquals(3)
589583
%test:args("Three")
590584
%test:assertEmpty
591-
function mt:doubleKeys($key as item()) {
585+
function mt:double-keys($key as item()) {
592586
let $map := map { xs:double(1.1) : 1, xs:double(2) : 2 }
593587
return
594-
map:merge(($map, map:entry(xs:double(2), 3)))($key)
588+
map:merge((map:entry(xs:double(2), 3), $map))($key)
595589
};
596590

597591
declare
@@ -797,7 +791,7 @@ declare
797791
function mt:immutable-put-then-merge() {
798792
let $extended := map:put(mt:create-test-map(), $mt:test-key-two, false())
799793
let $expected := $extended($mt:test-key-one)
800-
let $result := map:merge(($extended, map { $mt:test-key-one : false() }))
794+
let $result := map:merge((map { $mt:test-key-one : false() }, $extended))
801795
return
802796
(
803797
$expected eq $extended($mt:test-key-one),
@@ -839,7 +833,7 @@ declare
839833
function mt:immutable-remove-then-merge() {
840834
let $removed := map:remove(mt:create-test-map(), $mt:test-key-two)
841835
let $expected := $removed($mt:test-key-one)
842-
let $result := map:merge(($removed, map { $mt:test-key-one : false() }))
836+
let $result := map:merge((map { $mt:test-key-one : false() }, $removed))
843837
return
844838
(
845839
$expected eq $removed($mt:test-key-one),
@@ -880,7 +874,7 @@ declare
880874
function mt:immutable-merge-then-merge() {
881875
let $merged := map:merge(mt:create-test-map())
882876
let $expected := $merged($mt:test-key-one)
883-
let $result := map:merge(($merged, map { $mt:test-key-one : false() }))
877+
let $result := map:merge((map { $mt:test-key-one : false() }, $merged))
884878
return
885879
(
886880
$expected eq $merged($mt:test-key-one),
@@ -916,12 +910,8 @@ function mt:immutable-merge2-then-remove() {
916910
)
917911
};
918912

919-
(:~
920-
: TODO(AR) implicit behaviour of map:merge according to XQ3.1 specification should be use-first not use-last,
921-
: therefore the result should be ("true", "true") instead
922-
:)
923913
declare
924-
%test:assertEquals("true", "false")
914+
%test:assertEquals("true", "true")
925915
function mt:immutable-merge2-then-merge() {
926916
let $merged := map:merge((mt:create-test-map(), mt:create-test-map2()))
927917
let $expected := $merged($mt:test-key-one)
@@ -932,6 +922,7 @@ function mt:immutable-merge2-then-merge() {
932922
$expected ne $result($mt:test-key-one)
933923
)
934924
};
925+
935926
declare
936927
%test:assertEquals("true", "true")
937928
function mt:immutable-merge-duplicates-then-put() {
@@ -960,12 +951,8 @@ function mt:immutable-merge-duplicates-then-remove() {
960951
)
961952
};
962953

963-
(:~
964-
: TODO(AR) implicit behaviour of map:merge according to XQ3.1 specification should be use-first not use-last,
965-
: therefore the result should be ("true", "true") instead
966-
:)
967954
declare
968-
%test:assertEquals("true", "false")
955+
%test:assertEquals("true", "true")
969956
function mt:immutable-merge-duplicates-then-merge() {
970957
let $merged := map:merge((mt:create-test-map(), mt:create-test-map()))
971958
let $expected := $merged($mt:test-key-one)

0 commit comments

Comments
 (0)