mirror of
https://github.com/mongodb/mongo.git
synced 2024-11-21 20:49:10 +01:00
SERVER-93678: Add a shell utility function to compare strings given a collation object (#26234)
GitOrigin-RevId: 6480e21ac48c379052ece62f0efb9e60771cb2ea
This commit is contained in:
parent
84ca7a7728
commit
cfe3e7e4d1
@ -150,6 +150,7 @@ globals:
|
||||
_fnvHashToHexString: true
|
||||
_resultSetsEqualUnordered: true
|
||||
getStringWidth: true
|
||||
_compareStringsWithCollation: true
|
||||
|
||||
# likely could be replaced with `path`
|
||||
_copyFileRange: true
|
||||
|
59
jstests/core/shell/comparisonWithCollation.js
Normal file
59
jstests/core/shell/comparisonWithCollation.js
Normal file
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Tests the shell util '_compareStringsWithCollation'
|
||||
*/
|
||||
|
||||
assert.eq(_compareStringsWithCollation("abc", "abc", {locale: "en_US"}), 0);
|
||||
assert.gt(_compareStringsWithCollation("bcd", "abc", {locale: "en_US"}), 0);
|
||||
assert.lt(_compareStringsWithCollation("abc", "ABC", {locale: "en_US"}), 0);
|
||||
|
||||
// zero length strings and null bytes
|
||||
assert.eq(_compareStringsWithCollation("", "", {locale: "en_US"}), 0);
|
||||
assert.gt(_compareStringsWithCollation("abc", "", {locale: "en_US"}), 0);
|
||||
assert.gt(_compareStringsWithCollation("abc", "", {locale: "en_US", strength: 2}), 0);
|
||||
assert.eq(_compareStringsWithCollation("\0", "", {locale: "en_US"}), 0);
|
||||
assert.lt(_compareStringsWithCollation("\0", "ab", {locale: "en_US"}), 0);
|
||||
assert.gt(_compareStringsWithCollation("a\0c", "a\0b", {locale: "en_US"}), 0);
|
||||
assert.eq(_compareStringsWithCollation("a", "a\0", {locale: "en_US"}), 0);
|
||||
|
||||
// case-level and diatrics
|
||||
assert.eq(_compareStringsWithCollation("abc", "ABC", {locale: "en_US", strength: 1}), 0);
|
||||
assert.eq(_compareStringsWithCollation("abc", "ABC", {locale: "en_US", strength: 2}), 0);
|
||||
assert.lt(_compareStringsWithCollation("abc", "ABC", {locale: "en_US", strength: 3}), 0);
|
||||
assert.lt(
|
||||
_compareStringsWithCollation("abc", "ABC", {locale: "en_US", strength: 1, caseLevel: true}), 0);
|
||||
assert.lt(
|
||||
_compareStringsWithCollation("abc", "ABC", {locale: "en_US", strength: 2, caseLevel: true}), 0);
|
||||
|
||||
assert.eq(_compareStringsWithCollation("eaio", "éáïô", {locale: "en_US", strength: 1}), 0);
|
||||
assert.lt(_compareStringsWithCollation("eaio", "éáïô", {locale: "en_US", strength: 2}), 0);
|
||||
|
||||
assert.gt(_compareStringsWithCollation("abc", "ABC", {locale: "en_US", caseFirst: "upper"}), 0);
|
||||
assert.lt(_compareStringsWithCollation("abc", "ABC", {locale: "en_US", caseFirst: "lower"}), 0);
|
||||
|
||||
// numeric ordering
|
||||
assert.gt(_compareStringsWithCollation("10", "2", {locale: "en_US", numericOrdering: true}), 0);
|
||||
assert.lt(_compareStringsWithCollation("10", "2", {locale: "en_US", numericOrdering: false}), 0);
|
||||
|
||||
// Ignore whitespace and punctuation
|
||||
assert.eq(_compareStringsWithCollation("a b, c", "abc", {locale: "en_US", alternate: "shifted"}),
|
||||
0);
|
||||
assert.neq(_compareStringsWithCollation(
|
||||
"a b, c", "abc", {locale: "en_US", strength: 4, alternate: "shifted"}),
|
||||
0);
|
||||
assert.eq(_compareStringsWithCollation(
|
||||
"a b, c", "abc", {locale: "en_US", alternate: "shifted", maxVariable: "punct"}),
|
||||
0);
|
||||
assert.neq(_compareStringsWithCollation(
|
||||
"a b, c", "abc", {locale: "en_US", alternate: "shifted", maxVariable: "space"}),
|
||||
0);
|
||||
assert.eq(_compareStringsWithCollation(
|
||||
"a b c", "abc", {locale: "en_US", alternate: "shifted", maxVariable: "space"}),
|
||||
0);
|
||||
|
||||
// error cases
|
||||
assert.throwsWithCode(() => _compareStringsWithCollation("", ""), 9367804);
|
||||
assert.throwsWithCode(() => _compareStringsWithCollation(1, "", {locale: "en_US"}), 9367801);
|
||||
assert.throwsWithCode(() => _compareStringsWithCollation("", 1, {locale: "en_US"}), 9367803);
|
||||
assert.throwsWithCode(() => _compareStringsWithCollation({a: ""}, "", {locale: "en_US"}), 9367801);
|
||||
assert.throwsWithCode(() => _compareStringsWithCollation("", "", ""), 9367805);
|
||||
assert.throwsWithCode(() => _compareStringsWithCollation("", "", {}), 40414);
|
@ -116,6 +116,7 @@ env.Library(
|
||||
LIBDEPS_PRIVATE=[
|
||||
"$BUILD_DIR/mongo/bson/util/bson_column",
|
||||
"$BUILD_DIR/mongo/db/auth/security_token_auth",
|
||||
"$BUILD_DIR/mongo/db/query/collation/collator_icu",
|
||||
"$BUILD_DIR/mongo/db/storage/record_store_base",
|
||||
"$BUILD_DIR/mongo/util/icu",
|
||||
"program_runner",
|
||||
|
@ -75,6 +75,7 @@
|
||||
#include "mongo/db/auth/validated_tenancy_scope_factory.h"
|
||||
#include "mongo/db/database_name.h"
|
||||
#include "mongo/db/hasher.h"
|
||||
#include "mongo/db/query/collation/collator_factory_icu.h"
|
||||
#include "mongo/platform/decimal128.h"
|
||||
#include "mongo/platform/mutex.h"
|
||||
#include "mongo/platform/random.h"
|
||||
@ -993,6 +994,36 @@ BSONObj _resultSetsEqualUnordered(const BSONObj& input, void*) {
|
||||
return BSON("" << true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Takes two strings and a valid collation document and returns the comparison result (a number < 0
|
||||
* if 'left' is less than 'right', a number > 0 if 'left' is greater than 'right', and 0 if 'left'
|
||||
* and 'right' are equal) with respect to the collation
|
||||
* Refer to https://www.mongodb.com/docs/manual/reference/collation and
|
||||
* https://unicode-org.github.io/icu/userguide/collation for the expected behaviour when collation
|
||||
* is specified
|
||||
*/
|
||||
BSONObj _compareStringsWithCollation(const BSONObj& input, void*) {
|
||||
BSONObjIterator i(input);
|
||||
|
||||
uassert(9367800, "Expected left argument", i.more());
|
||||
auto left = i.next();
|
||||
uassert(9367801, "Left argument should be a string", left.type() == BSONType::String);
|
||||
|
||||
uassert(9367802, "Expected right argument", i.more());
|
||||
auto right = i.next();
|
||||
uassert(9367803, "Right argument should be string", right.type() == BSONType::String);
|
||||
|
||||
uassert(9367804, "Expected collation argument", i.more());
|
||||
auto collatorSpec = i.next();
|
||||
uassert(9367805, "Expected a collation object", collatorSpec.type() == BSONType::Object);
|
||||
|
||||
CollatorFactoryICU collationFactory;
|
||||
auto collator = uassertStatusOK(collationFactory.makeFromBSON(collatorSpec.Obj()));
|
||||
|
||||
int cmp = collator->compare(left.valueStringData(), right.valueStringData());
|
||||
return BSON("" << cmp);
|
||||
}
|
||||
|
||||
void installShellUtils(Scope& scope) {
|
||||
scope.injectNative("getMemInfo", JSGetMemInfo);
|
||||
scope.injectNative("_createSecurityToken", _createSecurityToken);
|
||||
@ -1016,6 +1047,7 @@ void installShellUtils(Scope& scope) {
|
||||
scope.injectNative("_buildBsonObj", _buildBsonObj);
|
||||
scope.injectNative("_fnvHashToHexString", _fnvHashToHexString);
|
||||
scope.injectNative("_resultSetsEqualUnordered", _resultSetsEqualUnordered);
|
||||
scope.injectNative("_compareStringsWithCollation", _compareStringsWithCollation);
|
||||
|
||||
installShellUtilsLauncher(scope);
|
||||
installShellUtilsExtended(scope);
|
||||
|
Loading…
Reference in New Issue
Block a user