summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Grebennicov <denis.grebennicov@mongodb.com>2022-03-11 12:09:22 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-03-11 19:16:35 +0000
commitc26d169cfe6d0d369b422e7de0c54b68ec8b8ec5 (patch)
tree8c9973dde71c6ea4bdef2ad6781f01c60d97802e
parent14e29b80591ebb1d2a50677f4868827d3b02a7d5 (diff)
downloadmongo-c26d169cfe6d0d369b422e7de0c54b68ec8b8ec5.tar.gz
SERVER-64403 Encode the sort key from a document with collation only if value is present when comparing a sort key from index with one from the document in SORT_MERGE stage.
-rw-r--r--jstests/core/merge_sort_collation.js30
-rw-r--r--src/mongo/db/exec/merge_sort.cpp8
2 files changed, 21 insertions, 17 deletions
diff --git a/jstests/core/merge_sort_collation.js b/jstests/core/merge_sort_collation.js
index a49dffc765a..ae571e43477 100644
--- a/jstests/core/merge_sort_collation.js
+++ b/jstests/core/merge_sort_collation.js
@@ -263,33 +263,33 @@ const testCases = [
// collation of the indexes. Also, the second/third operands to $or queries on fields
// 'e'/'g' that are not covered by the indexes therefore triggers addition of a FETCH stage
// between MERGE_SORT and IXSCAN. This tests comparison of index versus fetched document
- // provided sort keys. In addition to that, some documents have objects as sort attribute
- // values.
+ // provided sort keys. In addition to that, some documents have missing values and objects
+ // as sort attribute values.
indexes: [{a: 1, b: 1, c: 1}, {d: 1, c: 1}, {f: 1, c: 1}],
indexOptions: {collation: {locale: "en", strength: 2}},
filter: {$or: [{a: {$in: ["1", "2"]}, b: "1"}, {d: "3", e: "3"}, {f: "4", g: "3"}]},
sort: {c: 1},
findCollation: {locale: "en", strength: 2},
inputDocuments: [
- {_id: 0, a: "1", b: "1", c: "a"},
- {_id: 1, a: "1", b: "1", c: "d"},
- {_id: 2, a: "2", b: "1", c: "b"},
- {_id: 3, a: "2", b: "1", c: "e"},
- {_id: 6, a: "2", b: "1", c: {a: "B"}},
+ {_id: 0, d: "3", e: "3", c: "a"},
+ {_id: 1, d: "3", e: "3", c: "b"},
+ {_id: 2, d: "3", e: "3"},
+ {_id: 3, d: "3", e: "3", c: {}},
{_id: 4, d: "3", e: "3", c: "c"},
- {_id: 5, d: "3", e: "3", c: "f"},
+ {_id: 5, d: "3", e: "3", c: 1},
+ {_id: 6, a: "2", b: "1", c: {a: "B"}},
{_id: 7, d: "3", e: "3", c: {a: "A"}},
{_id: 8, d: "3", e: "3", c: {a: "C"}},
- {_id: 9, f: "4", g: "3", c: "g"},
+ {_id: 9, f: "4", g: "3", c: "d"},
],
expectedResults: [
- {_id: 0, a: "1", b: "1", c: "a"},
- {_id: 2, a: "2", b: "1", c: "b"},
+ {_id: 2, d: "3", e: "3"},
+ {_id: 5, d: "3", e: "3", c: 1},
+ {_id: 0, d: "3", e: "3", c: "a"},
+ {_id: 1, d: "3", e: "3", c: "b"},
{_id: 4, d: "3", e: "3", c: "c"},
- {_id: 1, a: "1", b: "1", c: "d"},
- {_id: 3, a: "2", b: "1", c: "e"},
- {_id: 5, d: "3", e: "3", c: "f"},
- {_id: 9, f: "4", g: "3", c: "g"},
+ {_id: 9, f: "4", g: "3", c: "d"},
+ {_id: 3, d: "3", e: "3", c: {}},
{_id: 7, d: "3", e: "3", c: {a: "A"}},
{_id: 6, a: "2", b: "1", c: {a: "B"}},
{_id: 8, d: "3", e: "3", c: {a: "C"}},
diff --git a/src/mongo/db/exec/merge_sort.cpp b/src/mongo/db/exec/merge_sort.cpp
index 443a6ed59e1..8520a959475 100644
--- a/src/mongo/db/exec/merge_sort.cpp
+++ b/src/mongo/db/exec/merge_sort.cpp
@@ -207,8 +207,12 @@ bool MergeSortStage::StageWithValueComparison::operator()(const MergingRef& lhs,
// One of the sort key parts was extracted from fetched documents. Encode that part
// using the query's collation.
auto& keyPartFetchedFromDocument = rhsIsFromIndexKey ? lhsElt : rhsElt;
- collationEncodedKeyPart = encodeKeyPartWithCollation(keyPartFetchedFromDocument);
- keyPartFetchedFromDocument = collationEncodedKeyPart.firstElement();
+
+ // Encode the sort key part only if it contains some value.
+ if (keyPartFetchedFromDocument.ok()) {
+ collationEncodedKeyPart = encodeKeyPartWithCollation(keyPartFetchedFromDocument);
+ keyPartFetchedFromDocument = collationEncodedKeyPart.firstElement();
+ }
}
// false means don't compare field name.