mirror of https://github.com/mongodb/mongo
SERVER-91077 Update FLE Range sparsity/trimFactor defaults (#24158)
GitOrigin-RevId: 7d11c46616c032f426b0635c180374bd7d8c346b
This commit is contained in:
parent
936cca77e5
commit
755b06ff50
|
|
@ -167,11 +167,6 @@ uint32_t getNumberOfBitsInDomain(const boost::optional<Decimal128>& min,
|
|||
}
|
||||
}
|
||||
|
||||
std::int64_t getRangeSparsityDefault() {
|
||||
// TODO: SERVER-91077 change to a more suitable default value
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::pair<mongo::Value, mongo::Value> getRangeMinMaxDefaults(BSONType fieldType) {
|
||||
switch (fieldType) {
|
||||
case NumberDouble:
|
||||
|
|
@ -470,10 +465,9 @@ void setRangeDefaults(BSONType fieldType, StringData fieldPath, QueryTypeConfig*
|
|||
validateRangeIndex(fieldType, fieldPath, query);
|
||||
|
||||
auto [defMin, defMax] = getRangeMinMaxDefaults(fieldType);
|
||||
auto defSparsity = getRangeSparsityDefault();
|
||||
query.setMin(query.getMin().value_or(defMin));
|
||||
query.setMax(query.getMax().value_or(defMax));
|
||||
query.setSparsity(query.getSparsity().value_or(defSparsity));
|
||||
query.setSparsity(query.getSparsity().value_or(kFLERangeSparsityDefault));
|
||||
}
|
||||
|
||||
} // namespace mongo
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ class EncryptedField;
|
|||
class EncryptedFieldConfig;
|
||||
class QueryTypeConfig;
|
||||
|
||||
constexpr int kFLERangeSparsityDefault = 1;
|
||||
constexpr int kFLERangeTrimFactorDefault = 0;
|
||||
constexpr int kFLERangeSparsityDefault = 2;
|
||||
constexpr int kFLERangeTrimFactorDefault = 6;
|
||||
|
||||
/*
|
||||
* Value: Value to attempt to coerce to field's type.
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ extern "C" {
|
|||
#include "mongo/crypto/aead_encryption.h"
|
||||
#include "mongo/crypto/encryption_fields_gen.h"
|
||||
#include "mongo/crypto/encryption_fields_util.h"
|
||||
#include "mongo/crypto/encryption_fields_validation.h"
|
||||
#include "mongo/crypto/fle_crypto_predicate.h"
|
||||
#include "mongo/crypto/fle_data_frames.h"
|
||||
#include "mongo/crypto/fle_field_schema_gen.h"
|
||||
|
|
@ -931,7 +932,7 @@ std::unique_ptr<Edges> getEdges(FLE2RangeInsertSpec spec, int sparsity) {
|
|||
auto element = spec.getValue().getElement();
|
||||
auto minBound = spec.getMinBound().map([](IDLAnyType m) { return m.getElement(); });
|
||||
auto maxBound = spec.getMaxBound().map([](IDLAnyType m) { return m.getElement(); });
|
||||
auto trimFactor = spec.getTrimFactor() ? spec.getTrimFactor().value() : 0;
|
||||
auto trimFactor = spec.getTrimFactor();
|
||||
|
||||
switch (element.type()) {
|
||||
case BSONType::NumberInt:
|
||||
|
|
@ -4322,8 +4323,20 @@ bool EncryptedPredicateEvaluatorV2::evaluate(
|
|||
|
||||
// Edges
|
||||
|
||||
Edges::Edges(std::string leaf, int sparsity, int trimFactor)
|
||||
: _leaf(std::move(leaf)), _sparsity(sparsity), _trimFactor(trimFactor) {
|
||||
namespace {
|
||||
int resolveTrimFactorDefault(int maxlen, const boost::optional<int>& optTrimFactor) {
|
||||
if (optTrimFactor) {
|
||||
return *optTrimFactor;
|
||||
}
|
||||
|
||||
return std::clamp(kFLERangeTrimFactorDefault, 0, maxlen - 1);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Edges::Edges(std::string leaf, int sparsity, const boost::optional<int>& optTrimFactor)
|
||||
: _leaf(std::move(leaf)),
|
||||
_sparsity(sparsity),
|
||||
_trimFactor(resolveTrimFactorDefault(_leaf.length(), optTrimFactor)) {
|
||||
uassert(6775101, "sparsity must be 1 or larger", _sparsity > 0);
|
||||
dassert(std::all_of(_leaf.begin(), _leaf.end(), [](char c) { return c == '1' || c == '0'; }));
|
||||
uassert(8574105,
|
||||
|
|
@ -4370,7 +4383,8 @@ std::size_t Edges::size() const {
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
std::unique_ptr<Edges> getEdgesT(T value, T min, T max, int sparsity, int trimFactor) {
|
||||
std::unique_ptr<Edges> getEdgesT(
|
||||
T value, T min, T max, int sparsity, const boost::optional<int>& trimFactor) {
|
||||
static_assert(!std::numeric_limits<T>::is_signed);
|
||||
static_assert(std::numeric_limits<T>::is_integer);
|
||||
|
||||
|
|
@ -4388,7 +4402,7 @@ std::unique_ptr<Edges> getEdgesInt32(int32_t value,
|
|||
boost::optional<int32_t> min,
|
||||
boost::optional<int32_t> max,
|
||||
int sparsity,
|
||||
int trimFactor) {
|
||||
const boost::optional<int>& trimFactor) {
|
||||
auto aost = getTypeInfo32(value, min, max);
|
||||
return getEdgesT(aost.value, aost.min, aost.max, sparsity, trimFactor);
|
||||
}
|
||||
|
|
@ -4397,7 +4411,7 @@ std::unique_ptr<Edges> getEdgesInt64(int64_t value,
|
|||
boost::optional<int64_t> min,
|
||||
boost::optional<int64_t> max,
|
||||
int sparsity,
|
||||
int trimFactor) {
|
||||
const boost::optional<int>& trimFactor) {
|
||||
auto aost = getTypeInfo64(value, min, max);
|
||||
return getEdgesT(aost.value, aost.min, aost.max, sparsity, trimFactor);
|
||||
}
|
||||
|
|
@ -4407,7 +4421,7 @@ std::unique_ptr<Edges> getEdgesDouble(double value,
|
|||
boost::optional<double> max,
|
||||
boost::optional<uint32_t> precision,
|
||||
int sparsity,
|
||||
int trimFactor) {
|
||||
const boost::optional<int>& trimFactor) {
|
||||
auto aost = getTypeInfoDouble(value, min, max, precision);
|
||||
return getEdgesT(aost.value, aost.min, aost.max, sparsity, trimFactor);
|
||||
}
|
||||
|
|
@ -4417,7 +4431,7 @@ std::unique_ptr<Edges> getEdgesDecimal128(Decimal128 value,
|
|||
boost::optional<Decimal128> max,
|
||||
boost::optional<uint32_t> precision,
|
||||
int sparsity,
|
||||
int trimFactor) {
|
||||
const boost::optional<int>& trimFactor) {
|
||||
auto aost = getTypeInfoDecimal128(value, min, max, precision);
|
||||
return getEdgesT(aost.value, aost.min, aost.max, sparsity, trimFactor);
|
||||
}
|
||||
|
|
@ -4427,7 +4441,7 @@ std::uint64_t getEdgesLength(BSONType fieldType, StringData fieldPath, QueryType
|
|||
setRangeDefaults(fieldType, fieldPath, &config);
|
||||
|
||||
const auto sparsity = *config.getSparsity();
|
||||
const auto trimFactor = config.getTrimFactor().get_value_or(0);
|
||||
const auto trimFactor = config.getTrimFactor();
|
||||
auto precision = config.getPrecision().map(
|
||||
[](auto signedInt) -> uint32_t { return static_cast<uint32_t>(signedInt); });
|
||||
|
||||
|
|
@ -4473,7 +4487,7 @@ template <typename T>
|
|||
class MinCoverGenerator {
|
||||
public:
|
||||
static std::vector<std::string> minCover(
|
||||
T lowerBound, T upperBound, T max, int sparsity, int trimFactor) {
|
||||
T lowerBound, T upperBound, T max, int sparsity, const boost::optional<int>& trimFactor) {
|
||||
MinCoverGenerator<T> mcg(lowerBound, upperBound, max, sparsity, trimFactor);
|
||||
std::vector<std::string> c;
|
||||
mcg.minCoverRec(c, 0, mcg._maxlen);
|
||||
|
|
@ -4481,12 +4495,13 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
MinCoverGenerator(T lowerBound, T upperBound, T max, int sparsity, int trimFactor)
|
||||
MinCoverGenerator(
|
||||
T lowerBound, T upperBound, T max, int sparsity, const boost::optional<int>& optTrimFactor)
|
||||
: _lowerBound(lowerBound),
|
||||
_upperBound(upperBound),
|
||||
_sparsity(sparsity),
|
||||
_trimFactor(trimFactor),
|
||||
_maxlen(getFirstBitSet(max)) {
|
||||
_maxlen(getFirstBitSet(max)),
|
||||
_trimFactor(resolveTrimFactorDefault(_maxlen, optTrimFactor)) {
|
||||
static_assert(!std::numeric_limits<T>::is_signed);
|
||||
static_assert(std::numeric_limits<T>::is_integer);
|
||||
tassert(6860001,
|
||||
|
|
@ -4496,7 +4511,7 @@ private:
|
|||
uassert(8574106,
|
||||
"Trim factor must be >= 0 and less than the number of bits used to represent an "
|
||||
"element of the domain",
|
||||
trimFactor >= 0 && (trimFactor == 0 || trimFactor < _maxlen));
|
||||
_trimFactor >= 0 && (_trimFactor == 0 || _trimFactor < _maxlen));
|
||||
}
|
||||
|
||||
// Generate and apply a mask to an integer, filling masked bits with 1;
|
||||
|
|
@ -4560,13 +4575,17 @@ private:
|
|||
T _lowerBound;
|
||||
T _upperBound;
|
||||
int _sparsity;
|
||||
int _trimFactor;
|
||||
int _maxlen;
|
||||
int _trimFactor;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
std::vector<std::string> minCover(
|
||||
T lowerBound, T upperBound, T min, T max, int sparsity, int trimFactor) {
|
||||
std::vector<std::string> minCover(T lowerBound,
|
||||
T upperBound,
|
||||
T min,
|
||||
T max,
|
||||
int sparsity,
|
||||
const boost::optional<int>& trimFactor) {
|
||||
dassert(0 == min);
|
||||
return MinCoverGenerator<T>::minCover(lowerBound, upperBound, max, sparsity, trimFactor);
|
||||
}
|
||||
|
|
@ -4604,7 +4623,7 @@ std::vector<std::string> minCoverInt32(int32_t lowerBound,
|
|||
boost::optional<int32_t> min,
|
||||
boost::optional<int32_t> max,
|
||||
int sparsity,
|
||||
int trimFactor) {
|
||||
const boost::optional<int>& trimFactor) {
|
||||
auto a = getTypeInfo32(lowerBound, min, max);
|
||||
auto b = getTypeInfo32(upperBound, min, max);
|
||||
dassert(a.min == b.min);
|
||||
|
|
@ -4623,7 +4642,7 @@ std::vector<std::string> minCoverInt64(int64_t lowerBound,
|
|||
boost::optional<int64_t> min,
|
||||
boost::optional<int64_t> max,
|
||||
int sparsity,
|
||||
int trimFactor) {
|
||||
const boost::optional<int>& trimFactor) {
|
||||
auto a = getTypeInfo64(lowerBound, min, max);
|
||||
auto b = getTypeInfo64(upperBound, min, max);
|
||||
dassert(a.min == b.min);
|
||||
|
|
@ -4643,7 +4662,7 @@ std::vector<std::string> minCoverDouble(double lowerBound,
|
|||
boost::optional<double> max,
|
||||
boost::optional<uint32_t> precision,
|
||||
int sparsity,
|
||||
int trimFactor) {
|
||||
const boost::optional<int>& trimFactor) {
|
||||
auto a = getTypeInfoDouble(lowerBound, min, max, precision);
|
||||
auto b = getTypeInfoDouble(upperBound, min, max, precision);
|
||||
dassert(a.min == b.min);
|
||||
|
|
@ -4662,7 +4681,7 @@ std::vector<std::string> minCoverDecimal128(Decimal128 lowerBound,
|
|||
boost::optional<Decimal128> max,
|
||||
boost::optional<uint32_t> precision,
|
||||
int sparsity,
|
||||
int trimFactor) {
|
||||
const boost::optional<int>& trimFactor) {
|
||||
auto a = getTypeInfoDecimal128(lowerBound, min, max, precision);
|
||||
auto b = getTypeInfoDecimal128(upperBound, min, max, precision);
|
||||
dassert(a.min == b.min);
|
||||
|
|
|
|||
|
|
@ -1503,7 +1503,7 @@ struct ParsedFindRangePayload {
|
|||
|
||||
class Edges {
|
||||
public:
|
||||
Edges(std::string leaf, int sparsity, int trimFactor);
|
||||
Edges(std::string leaf, int sparsity, const boost::optional<int>& trimFactor);
|
||||
std::vector<StringData> get();
|
||||
std::size_t size() const;
|
||||
const std::string& getLeaf() const {
|
||||
|
|
@ -1520,27 +1520,27 @@ std::unique_ptr<Edges> getEdgesInt32(int32_t value,
|
|||
boost::optional<int32_t> min,
|
||||
boost::optional<int32_t> max,
|
||||
int sparsity,
|
||||
int trimFactor);
|
||||
const boost::optional<int>& trimFactor);
|
||||
|
||||
std::unique_ptr<Edges> getEdgesInt64(int64_t value,
|
||||
boost::optional<int64_t> min,
|
||||
boost::optional<int64_t> max,
|
||||
int sparsity,
|
||||
int trimFactor);
|
||||
const boost::optional<int>& trimFactor);
|
||||
|
||||
std::unique_ptr<Edges> getEdgesDouble(double value,
|
||||
boost::optional<double> min,
|
||||
boost::optional<double> max,
|
||||
boost::optional<uint32_t> precision,
|
||||
int sparsity,
|
||||
int trimFactor);
|
||||
const boost::optional<int>& trimFactor);
|
||||
|
||||
std::unique_ptr<Edges> getEdgesDecimal128(Decimal128 value,
|
||||
boost::optional<Decimal128> min,
|
||||
boost::optional<Decimal128> max,
|
||||
boost::optional<uint32_t> precision,
|
||||
int sparsity,
|
||||
int trimFactor);
|
||||
const boost::optional<int>& trimFactor);
|
||||
|
||||
// Equivalent to a full edges calculation without creating an intemediate vector.
|
||||
// getEdgesT(min, min, max, precision, sparsity, trimFactor).size()
|
||||
|
|
@ -1557,7 +1557,7 @@ std::vector<std::string> minCoverInt32(int32_t lowerBound,
|
|||
boost::optional<int32_t> min,
|
||||
boost::optional<int32_t> max,
|
||||
int sparsity,
|
||||
int trimFactor);
|
||||
const boost::optional<int>& trimFactor);
|
||||
|
||||
std::vector<std::string> minCoverInt64(int64_t lowerBound,
|
||||
bool includeLowerBound,
|
||||
|
|
@ -1566,7 +1566,7 @@ std::vector<std::string> minCoverInt64(int64_t lowerBound,
|
|||
boost::optional<int64_t> min,
|
||||
boost::optional<int64_t> max,
|
||||
int sparsity,
|
||||
int trimFactor);
|
||||
const boost::optional<int>& trimFactor);
|
||||
|
||||
std::vector<std::string> minCoverDouble(double lowerBound,
|
||||
bool includeLowerBound,
|
||||
|
|
@ -1576,7 +1576,7 @@ std::vector<std::string> minCoverDouble(double lowerBound,
|
|||
boost::optional<double> max,
|
||||
boost::optional<uint32_t> precision,
|
||||
int sparsity,
|
||||
int trimFactor);
|
||||
const boost::optional<int>& trimFactor);
|
||||
|
||||
std::vector<std::string> minCoverDecimal128(Decimal128 lowerBound,
|
||||
bool includeLowerBound,
|
||||
|
|
@ -1586,7 +1586,7 @@ std::vector<std::string> minCoverDecimal128(Decimal128 lowerBound,
|
|||
boost::optional<Decimal128> max,
|
||||
boost::optional<uint32_t> precision,
|
||||
int sparsity,
|
||||
int trimFactor);
|
||||
const boost::optional<int>& trimFactor);
|
||||
|
||||
class FLEUtil {
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -5071,6 +5071,7 @@ public:
|
|||
if (precision) {
|
||||
config.setPrecision(*precision);
|
||||
}
|
||||
config.setTrimFactor(0);
|
||||
return config;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -565,6 +565,7 @@ QueryTypeConfig generateQueryTypeConfigForTest(const T& min,
|
|||
config.setPrecision(precision.get());
|
||||
}
|
||||
config.setSparsity(sparsity);
|
||||
config.setTrimFactor(0);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -455,7 +455,7 @@ EncryptedFieldConfig getTestEncryptedFieldConfig(
|
|||
,
|
||||
"path": "encrypted",
|
||||
"bsonType": "int",
|
||||
"queries": {"queryType": "range", "min": 0, "max": 15, "sparsity": 1}
|
||||
"queries": {"queryType": "range", "min": 0, "max": 15, "sparsity": 1, "trimFactor": 0}
|
||||
|
||||
}
|
||||
]
|
||||
|
|
@ -482,7 +482,7 @@ void parseEncryptedInvalidFieldConfig(StringData esc, StringData ecoc) {
|
|||
,
|
||||
"path": "encrypted",
|
||||
"bsonType": "int",
|
||||
"queries": {"queryType": "range", "min": 0, "max": 15, "sparsity": 1}
|
||||
"queries": {"queryType": "range", "min": 0, "max": 15, "sparsity": 1, "trimFactor": 0}
|
||||
|
||||
}
|
||||
]
|
||||
|
|
@ -553,6 +553,7 @@ BSONObj generateFLE2RangeInsertSpec(BSONElement value) {
|
|||
auto upperDoc = BSON("ub" << 15);
|
||||
|
||||
spec.setMaxBound(boost::optional<IDLAnyType>(upperDoc.firstElement()));
|
||||
spec.setTrimFactor(0);
|
||||
auto specDoc = BSON("s" << spec.toBSON());
|
||||
|
||||
return specDoc;
|
||||
|
|
@ -563,17 +564,15 @@ std::vector<char> generateSinglePlaceholder(BSONElement value,
|
|||
Fle2AlgorithmInt alg = Fle2AlgorithmInt::kEquality,
|
||||
int64_t cm = 0) {
|
||||
FLE2EncryptionPlaceholder ep;
|
||||
|
||||
// Has to be generated outside of if statements to root the
|
||||
// value until ep is finalized as an object.
|
||||
BSONObj temp = generateFLE2RangeInsertSpec(value);
|
||||
|
||||
ep.setAlgorithm(alg);
|
||||
ep.setUserKeyId(userKeyId);
|
||||
ep.setIndexKeyId(indexKeyId);
|
||||
ep.setType(mongo::Fle2PlaceholderType::kInsert);
|
||||
|
||||
// Keep definition outside of conditional to keep it alive until serialization.
|
||||
BSONObj temp;
|
||||
if (alg == Fle2AlgorithmInt::kRange) {
|
||||
temp = generateFLE2RangeInsertSpec(value);
|
||||
ep.setValue(temp.firstElement());
|
||||
ep.setSparsity(1);
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in New Issue