Skip to content

Commit 14ccd9c

Browse files
authored
MONGOCRYPT-698 Make trimFactor and sparsity optional (#867)
Supply a constant default sparsity and calculate a default trimFactor if not provided by the user.
1 parent ea59418 commit 14ccd9c

14 files changed

+154
-84
lines changed

src/mc-range-edge-generation-private.h

+6-6
Original file line numberDiff line numberDiff line change
@@ -45,32 +45,32 @@ typedef struct {
4545
mc_optional_int32_t min;
4646
mc_optional_int32_t max;
4747
size_t sparsity;
48-
uint32_t trimFactor;
48+
mc_optional_uint32_t trimFactor;
4949
} mc_getEdgesInt32_args_t;
5050

5151
// mc_getEdgesInt32 implements the Edge Generation algorithm described in
5252
// SERVER-67751 for int32_t.
53-
mc_edges_t *mc_getEdgesInt32(mc_getEdgesInt32_args_t args, mongocrypt_status_t *status);
53+
mc_edges_t *mc_getEdgesInt32(mc_getEdgesInt32_args_t args, mongocrypt_status_t *status, bool use_range_v2);
5454

5555
typedef struct {
5656
int64_t value;
5757
mc_optional_int64_t min;
5858
mc_optional_int64_t max;
5959
size_t sparsity;
60-
uint32_t trimFactor;
60+
mc_optional_uint32_t trimFactor;
6161
} mc_getEdgesInt64_args_t;
6262

6363
// mc_getEdgesInt64 implements the Edge Generation algorithm described in
6464
// SERVER-67751 for int64_t.
65-
mc_edges_t *mc_getEdgesInt64(mc_getEdgesInt64_args_t args, mongocrypt_status_t *status);
65+
mc_edges_t *mc_getEdgesInt64(mc_getEdgesInt64_args_t args, mongocrypt_status_t *status, bool use_range_v2);
6666

6767
typedef struct {
6868
double value;
6969
size_t sparsity;
7070
mc_optional_double_t min;
7171
mc_optional_double_t max;
7272
mc_optional_uint32_t precision;
73-
uint32_t trimFactor;
73+
mc_optional_uint32_t trimFactor;
7474
} mc_getEdgesDouble_args_t;
7575

7676
// mc_getEdgesDouble implements the Edge Generation algorithm described in
@@ -83,7 +83,7 @@ typedef struct {
8383
size_t sparsity;
8484
mc_optional_dec128_t min, max;
8585
mc_optional_uint32_t precision;
86-
uint32_t trimFactor;
86+
mc_optional_uint32_t trimFactor;
8787
} mc_getEdgesDecimal128_args_t;
8888

8989
mc_edges_t *mc_getEdgesDecimal128(mc_getEdgesDecimal128_args_t args, mongocrypt_status_t *status, bool use_range_v2);

src/mc-range-edge-generation.c

+13-7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17+
#include "mc-optional-private.h"
1718
#include "mc-range-edge-generation-private.h"
1819

1920
#include "mc-array-private.h"
@@ -28,14 +29,19 @@ struct _mc_edges_t {
2829
char *leaf;
2930
};
3031

31-
static mc_edges_t *mc_edges_new(const char *leaf, size_t sparsity, uint32_t trimFactor, mongocrypt_status_t *status) {
32+
static mc_edges_t *mc_edges_new(const char *leaf,
33+
size_t sparsity,
34+
mc_optional_uint32_t opt_trimFactor,
35+
mongocrypt_status_t *status,
36+
bool use_range_v2) {
3237
BSON_ASSERT_PARAM(leaf);
3338
if (sparsity < 1) {
3439
CLIENT_ERR("sparsity must be 1 or larger");
3540
return NULL;
3641
}
3742

3843
const size_t leaf_len = strlen(leaf);
44+
const uint32_t trimFactor = trimFactorDefault(leaf_len, opt_trimFactor, use_range_v2);
3945
if (trimFactor != 0 && trimFactor >= leaf_len) {
4046
// We append a total of leaf_len + 1 (for the root) - trimFactor edges. When this number is equal to 1, we
4147
// degenerate into equality, which is not desired, so trimFactor must be less than leaf_len.
@@ -142,7 +148,7 @@ mc_bitstring mc_convert_to_bitstring_u128(mlib_int128 i) {
142148
return ret;
143149
}
144150

145-
mc_edges_t *mc_getEdgesInt32(mc_getEdgesInt32_args_t args, mongocrypt_status_t *status) {
151+
mc_edges_t *mc_getEdgesInt32(mc_getEdgesInt32_args_t args, mongocrypt_status_t *status, bool use_range_v2) {
146152
mc_OSTType_Int32 got;
147153
if (!mc_getTypeInfo32((mc_getTypeInfo32_args_t){.value = args.value, .min = args.min, .max = args.max},
148154
&got,
@@ -158,11 +164,11 @@ mc_edges_t *mc_getEdgesInt32(mc_getEdgesInt32_args_t args, mongocrypt_status_t *
158164
mc_bitstring valueBin = mc_convert_to_bitstring_u32(got.value);
159165
size_t offset = mc_count_leading_zeros_u32(got.max);
160166
const char *leaf = valueBin.str + offset;
161-
mc_edges_t *ret = mc_edges_new(leaf, args.sparsity, args.trimFactor, status);
167+
mc_edges_t *ret = mc_edges_new(leaf, args.sparsity, args.trimFactor, status, use_range_v2);
162168
return ret;
163169
}
164170

165-
mc_edges_t *mc_getEdgesInt64(mc_getEdgesInt64_args_t args, mongocrypt_status_t *status) {
171+
mc_edges_t *mc_getEdgesInt64(mc_getEdgesInt64_args_t args, mongocrypt_status_t *status, bool use_range_v2) {
166172
mc_OSTType_Int64 got;
167173
if (!mc_getTypeInfo64((mc_getTypeInfo64_args_t){.value = args.value, .min = args.min, .max = args.max},
168174
&got,
@@ -178,7 +184,7 @@ mc_edges_t *mc_getEdgesInt64(mc_getEdgesInt64_args_t args, mongocrypt_status_t *
178184
mc_bitstring valueBin = mc_convert_to_bitstring_u64(got.value);
179185
size_t offset = mc_count_leading_zeros_u64(got.max);
180186
const char *leaf = valueBin.str + offset;
181-
mc_edges_t *ret = mc_edges_new(leaf, args.sparsity, args.trimFactor, status);
187+
mc_edges_t *ret = mc_edges_new(leaf, args.sparsity, args.trimFactor, status, use_range_v2);
182188
return ret;
183189
}
184190

@@ -202,7 +208,7 @@ mc_edges_t *mc_getEdgesDouble(mc_getEdgesDouble_args_t args, mongocrypt_status_t
202208
mc_bitstring valueBin = mc_convert_to_bitstring_u64(got.value);
203209
size_t offset = mc_count_leading_zeros_u64(got.max);
204210
const char *leaf = valueBin.str + offset;
205-
mc_edges_t *ret = mc_edges_new(leaf, args.sparsity, args.trimFactor, status);
211+
mc_edges_t *ret = mc_edges_new(leaf, args.sparsity, args.trimFactor, status, use_range_v2);
206212
return ret;
207213
}
208214

@@ -227,7 +233,7 @@ mc_edges_t *mc_getEdgesDecimal128(mc_getEdgesDecimal128_args_t args, mongocrypt_
227233
mc_bitstring bits = mc_convert_to_bitstring_u128(got.value);
228234
size_t offset = mc_count_leading_zeros_u128(got.max);
229235
const char *leaf = bits.str + offset;
230-
mc_edges_t *ret = mc_edges_new(leaf, args.sparsity, args.trimFactor, status);
236+
mc_edges_t *ret = mc_edges_new(leaf, args.sparsity, args.trimFactor, status, use_range_v2);
231237
return ret;
232238
}
233239
#endif // MONGOCRYPT_HAVE_DECIMAL128_SUPPORT

src/mc-range-encoding-private.h

+3
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,7 @@ bool mc_getTypeInfoDecimal128(mc_getTypeInfoDecimal128_args_t args,
127127
bool use_range_v2) MONGOCRYPT_WARN_UNUSED_RESULT;
128128
#endif // MONGOCRYPT_HAVE_DECIMAL128_SUPPORT
129129

130+
extern const int64_t mc_FLERangeSparsityDefault;
131+
132+
uint32_t trimFactorDefault(size_t maxlen, mc_optional_uint32_t trimFactor, bool use_range_v2);
130133
#endif /* MC_RANGE_ENCODING_PRIVATE_H */

src/mc-range-encoding.c

+20
Original file line numberDiff line numberDiff line change
@@ -616,3 +616,23 @@ bool mc_getTypeInfoDecimal128(mc_getTypeInfoDecimal128_args_t args,
616616
}
617617

618618
#endif // defined MONGOCRYPT_HAVE_DECIMAL128_SUPPORT
619+
620+
const int64_t mc_FLERangeSparsityDefault = 2;
621+
const uint32_t mc_FLERangeTrimFactorDefault = 6;
622+
623+
uint32_t trimFactorDefault(size_t maxlen, mc_optional_uint32_t trimFactor, bool use_range_v2) {
624+
if (trimFactor.set) {
625+
return trimFactor.value;
626+
}
627+
628+
if (!use_range_v2) {
629+
// Preserve old default.
630+
return 0;
631+
}
632+
633+
if (mc_FLERangeTrimFactorDefault > maxlen - 1) {
634+
return (uint32_t)maxlen - 1;
635+
} else {
636+
return mc_FLERangeTrimFactorDefault;
637+
}
638+
}

src/mc-range-mincover-generator.template.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,9 @@ static inline DECORATE_NAME(MinCoverGenerator)
9999
UINT_T rangeMax,
100100
UINT_T max,
101101
size_t sparsity,
102-
uint32_t trimFactor,
103-
mongocrypt_status_t *status) {
102+
mc_optional_uint32_t opt_trimFactor,
103+
mongocrypt_status_t *status,
104+
bool use_range_v2) {
104105
BSON_ASSERT_PARAM(status);
105106

106107
if (UINT_COMPARE(rangeMin, rangeMax) > 0) {
@@ -122,6 +123,7 @@ static inline DECORATE_NAME(MinCoverGenerator)
122123
return NULL;
123124
}
124125
size_t maxlen = (size_t)BITS - DECORATE_NAME(mc_count_leading_zeros)(max);
126+
uint32_t trimFactor = trimFactorDefault(maxlen, opt_trimFactor, use_range_v2);
125127
if (trimFactor != 0 && trimFactor >= maxlen) {
126128
CLIENT_ERR("Trim factor must be less than the number of bits (%zu) used to represent an element of the domain",
127129
maxlen);

src/mc-range-mincover-private.h

+8-6
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,14 @@ typedef struct {
4444
mc_optional_int32_t min;
4545
mc_optional_int32_t max;
4646
size_t sparsity;
47-
uint32_t trimFactor;
47+
mc_optional_uint32_t trimFactor;
4848
} mc_getMincoverInt32_args_t;
4949

5050
// mc_getMincoverInt32 implements the Mincover Generation algorithm described in
5151
// SERVER-68600 for int32_t.
5252
mc_mincover_t *mc_getMincoverInt32(mc_getMincoverInt32_args_t args,
53-
mongocrypt_status_t *status) MONGOCRYPT_WARN_UNUSED_RESULT;
53+
mongocrypt_status_t *status,
54+
bool use_range_v2) MONGOCRYPT_WARN_UNUSED_RESULT;
5455

5556
typedef struct {
5657
int64_t lowerBound;
@@ -60,13 +61,14 @@ typedef struct {
6061
mc_optional_int64_t min;
6162
mc_optional_int64_t max;
6263
size_t sparsity;
63-
uint32_t trimFactor;
64+
mc_optional_uint32_t trimFactor;
6465
} mc_getMincoverInt64_args_t;
6566

6667
// mc_getMincoverInt64 implements the Mincover Generation algorithm described in
6768
// SERVER-68600 for int64_t.
6869
mc_mincover_t *mc_getMincoverInt64(mc_getMincoverInt64_args_t args,
69-
mongocrypt_status_t *status) MONGOCRYPT_WARN_UNUSED_RESULT;
70+
mongocrypt_status_t *status,
71+
bool use_range_v2) MONGOCRYPT_WARN_UNUSED_RESULT;
7072

7173
typedef struct {
7274
double lowerBound;
@@ -77,7 +79,7 @@ typedef struct {
7779
mc_optional_double_t min;
7880
mc_optional_double_t max;
7981
mc_optional_uint32_t precision;
80-
uint32_t trimFactor;
82+
mc_optional_uint32_t trimFactor;
8183
} mc_getMincoverDouble_args_t;
8284

8385
// mc_getMincoverDouble implements the Mincover Generation algorithm described
@@ -95,7 +97,7 @@ typedef struct {
9597
size_t sparsity;
9698
mc_optional_dec128_t min, max;
9799
mc_optional_uint32_t precision;
98-
uint32_t trimFactor;
100+
mc_optional_uint32_t trimFactor;
99101
} mc_getMincoverDecimal128_args_t;
100102

101103
// mc_getMincoverDecimal128 implements the Mincover Generation algorithm

src/mc-range-mincover.c

+7-7
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
#include "mc-array-private.h"
2222
#include "mc-range-edge-generation-private.h" // mc_count_leading_zeros_u32
23-
#include "mc-range-encoding-private.h" // mc_getTypeInfo32
23+
#include "mc-range-encoding-private.h" // mc_getTypeInfo32, trimFactorDefault
2424
#include "mc-range-mincover-private.h"
2525
#include "mongocrypt-private.h"
2626

@@ -127,7 +127,7 @@ void mc_mincover_destroy(mc_mincover_t *mincover) {
127127
} else \
128128
(void)0
129129

130-
mc_mincover_t *mc_getMincoverInt32(mc_getMincoverInt32_args_t args, mongocrypt_status_t *status) {
130+
mc_mincover_t *mc_getMincoverInt32(mc_getMincoverInt32_args_t args, mongocrypt_status_t *status, bool use_range_v2) {
131131
BSON_ASSERT_PARAM(status);
132132
CHECK_BOUNDS(args, PRId32, IDENTITY, LESSTHAN);
133133
mc_OSTType_Int32 a, b;
@@ -150,7 +150,7 @@ mc_mincover_t *mc_getMincoverInt32(mc_getMincoverInt32_args_t args, mongocrypt_s
150150
}
151151

152152
MinCoverGenerator_u32 *mcg =
153-
MinCoverGenerator_new_u32(a.value, b.value, a.max, args.sparsity, args.trimFactor, status);
153+
MinCoverGenerator_new_u32(a.value, b.value, a.max, args.sparsity, args.trimFactor, status, use_range_v2);
154154
if (!mcg) {
155155
return NULL;
156156
}
@@ -159,7 +159,7 @@ mc_mincover_t *mc_getMincoverInt32(mc_getMincoverInt32_args_t args, mongocrypt_s
159159
return mc;
160160
}
161161

162-
mc_mincover_t *mc_getMincoverInt64(mc_getMincoverInt64_args_t args, mongocrypt_status_t *status) {
162+
mc_mincover_t *mc_getMincoverInt64(mc_getMincoverInt64_args_t args, mongocrypt_status_t *status, bool use_range_v2) {
163163
BSON_ASSERT_PARAM(status);
164164
CHECK_BOUNDS(args, PRId64, IDENTITY, LESSTHAN);
165165
mc_OSTType_Int64 a, b;
@@ -182,7 +182,7 @@ mc_mincover_t *mc_getMincoverInt64(mc_getMincoverInt64_args_t args, mongocrypt_s
182182
}
183183

184184
MinCoverGenerator_u64 *mcg =
185-
MinCoverGenerator_new_u64(a.value, b.value, a.max, args.sparsity, args.trimFactor, status);
185+
MinCoverGenerator_new_u64(a.value, b.value, a.max, args.sparsity, args.trimFactor, status, use_range_v2);
186186
if (!mcg) {
187187
return NULL;
188188
}
@@ -225,7 +225,7 @@ mc_mincover_t *mc_getMincoverDouble(mc_getMincoverDouble_args_t args, mongocrypt
225225
}
226226

227227
MinCoverGenerator_u64 *mcg =
228-
MinCoverGenerator_new_u64(a.value, b.value, a.max, args.sparsity, args.trimFactor, status);
228+
MinCoverGenerator_new_u64(a.value, b.value, a.max, args.sparsity, args.trimFactor, status, use_range_v2);
229229
if (!mcg) {
230230
return NULL;
231231
}
@@ -269,7 +269,7 @@ mc_getMincoverDecimal128(mc_getMincoverDecimal128_args_t args, mongocrypt_status
269269
}
270270

271271
MinCoverGenerator_u128 *mcg =
272-
MinCoverGenerator_new_u128(a.value, b.value, a.max, args.sparsity, args.trimFactor, status);
272+
MinCoverGenerator_new_u128(a.value, b.value, a.max, args.sparsity, args.trimFactor, status, use_range_v2);
273273
if (!mcg) {
274274
return NULL;
275275
}

src/mc-rangeopts.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,14 @@ bool mc_RangeOpts_parse(mc_RangeOpts_t *ro, const bson_t *in, bool use_range_v2,
119119
}
120120

121121
// Do not error if min/max are not present. min/max are optional.
122-
CHECK_HAS(sparsity);
123122
// Do not error if precision is not present. Precision is optional and only
124123
// applies to double/decimal128.
125124
// Do not error if trimFactor is not present. It is optional.
126125

126+
if (!has_sparsity && use_range_v2) {
127+
ro->sparsity = mc_FLERangeSparsityDefault;
128+
}
129+
127130
// Expect precision only to be set for double or decimal128.
128131
if (has_precision) {
129132
if (!ro->min.set) {
@@ -491,10 +494,7 @@ bool mc_RangeOpts_appendTrimFactor(const mc_RangeOpts_t *ro,
491494
BSON_ASSERT(status || true);
492495

493496
if (!ro->trimFactor.set) {
494-
if (!BSON_APPEND_INT32(out, fieldName, 0)) {
495-
CLIENT_ERR_PREFIXED("failed to append BSON");
496-
return false;
497-
}
497+
// A default `trimFactor` will be selected later with `trimFactorDefault`
498498
return true;
499499
}
500500
BSON_ASSERT(ro->trimFactor.value <= INT32_MAX);

0 commit comments

Comments
 (0)