SERVER-124174 Replace FLE2 prefix/suffix preview types with GA types in jstests and unit tests (#52170)
GitOrigin-RevId: 1f47137fd5a87dc5545c3904cdc5b8d7b32abb7e
This commit is contained in:
parent
ae4b3b02be
commit
d304172308
@ -1,10 +1,12 @@
|
||||
import {FeatureFlagUtil} from "jstests/libs/feature_flag_util.js";
|
||||
class TextFieldBase {
|
||||
constructor(lb, ub, caseSensitive, diacriticSensitive, maxContention) {
|
||||
constructor(lb, ub, caseSensitive, diacriticSensitive, maxContention, forcePreview = false) {
|
||||
this._lb = NumberInt(lb);
|
||||
this._ub = NumberInt(ub);
|
||||
this._caseSensitive = caseSensitive;
|
||||
this._diacriticSensitive = diacriticSensitive;
|
||||
this._cm = NumberLong(maxContention);
|
||||
this._forcePreview = forcePreview;
|
||||
}
|
||||
createQueryTypeDescriptor() {
|
||||
return {
|
||||
@ -18,10 +20,12 @@ class TextFieldBase {
|
||||
}
|
||||
|
||||
export class SuffixField extends TextFieldBase {
|
||||
createQueryTypeDescriptor() {
|
||||
// Use the deprecated "suffixPreview" name for mongocrypt compatibility.
|
||||
// TODO SERVER-123416 Change to "suffix" once libmongocrypt supports the new name.
|
||||
return Object.assign({"queryType": "suffixPreview"}, super.createQueryTypeDescriptor());
|
||||
createQueryTypeDescriptor(db) {
|
||||
let queryType = "suffix";
|
||||
if (this._forcePreview || (db && !FeatureFlagUtil.isPresentAndEnabled(db.getMongo(), "QEPrefixSuffixSearch"))) {
|
||||
queryType = "suffixPreview";
|
||||
}
|
||||
return Object.assign({"queryType": queryType}, super.createQueryTypeDescriptor());
|
||||
}
|
||||
|
||||
calculateExpectedTagCount(byte_len) {
|
||||
@ -61,11 +65,12 @@ export class SuffixField extends TextFieldBase {
|
||||
}
|
||||
|
||||
export class PrefixField extends SuffixField {
|
||||
createQueryTypeDescriptor() {
|
||||
let spec = super.createQueryTypeDescriptor();
|
||||
// Use the deprecated "prefixPreview" name for mongocrypt compatibility.
|
||||
// TODO SERVER-123416 Change to "prefix" once libmongocrypt supports the new name.
|
||||
spec.queryType = "prefixPreview";
|
||||
createQueryTypeDescriptor(db) {
|
||||
let spec = super.createQueryTypeDescriptor(db);
|
||||
spec.queryType = "prefix";
|
||||
if (this._forcePreview || (db && !FeatureFlagUtil.isPresentAndEnabled(db.getMongo(), "QEPrefixSuffixSearch"))) {
|
||||
spec.queryType = "prefixPreview";
|
||||
}
|
||||
return spec;
|
||||
}
|
||||
|
||||
@ -91,12 +96,12 @@ export class PrefixField extends SuffixField {
|
||||
}
|
||||
|
||||
export class SubstringField extends TextFieldBase {
|
||||
constructor(mlen, lb, ub, caseSensitive, diacriticSensitive, maxContention) {
|
||||
super(lb, ub, caseSensitive, diacriticSensitive, maxContention);
|
||||
constructor(mlen, lb, ub, caseSensitive, diacriticSensitive, maxContention, forcePreview = false) {
|
||||
super(lb, ub, caseSensitive, diacriticSensitive, maxContention, forcePreview);
|
||||
this._mlen = NumberInt(mlen);
|
||||
}
|
||||
|
||||
createQueryTypeDescriptor() {
|
||||
createQueryTypeDescriptor(db) {
|
||||
return Object.assign(
|
||||
{"queryType": "substringPreview", "strMaxLength": this._mlen},
|
||||
super.createQueryTypeDescriptor(),
|
||||
@ -154,12 +159,26 @@ export class SubstringField extends TextFieldBase {
|
||||
}
|
||||
|
||||
export class SuffixAndPrefixField {
|
||||
constructor(sfxLb, sfxUb, pfxLb, pfxUb, caseSensitive, diacriticSensitive, maxContention) {
|
||||
this._suffixField = new SuffixField(sfxLb, sfxUb, caseSensitive, diacriticSensitive, maxContention);
|
||||
this._prefixField = new PrefixField(pfxLb, pfxUb, caseSensitive, diacriticSensitive, maxContention);
|
||||
constructor(sfxLb, sfxUb, pfxLb, pfxUb, caseSensitive, diacriticSensitive, maxContention, forcePreview = false) {
|
||||
this._suffixField = new SuffixField(
|
||||
sfxLb,
|
||||
sfxUb,
|
||||
caseSensitive,
|
||||
diacriticSensitive,
|
||||
maxContention,
|
||||
forcePreview,
|
||||
);
|
||||
this._prefixField = new PrefixField(
|
||||
pfxLb,
|
||||
pfxUb,
|
||||
caseSensitive,
|
||||
diacriticSensitive,
|
||||
maxContention,
|
||||
forcePreview,
|
||||
);
|
||||
}
|
||||
createQueryTypeDescriptor() {
|
||||
return [this._suffixField.createQueryTypeDescriptor(), this._prefixField.createQueryTypeDescriptor()];
|
||||
createQueryTypeDescriptor(db) {
|
||||
return [this._suffixField.createQueryTypeDescriptor(db), this._prefixField.createQueryTypeDescriptor(db)];
|
||||
}
|
||||
calculateExpectedTagCount(byte_len) {
|
||||
// subtract 1 since the exact match string is doubly counted in the other call
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Test downgrade to incompatible versions is blocked if substringPreview,
|
||||
* suffix, or prefix query types are being used in a FLE2 collection.
|
||||
* suffixPreview, or prefixPreview query types are being used in a FLE2 collection.
|
||||
*/
|
||||
import "jstests/multiVersion/libs/multi_rs.js";
|
||||
|
||||
@ -9,10 +9,12 @@ import {PrefixField, SubstringField, SuffixAndPrefixField, SuffixField} from "js
|
||||
import {ReplSetTest} from "jstests/libs/replsettest.js";
|
||||
|
||||
const dbName = "qe_text_downgrade_test";
|
||||
const substrField = new SubstringField(20, 2, 10, false, false, 1);
|
||||
const suffixField = new SuffixField(2, 5, true, false, 1);
|
||||
const prefixField = new PrefixField(2, 5, false, true, 1);
|
||||
const comboField = new SuffixAndPrefixField(2, 5, 2, 5, false, false, 1);
|
||||
// TODO: SERVER-123416 test downgrade also prevented by the existence of non-preview types.
|
||||
const forcePreview = true;
|
||||
const substrField = new SubstringField(20, 2, 10, false, false, 1, forcePreview);
|
||||
const suffixField = new SuffixField(2, 5, true, false, 1, forcePreview);
|
||||
const prefixField = new PrefixField(2, 5, false, true, 1, forcePreview);
|
||||
const comboField = new SuffixAndPrefixField(2, 5, 2, 5, false, false, 1, forcePreview);
|
||||
|
||||
function testBinaryDowngrade(queryTypeConfig) {
|
||||
jsTestLog("Testing downgrade from latest to last-lts");
|
||||
|
||||
@ -58,6 +58,8 @@ static void accumulateStats(ECOCStats& left, const ECOCStats& right) {
|
||||
static void accumulateStats(FLEIndexTypeStats& left, const FLEIndexTypeStats& right) {
|
||||
left.setEquality(left.getEquality() + right.getEquality());
|
||||
left.setRange(left.getRange() + right.getRange());
|
||||
left.setSuffix(left.getSuffix() + right.getSuffix());
|
||||
left.setPrefix(left.getPrefix() + right.getPrefix());
|
||||
left.setRangePreview(left.getRangePreview() + right.getRangePreview());
|
||||
left.setSubstringPreview(left.getSubstringPreview() + right.getSubstringPreview());
|
||||
left.setSuffixPreview(left.getSuffixPreview() + right.getSuffixPreview());
|
||||
|
||||
@ -175,6 +175,8 @@ TEST_F(FLEStatsTest, IndexTypeStats) {
|
||||
int64_t equality = 0;
|
||||
int64_t unindexed = 0;
|
||||
int64_t range = 0;
|
||||
int64_t suffix = 0;
|
||||
int64_t prefix = 0;
|
||||
int64_t rangePreview = 0;
|
||||
int64_t substringPreview = 0;
|
||||
int64_t suffixPreview = 0;
|
||||
@ -187,6 +189,8 @@ TEST_F(FLEStatsTest, IndexTypeStats) {
|
||||
ASSERT_EQ(actual.getEquality(), expected.equality);
|
||||
ASSERT_EQ(actual.getUnindexed(), expected.unindexed);
|
||||
ASSERT_EQ(actual.getRange(), expected.range);
|
||||
ASSERT_EQ(actual.getSuffix(), expected.suffix);
|
||||
ASSERT_EQ(actual.getPrefix(), expected.prefix);
|
||||
ASSERT_EQ(actual.getRangePreview(), expected.rangePreview);
|
||||
ASSERT_EQ(actual.getSubstringPreview(), expected.substringPreview);
|
||||
ASSERT_EQ(actual.getSuffixPreview(), expected.suffixPreview);
|
||||
@ -203,15 +207,18 @@ TEST_F(FLEStatsTest, IndexTypeStats) {
|
||||
for (auto i = count; i > 0; i--) {
|
||||
fields.emplace_back(keyId, indexType);
|
||||
}
|
||||
} else if (indexType == "multi") {
|
||||
} else if (indexType == "multi" || indexType == "multiPreview") {
|
||||
auto suffixType = (indexType == "multi") ? R"({"queryType": "suffix"})"
|
||||
: R"({"queryType": "suffixPreview"})";
|
||||
auto prefixType = (indexType == "multi") ? R"({"queryType": "prefix"})"
|
||||
: R"({"queryType": "prefixPreview"})";
|
||||
|
||||
for (auto i = count; i > 0; i--) {
|
||||
fields.emplace_back(keyId, indexType);
|
||||
|
||||
std::vector<QueryTypeConfig> queries;
|
||||
queries.push_back(
|
||||
QueryTypeConfig::parse(fromjson(R"({"queryType": "suffixPreview"})")));
|
||||
queries.push_back(
|
||||
QueryTypeConfig::parse(fromjson(R"({"queryType": "prefixPreview"})")));
|
||||
queries.push_back(QueryTypeConfig::parse(fromjson(suffixType)));
|
||||
queries.push_back(QueryTypeConfig::parse(fromjson(prefixType)));
|
||||
|
||||
fields.back().setQueries(
|
||||
std::variant<std::vector<QueryTypeConfig>, QueryTypeConfig>(
|
||||
@ -237,7 +244,7 @@ TEST_F(FLEStatsTest, IndexTypeStats) {
|
||||
IndexTypeCounters expected;
|
||||
assertCounters(expected);
|
||||
|
||||
auto efc1 = buildConfig({{"unindexed", 4}, {"equality", 2}, {"multi", 3}});
|
||||
auto efc1 = buildConfig({{"unindexed", 4}, {"equality", 2}, {"multiPreview", 3}});
|
||||
instance->updateIndexTypeStatsOnRegisterCollection(efc1);
|
||||
expected.unindexed++;
|
||||
expected.equality++;
|
||||
@ -255,7 +262,8 @@ TEST_F(FLEStatsTest, IndexTypeStats) {
|
||||
auto efc3 = buildConfig({{"suffixPreview", 1}, {"multi", 1}});
|
||||
instance->updateIndexTypeStatsOnRegisterCollection(efc3);
|
||||
expected.suffixPreview++;
|
||||
expected.prefixPreview++;
|
||||
expected.suffix++;
|
||||
expected.prefix++;
|
||||
assertCounters(expected);
|
||||
|
||||
instance->updateIndexTypeStatsOnDeregisterCollection(efc2);
|
||||
@ -266,12 +274,14 @@ TEST_F(FLEStatsTest, IndexTypeStats) {
|
||||
|
||||
instance->updateIndexTypeStatsOnRegisterCollection(efc3);
|
||||
expected.suffixPreview++;
|
||||
expected.prefixPreview++;
|
||||
expected.suffix++;
|
||||
expected.prefix++;
|
||||
assertCounters(expected);
|
||||
|
||||
instance->updateIndexTypeStatsOnDeregisterCollection(efc3);
|
||||
expected.suffixPreview--;
|
||||
expected.prefixPreview--;
|
||||
expected.suffix--;
|
||||
expected.prefix--;
|
||||
assertCounters(expected);
|
||||
|
||||
instance->updateIndexTypeStatsOnDeregisterCollection(efc1);
|
||||
@ -283,7 +293,8 @@ TEST_F(FLEStatsTest, IndexTypeStats) {
|
||||
|
||||
instance->updateIndexTypeStatsOnDeregisterCollection(efc3);
|
||||
expected.suffixPreview--;
|
||||
expected.prefixPreview--;
|
||||
expected.suffix--;
|
||||
expected.prefix--;
|
||||
assertCounters(expected);
|
||||
}
|
||||
|
||||
|
||||
@ -1811,16 +1811,7 @@ EncryptedFieldConfig QETextSearchCrudTest::getEFC() {
|
||||
std::vector<QueryTypeConfig> qtcs;
|
||||
for (const auto& schema : _schemas) {
|
||||
QueryTypeConfig qtc;
|
||||
// Use the deprecated "Preview" query type names when building the EFC that gets
|
||||
// passed to libmongocrypt, since libmongocrypt does not yet recognize the new names.
|
||||
// TODO SERVER-123416 Remove this mapping once libmongocrypt supports "suffix"/"prefix".
|
||||
auto mongocryptType = schema.type;
|
||||
if (mongocryptType == QueryTypeEnum::Suffix) {
|
||||
mongocryptType = QueryTypeEnum::SuffixPreviewDeprecated;
|
||||
} else if (mongocryptType == QueryTypeEnum::Prefix) {
|
||||
mongocryptType = QueryTypeEnum::PrefixPreviewDeprecated;
|
||||
}
|
||||
qtc.setQueryType(mongocryptType);
|
||||
qtc.setQueryType(schema.type);
|
||||
if (schema.type == QueryTypeEnum::SubstringPreview) {
|
||||
qtc.setStrMaxLength(schema.mlen);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user