Skip to content

Commit 755b06f

Browse files
sgolemon-corpMongoDB Bot
authored and
MongoDB Bot
committed
SERVER-91077 Update FLE Range sparsity/trimFactor defaults (#24158)
GitOrigin-RevId: 7d11c46616c032f426b0635c180374bd7d8c346b
1 parent 936cca7 commit 755b06f

7 files changed

+60
-46
lines changed

src/mongo/crypto/encryption_fields_validation.cpp

+1-7
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,6 @@ uint32_t getNumberOfBitsInDomain(const boost::optional<Decimal128>& min,
167167
}
168168
}
169169

170-
std::int64_t getRangeSparsityDefault() {
171-
// TODO: SERVER-91077 change to a more suitable default value
172-
return 1;
173-
}
174-
175170
std::pair<mongo::Value, mongo::Value> getRangeMinMaxDefaults(BSONType fieldType) {
176171
switch (fieldType) {
177172
case NumberDouble:
@@ -470,10 +465,9 @@ void setRangeDefaults(BSONType fieldType, StringData fieldPath, QueryTypeConfig*
470465
validateRangeIndex(fieldType, fieldPath, query);
471466

472467
auto [defMin, defMax] = getRangeMinMaxDefaults(fieldType);
473-
auto defSparsity = getRangeSparsityDefault();
474468
query.setMin(query.getMin().value_or(defMin));
475469
query.setMax(query.getMax().value_or(defMax));
476-
query.setSparsity(query.getSparsity().value_or(defSparsity));
470+
query.setSparsity(query.getSparsity().value_or(kFLERangeSparsityDefault));
477471
}
478472

479473
} // namespace mongo

src/mongo/crypto/encryption_fields_validation.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ class EncryptedField;
4141
class EncryptedFieldConfig;
4242
class QueryTypeConfig;
4343

44-
constexpr int kFLERangeSparsityDefault = 1;
45-
constexpr int kFLERangeTrimFactorDefault = 0;
44+
constexpr int kFLERangeSparsityDefault = 2;
45+
constexpr int kFLERangeTrimFactorDefault = 6;
4646

4747
/*
4848
* Value: Value to attempt to coerce to field's type.

src/mongo/crypto/fle_crypto.cpp

+40-21
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ extern "C" {
8989
#include "mongo/crypto/aead_encryption.h"
9090
#include "mongo/crypto/encryption_fields_gen.h"
9191
#include "mongo/crypto/encryption_fields_util.h"
92+
#include "mongo/crypto/encryption_fields_validation.h"
9293
#include "mongo/crypto/fle_crypto_predicate.h"
9394
#include "mongo/crypto/fle_data_frames.h"
9495
#include "mongo/crypto/fle_field_schema_gen.h"
@@ -931,7 +932,7 @@ std::unique_ptr<Edges> getEdges(FLE2RangeInsertSpec spec, int sparsity) {
931932
auto element = spec.getValue().getElement();
932933
auto minBound = spec.getMinBound().map([](IDLAnyType m) { return m.getElement(); });
933934
auto maxBound = spec.getMaxBound().map([](IDLAnyType m) { return m.getElement(); });
934-
auto trimFactor = spec.getTrimFactor() ? spec.getTrimFactor().value() : 0;
935+
auto trimFactor = spec.getTrimFactor();
935936

936937
switch (element.type()) {
937938
case BSONType::NumberInt:
@@ -4322,8 +4323,20 @@ bool EncryptedPredicateEvaluatorV2::evaluate(
43224323

43234324
// Edges
43244325

4325-
Edges::Edges(std::string leaf, int sparsity, int trimFactor)
4326-
: _leaf(std::move(leaf)), _sparsity(sparsity), _trimFactor(trimFactor) {
4326+
namespace {
4327+
int resolveTrimFactorDefault(int maxlen, const boost::optional<int>& optTrimFactor) {
4328+
if (optTrimFactor) {
4329+
return *optTrimFactor;
4330+
}
4331+
4332+
return std::clamp(kFLERangeTrimFactorDefault, 0, maxlen - 1);
4333+
}
4334+
} // namespace
4335+
4336+
Edges::Edges(std::string leaf, int sparsity, const boost::optional<int>& optTrimFactor)
4337+
: _leaf(std::move(leaf)),
4338+
_sparsity(sparsity),
4339+
_trimFactor(resolveTrimFactorDefault(_leaf.length(), optTrimFactor)) {
43274340
uassert(6775101, "sparsity must be 1 or larger", _sparsity > 0);
43284341
dassert(std::all_of(_leaf.begin(), _leaf.end(), [](char c) { return c == '1' || c == '0'; }));
43294342
uassert(8574105,
@@ -4370,7 +4383,8 @@ std::size_t Edges::size() const {
43704383
}
43714384

43724385
template <typename T>
4373-
std::unique_ptr<Edges> getEdgesT(T value, T min, T max, int sparsity, int trimFactor) {
4386+
std::unique_ptr<Edges> getEdgesT(
4387+
T value, T min, T max, int sparsity, const boost::optional<int>& trimFactor) {
43744388
static_assert(!std::numeric_limits<T>::is_signed);
43754389
static_assert(std::numeric_limits<T>::is_integer);
43764390

@@ -4388,7 +4402,7 @@ std::unique_ptr<Edges> getEdgesInt32(int32_t value,
43884402
boost::optional<int32_t> min,
43894403
boost::optional<int32_t> max,
43904404
int sparsity,
4391-
int trimFactor) {
4405+
const boost::optional<int>& trimFactor) {
43924406
auto aost = getTypeInfo32(value, min, max);
43934407
return getEdgesT(aost.value, aost.min, aost.max, sparsity, trimFactor);
43944408
}
@@ -4397,7 +4411,7 @@ std::unique_ptr<Edges> getEdgesInt64(int64_t value,
43974411
boost::optional<int64_t> min,
43984412
boost::optional<int64_t> max,
43994413
int sparsity,
4400-
int trimFactor) {
4414+
const boost::optional<int>& trimFactor) {
44014415
auto aost = getTypeInfo64(value, min, max);
44024416
return getEdgesT(aost.value, aost.min, aost.max, sparsity, trimFactor);
44034417
}
@@ -4407,7 +4421,7 @@ std::unique_ptr<Edges> getEdgesDouble(double value,
44074421
boost::optional<double> max,
44084422
boost::optional<uint32_t> precision,
44094423
int sparsity,
4410-
int trimFactor) {
4424+
const boost::optional<int>& trimFactor) {
44114425
auto aost = getTypeInfoDouble(value, min, max, precision);
44124426
return getEdgesT(aost.value, aost.min, aost.max, sparsity, trimFactor);
44134427
}
@@ -4417,7 +4431,7 @@ std::unique_ptr<Edges> getEdgesDecimal128(Decimal128 value,
44174431
boost::optional<Decimal128> max,
44184432
boost::optional<uint32_t> precision,
44194433
int sparsity,
4420-
int trimFactor) {
4434+
const boost::optional<int>& trimFactor) {
44214435
auto aost = getTypeInfoDecimal128(value, min, max, precision);
44224436
return getEdgesT(aost.value, aost.min, aost.max, sparsity, trimFactor);
44234437
}
@@ -4427,7 +4441,7 @@ std::uint64_t getEdgesLength(BSONType fieldType, StringData fieldPath, QueryType
44274441
setRangeDefaults(fieldType, fieldPath, &config);
44284442

44294443
const auto sparsity = *config.getSparsity();
4430-
const auto trimFactor = config.getTrimFactor().get_value_or(0);
4444+
const auto trimFactor = config.getTrimFactor();
44314445
auto precision = config.getPrecision().map(
44324446
[](auto signedInt) -> uint32_t { return static_cast<uint32_t>(signedInt); });
44334447

@@ -4473,20 +4487,21 @@ template <typename T>
44734487
class MinCoverGenerator {
44744488
public:
44754489
static std::vector<std::string> minCover(
4476-
T lowerBound, T upperBound, T max, int sparsity, int trimFactor) {
4490+
T lowerBound, T upperBound, T max, int sparsity, const boost::optional<int>& trimFactor) {
44774491
MinCoverGenerator<T> mcg(lowerBound, upperBound, max, sparsity, trimFactor);
44784492
std::vector<std::string> c;
44794493
mcg.minCoverRec(c, 0, mcg._maxlen);
44804494
return c;
44814495
}
44824496

44834497
private:
4484-
MinCoverGenerator(T lowerBound, T upperBound, T max, int sparsity, int trimFactor)
4498+
MinCoverGenerator(
4499+
T lowerBound, T upperBound, T max, int sparsity, const boost::optional<int>& optTrimFactor)
44854500
: _lowerBound(lowerBound),
44864501
_upperBound(upperBound),
44874502
_sparsity(sparsity),
4488-
_trimFactor(trimFactor),
4489-
_maxlen(getFirstBitSet(max)) {
4503+
_maxlen(getFirstBitSet(max)),
4504+
_trimFactor(resolveTrimFactorDefault(_maxlen, optTrimFactor)) {
44904505
static_assert(!std::numeric_limits<T>::is_signed);
44914506
static_assert(std::numeric_limits<T>::is_integer);
44924507
tassert(6860001,
@@ -4496,7 +4511,7 @@ class MinCoverGenerator {
44964511
uassert(8574106,
44974512
"Trim factor must be >= 0 and less than the number of bits used to represent an "
44984513
"element of the domain",
4499-
trimFactor >= 0 && (trimFactor == 0 || trimFactor < _maxlen));
4514+
_trimFactor >= 0 && (_trimFactor == 0 || _trimFactor < _maxlen));
45004515
}
45014516

45024517
// Generate and apply a mask to an integer, filling masked bits with 1;
@@ -4560,13 +4575,17 @@ class MinCoverGenerator {
45604575
T _lowerBound;
45614576
T _upperBound;
45624577
int _sparsity;
4563-
int _trimFactor;
45644578
int _maxlen;
4579+
int _trimFactor;
45654580
};
45664581

45674582
template <typename T>
4568-
std::vector<std::string> minCover(
4569-
T lowerBound, T upperBound, T min, T max, int sparsity, int trimFactor) {
4583+
std::vector<std::string> minCover(T lowerBound,
4584+
T upperBound,
4585+
T min,
4586+
T max,
4587+
int sparsity,
4588+
const boost::optional<int>& trimFactor) {
45704589
dassert(0 == min);
45714590
return MinCoverGenerator<T>::minCover(lowerBound, upperBound, max, sparsity, trimFactor);
45724591
}
@@ -4604,7 +4623,7 @@ std::vector<std::string> minCoverInt32(int32_t lowerBound,
46044623
boost::optional<int32_t> min,
46054624
boost::optional<int32_t> max,
46064625
int sparsity,
4607-
int trimFactor) {
4626+
const boost::optional<int>& trimFactor) {
46084627
auto a = getTypeInfo32(lowerBound, min, max);
46094628
auto b = getTypeInfo32(upperBound, min, max);
46104629
dassert(a.min == b.min);
@@ -4623,7 +4642,7 @@ std::vector<std::string> minCoverInt64(int64_t lowerBound,
46234642
boost::optional<int64_t> min,
46244643
boost::optional<int64_t> max,
46254644
int sparsity,
4626-
int trimFactor) {
4645+
const boost::optional<int>& trimFactor) {
46274646
auto a = getTypeInfo64(lowerBound, min, max);
46284647
auto b = getTypeInfo64(upperBound, min, max);
46294648
dassert(a.min == b.min);
@@ -4643,7 +4662,7 @@ std::vector<std::string> minCoverDouble(double lowerBound,
46434662
boost::optional<double> max,
46444663
boost::optional<uint32_t> precision,
46454664
int sparsity,
4646-
int trimFactor) {
4665+
const boost::optional<int>& trimFactor) {
46474666
auto a = getTypeInfoDouble(lowerBound, min, max, precision);
46484667
auto b = getTypeInfoDouble(upperBound, min, max, precision);
46494668
dassert(a.min == b.min);
@@ -4662,7 +4681,7 @@ std::vector<std::string> minCoverDecimal128(Decimal128 lowerBound,
46624681
boost::optional<Decimal128> max,
46634682
boost::optional<uint32_t> precision,
46644683
int sparsity,
4665-
int trimFactor) {
4684+
const boost::optional<int>& trimFactor) {
46664685
auto a = getTypeInfoDecimal128(lowerBound, min, max, precision);
46674686
auto b = getTypeInfoDecimal128(upperBound, min, max, precision);
46684687
dassert(a.min == b.min);

src/mongo/crypto/fle_crypto.h

+9-9
Original file line numberDiff line numberDiff line change
@@ -1503,7 +1503,7 @@ struct ParsedFindRangePayload {
15031503

15041504
class Edges {
15051505
public:
1506-
Edges(std::string leaf, int sparsity, int trimFactor);
1506+
Edges(std::string leaf, int sparsity, const boost::optional<int>& trimFactor);
15071507
std::vector<StringData> get();
15081508
std::size_t size() const;
15091509
const std::string& getLeaf() const {
@@ -1520,27 +1520,27 @@ std::unique_ptr<Edges> getEdgesInt32(int32_t value,
15201520
boost::optional<int32_t> min,
15211521
boost::optional<int32_t> max,
15221522
int sparsity,
1523-
int trimFactor);
1523+
const boost::optional<int>& trimFactor);
15241524

15251525
std::unique_ptr<Edges> getEdgesInt64(int64_t value,
15261526
boost::optional<int64_t> min,
15271527
boost::optional<int64_t> max,
15281528
int sparsity,
1529-
int trimFactor);
1529+
const boost::optional<int>& trimFactor);
15301530

15311531
std::unique_ptr<Edges> getEdgesDouble(double value,
15321532
boost::optional<double> min,
15331533
boost::optional<double> max,
15341534
boost::optional<uint32_t> precision,
15351535
int sparsity,
1536-
int trimFactor);
1536+
const boost::optional<int>& trimFactor);
15371537

15381538
std::unique_ptr<Edges> getEdgesDecimal128(Decimal128 value,
15391539
boost::optional<Decimal128> min,
15401540
boost::optional<Decimal128> max,
15411541
boost::optional<uint32_t> precision,
15421542
int sparsity,
1543-
int trimFactor);
1543+
const boost::optional<int>& trimFactor);
15441544

15451545
// Equivalent to a full edges calculation without creating an intemediate vector.
15461546
// getEdgesT(min, min, max, precision, sparsity, trimFactor).size()
@@ -1557,7 +1557,7 @@ std::vector<std::string> minCoverInt32(int32_t lowerBound,
15571557
boost::optional<int32_t> min,
15581558
boost::optional<int32_t> max,
15591559
int sparsity,
1560-
int trimFactor);
1560+
const boost::optional<int>& trimFactor);
15611561

15621562
std::vector<std::string> minCoverInt64(int64_t lowerBound,
15631563
bool includeLowerBound,
@@ -1566,7 +1566,7 @@ std::vector<std::string> minCoverInt64(int64_t lowerBound,
15661566
boost::optional<int64_t> min,
15671567
boost::optional<int64_t> max,
15681568
int sparsity,
1569-
int trimFactor);
1569+
const boost::optional<int>& trimFactor);
15701570

15711571
std::vector<std::string> minCoverDouble(double lowerBound,
15721572
bool includeLowerBound,
@@ -1576,7 +1576,7 @@ std::vector<std::string> minCoverDouble(double lowerBound,
15761576
boost::optional<double> max,
15771577
boost::optional<uint32_t> precision,
15781578
int sparsity,
1579-
int trimFactor);
1579+
const boost::optional<int>& trimFactor);
15801580

15811581
std::vector<std::string> minCoverDecimal128(Decimal128 lowerBound,
15821582
bool includeLowerBound,
@@ -1586,7 +1586,7 @@ std::vector<std::string> minCoverDecimal128(Decimal128 lowerBound,
15861586
boost::optional<Decimal128> max,
15871587
boost::optional<uint32_t> precision,
15881588
int sparsity,
1589-
int trimFactor);
1589+
const boost::optional<int>& trimFactor);
15901590

15911591
class FLEUtil {
15921592
public:

src/mongo/crypto/fle_crypto_test.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -5071,6 +5071,7 @@ class EdgeTestFixture : public unittest::Test {
50715071
if (precision) {
50725072
config.setPrecision(*precision);
50735073
}
5074+
config.setTrimFactor(0);
50745075
return config;
50755076
}
50765077

src/mongo/db/commands/fle_compact_test.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,7 @@ QueryTypeConfig generateQueryTypeConfigForTest(const T& min,
565565
config.setPrecision(precision.get());
566566
}
567567
config.setSparsity(sparsity);
568+
config.setTrimFactor(0);
568569

569570
return config;
570571
}

src/mongo/db/fle_crud_test.cpp

+6-7
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ EncryptedFieldConfig getTestEncryptedFieldConfig(
455455
,
456456
"path": "encrypted",
457457
"bsonType": "int",
458-
"queries": {"queryType": "range", "min": 0, "max": 15, "sparsity": 1}
458+
"queries": {"queryType": "range", "min": 0, "max": 15, "sparsity": 1, "trimFactor": 0}
459459
460460
}
461461
]
@@ -482,7 +482,7 @@ void parseEncryptedInvalidFieldConfig(StringData esc, StringData ecoc) {
482482
,
483483
"path": "encrypted",
484484
"bsonType": "int",
485-
"queries": {"queryType": "range", "min": 0, "max": 15, "sparsity": 1}
485+
"queries": {"queryType": "range", "min": 0, "max": 15, "sparsity": 1, "trimFactor": 0}
486486
487487
}
488488
]
@@ -553,6 +553,7 @@ BSONObj generateFLE2RangeInsertSpec(BSONElement value) {
553553
auto upperDoc = BSON("ub" << 15);
554554

555555
spec.setMaxBound(boost::optional<IDLAnyType>(upperDoc.firstElement()));
556+
spec.setTrimFactor(0);
556557
auto specDoc = BSON("s" << spec.toBSON());
557558

558559
return specDoc;
@@ -563,17 +564,15 @@ std::vector<char> generateSinglePlaceholder(BSONElement value,
563564
Fle2AlgorithmInt alg = Fle2AlgorithmInt::kEquality,
564565
int64_t cm = 0) {
565566
FLE2EncryptionPlaceholder ep;
566-
567-
// Has to be generated outside of if statements to root the
568-
// value until ep is finalized as an object.
569-
BSONObj temp = generateFLE2RangeInsertSpec(value);
570-
571567
ep.setAlgorithm(alg);
572568
ep.setUserKeyId(userKeyId);
573569
ep.setIndexKeyId(indexKeyId);
574570
ep.setType(mongo::Fle2PlaceholderType::kInsert);
575571

572+
// Keep definition outside of conditional to keep it alive until serialization.
573+
BSONObj temp;
576574
if (alg == Fle2AlgorithmInt::kRange) {
575+
temp = generateFLE2RangeInsertSpec(value);
577576
ep.setValue(temp.firstElement());
578577
ep.setSparsity(1);
579578
} else {

0 commit comments

Comments
 (0)