Skip to content

Commit 0647ed0

Browse files
authored
MONGOCRYPT-936 Add "substring" query type as alias for "substringPreview" (#1190)
1 parent aa6da2b commit 0647ed0

12 files changed

Lines changed: 97 additions & 32 deletions

src/mc-efc-private.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@ typedef enum _supported_query_type_flags {
2828
SUPPORTS_RANGE_QUERIES = 1 << 1,
2929
// Range preview query supported
3030
SUPPORTS_RANGE_PREVIEW_DEPRECATED_QUERIES = 1 << 2,
31-
// Text search preview query supported
32-
SUPPORTS_SUBSTRING_PREVIEW_QUERIES = 1 << 3,
31+
// Text search query supported
32+
SUPPORTS_SUBSTRING_QUERIES = 1 << 3,
3333
SUPPORTS_SUFFIX_QUERIES = 1 << 4,
3434
SUPPORTS_PREFIX_QUERIES = 1 << 5,
3535
// suffixPreview and prefixPreview are deprecated aliases for suffix and prefix, respectively.
3636
SUPPORTS_SUFFIX_PREVIEW_DEPRECATED_QUERIES = 1 << 6,
3737
SUPPORTS_PREFIX_PREVIEW_DEPRECATED_QUERIES = 1 << 7,
38+
// substring preview query supported
39+
SUPPORTS_SUBSTRING_PREVIEW_DEPRECATED_QUERIES = 1 << 8,
3840
} supported_query_type_flags;
3941

4042
typedef struct _mc_EncryptedField_t {

src/mc-efc.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ static bool _parse_query_type_string(const char *queryType, supported_query_type
3333
*out = SUPPORTS_RANGE_QUERIES;
3434
} else if (mstr_eq_ignore_case(mstrv_lit(MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_DEPRECATED_STR), qtv)) {
3535
*out = SUPPORTS_RANGE_PREVIEW_DEPRECATED_QUERIES;
36-
} else if (mstr_eq_ignore_case(mstrv_lit(MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW_STR), qtv)) {
37-
*out = SUPPORTS_SUBSTRING_PREVIEW_QUERIES;
36+
} else if (mstr_eq_ignore_case(mstrv_lit(MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW_DEPRECATED_STR), qtv)
37+
|| mstr_eq_ignore_case(mstrv_lit(MONGOCRYPT_QUERY_TYPE_SUBSTRING_STR), qtv)) {
38+
*out = SUPPORTS_SUBSTRING_QUERIES;
3839
} else if (mstr_eq_ignore_case(mstrv_lit(MONGOCRYPT_QUERY_TYPE_SUFFIX_STR), qtv)) {
3940
*out = SUPPORTS_SUFFIX_QUERIES;
4041
} else if (mstr_eq_ignore_case(mstrv_lit(MONGOCRYPT_QUERY_TYPE_PREFIX_STR), qtv)) {
@@ -244,8 +245,9 @@ bool mc_EncryptedFieldConfig_parse(mc_EncryptedFieldConfig_t *efc,
244245

245246
if (!bson_iter_init_find(&iter, efc_bson, "strEncodeVersion")) {
246247
if (all_supported_queries
247-
& (SUPPORTS_SUBSTRING_PREVIEW_QUERIES | SUPPORTS_SUFFIX_QUERIES | SUPPORTS_PREFIX_QUERIES
248-
| SUPPORTS_SUFFIX_PREVIEW_DEPRECATED_QUERIES | SUPPORTS_PREFIX_PREVIEW_DEPRECATED_QUERIES)) {
248+
& (SUPPORTS_SUBSTRING_QUERIES | SUPPORTS_SUBSTRING_PREVIEW_DEPRECATED_QUERIES | SUPPORTS_SUFFIX_QUERIES
249+
| SUPPORTS_PREFIX_QUERIES | SUPPORTS_SUFFIX_PREVIEW_DEPRECATED_QUERIES
250+
| SUPPORTS_PREFIX_PREVIEW_DEPRECATED_QUERIES)) {
249251
// Has at least one text search query type, set to latest by default.
250252
efc->str_encode_version = LATEST_STR_ENCODE_VERSION;
251253
} else {

src/mc-textopts.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,8 @@ bool mc_TextOpts_to_FLE2TextSearchInsertSpec_for_query(const mc_TextOpts_t *txo,
378378
include_suffix = true;
379379
break;
380380
}
381-
case MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW: {
381+
case MONGOCRYPT_QUERY_TYPE_SUBSTRING:
382+
case MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW_DEPRECATED: {
382383
include_substring = true;
383384
break;
384385
}

src/mongocrypt-ctx-encrypt.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -890,9 +890,9 @@ static moe_result must_omit_encryptionInformation(const char *command_name,
890890
bool has_fields_requiring_ei = false;
891891
for (const mc_EncryptedField_t *ef = efc->fields; ef != NULL; ef = ef->next) {
892892
if (ef->supported_queries
893-
& (SUPPORTS_RANGE_QUERIES | SUPPORTS_SUBSTRING_PREVIEW_QUERIES | SUPPORTS_SUFFIX_QUERIES
894-
| SUPPORTS_PREFIX_QUERIES | SUPPORTS_SUFFIX_PREVIEW_DEPRECATED_QUERIES
895-
| SUPPORTS_PREFIX_PREVIEW_DEPRECATED_QUERIES)) {
893+
& (SUPPORTS_RANGE_QUERIES | SUPPORTS_SUBSTRING_QUERIES | SUPPORTS_SUFFIX_QUERIES
894+
| SUPPORTS_PREFIX_QUERIES | SUPPORTS_SUBSTRING_PREVIEW_DEPRECATED_QUERIES
895+
| SUPPORTS_SUFFIX_PREVIEW_DEPRECATED_QUERIES | SUPPORTS_PREFIX_PREVIEW_DEPRECATED_QUERIES)) {
896896
has_fields_requiring_ei = true;
897897
break;
898898
}
@@ -1012,8 +1012,8 @@ static bool _fle2_append_compactionTokens(mongocrypt_t *crypt,
10121012
const _mongocrypt_buffer_t *ecoct_buf = mc_ECOCToken_get(ecoct);
10131013

10141014
if (ptr->supported_queries
1015-
& (SUPPORTS_RANGE_QUERIES | SUPPORTS_SUBSTRING_PREVIEW_QUERIES | SUPPORTS_SUFFIX_QUERIES
1016-
| SUPPORTS_PREFIX_QUERIES | SUPPORTS_SUFFIX_PREVIEW_DEPRECATED_QUERIES
1015+
& (SUPPORTS_RANGE_QUERIES | SUPPORTS_SUBSTRING_QUERIES | SUPPORTS_SUFFIX_QUERIES | SUPPORTS_PREFIX_QUERIES
1016+
| SUPPORTS_SUBSTRING_PREVIEW_DEPRECATED_QUERIES | SUPPORTS_SUFFIX_PREVIEW_DEPRECATED_QUERIES
10171017
| SUPPORTS_PREFIX_PREVIEW_DEPRECATED_QUERIES)) {
10181018
// Append the document {ecoc: <ECOCToken>, anchorPaddingToken: <AnchorPaddingTokenRoot>}
10191019
esct = mc_ESCToken_new(crypto, cl1t, status);
@@ -1524,9 +1524,10 @@ static bool _fle2_finalize_explicit(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *
15241524
// fallthrough
15251525
case MONGOCRYPT_QUERY_TYPE_SUFFIX:
15261526
case MONGOCRYPT_QUERY_TYPE_PREFIX:
1527+
case MONGOCRYPT_QUERY_TYPE_SUBSTRING:
15271528
case MONGOCRYPT_QUERY_TYPE_SUFFIXPREVIEW_DEPRECATED:
15281529
case MONGOCRYPT_QUERY_TYPE_PREFIXPREVIEW_DEPRECATED:
1529-
case MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW:
1530+
case MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW_DEPRECATED:
15301531
case MONGOCRYPT_QUERY_TYPE_RANGE:
15311532
case MONGOCRYPT_QUERY_TYPE_EQUALITY: marking.u.fle2.type = MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_FIND; break;
15321533
default: _mongocrypt_ctx_fail_w_msg(ctx, "Invalid value for EncryptOpts.queryType"); goto fail;
@@ -2101,9 +2102,9 @@ static bool explicit_encrypt_init(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *ms
21012102
return _mongocrypt_ctx_fail_w_msg(ctx, "suffix query type requires string index type");
21022103
}
21032104
}
2104-
if (qt == MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW) {
2105+
if (qt == MONGOCRYPT_QUERY_TYPE_SUBSTRING || qt == MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW_DEPRECATED) {
21052106
if (!(ctx->opts.index_type.set && ctx->opts.index_type.value == MONGOCRYPT_INDEX_TYPE_STRING)) {
2106-
return _mongocrypt_ctx_fail_w_msg(ctx, "substringPreview query type requires string index type");
2107+
return _mongocrypt_ctx_fail_w_msg(ctx, "substring query type requires string index type");
21072108
}
21082109
}
21092110
}
@@ -2186,9 +2187,10 @@ static bool explicit_encrypt_init(mongocrypt_ctx_t *ctx, mongocrypt_binary_t *ms
21862187
// fallthrough
21872188
case MONGOCRYPT_QUERY_TYPE_PREFIX:
21882189
case MONGOCRYPT_QUERY_TYPE_SUFFIX:
2190+
case MONGOCRYPT_QUERY_TYPE_SUBSTRING:
21892191
case MONGOCRYPT_QUERY_TYPE_PREFIXPREVIEW_DEPRECATED:
21902192
case MONGOCRYPT_QUERY_TYPE_SUFFIXPREVIEW_DEPRECATED:
2191-
case MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW:
2193+
case MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW_DEPRECATED:
21922194
matches = (ctx->opts.index_type.value == MONGOCRYPT_INDEX_TYPE_STRING);
21932195
break;
21942196
default:

src/mongocrypt-ctx-private.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,12 @@ typedef enum _mongocrypt_query_type_t {
4646
MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_DEPRECATED = 3,
4747
MONGOCRYPT_QUERY_TYPE_PREFIX = 4,
4848
MONGOCRYPT_QUERY_TYPE_SUFFIX = 5,
49-
MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW = 6,
49+
MONGOCRYPT_QUERY_TYPE_SUBSTRING = 6,
5050
// prefixPreview and suffixPreview are deprecated aliases for prefix and suffix, respectively. They behave
5151
// identically; the distinct values exist for consistency (cf. rangePreview) and to ease eventual removal.
5252
MONGOCRYPT_QUERY_TYPE_PREFIXPREVIEW_DEPRECATED = 7,
5353
MONGOCRYPT_QUERY_TYPE_SUFFIXPREVIEW_DEPRECATED = 8,
54+
MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW_DEPRECATED = 9,
5455
} mongocrypt_query_type_t;
5556

5657
const char *_mongocrypt_query_type_to_string(mongocrypt_query_type_t val);

src/mongocrypt-ctx.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,9 @@ bool mongocrypt_ctx_setopt_query_type(mongocrypt_ctx_t *ctx, const char *query_t
10271027
} else if (mstr_eq_ignore_case(qt_str, mstrv_lit(MONGOCRYPT_QUERY_TYPE_SUFFIX_STR))) {
10281028
ctx->opts.query_type.value = MONGOCRYPT_QUERY_TYPE_SUFFIX;
10291029
ctx->opts.query_type.set = true;
1030+
} else if (mstr_eq_ignore_case(qt_str, mstrv_lit(MONGOCRYPT_QUERY_TYPE_SUBSTRING_STR))) {
1031+
ctx->opts.query_type.value = MONGOCRYPT_QUERY_TYPE_SUBSTRING;
1032+
ctx->opts.query_type.set = true;
10301033
} else if (mstr_eq_ignore_case(qt_str, mstrv_lit(MONGOCRYPT_QUERY_TYPE_PREFIXPREVIEW_DEPRECATED_STR))) {
10311034
// 'prefixPreview' is a deprecated alias for 'prefix'.
10321035
ctx->opts.query_type.value = MONGOCRYPT_QUERY_TYPE_PREFIXPREVIEW_DEPRECATED;
@@ -1035,8 +1038,10 @@ bool mongocrypt_ctx_setopt_query_type(mongocrypt_ctx_t *ctx, const char *query_t
10351038
// 'suffixPreview' is a deprecated alias for 'suffix'.
10361039
ctx->opts.query_type.value = MONGOCRYPT_QUERY_TYPE_SUFFIXPREVIEW_DEPRECATED;
10371040
ctx->opts.query_type.set = true;
1038-
} else if (mstr_eq_ignore_case(qt_str, mstrv_lit(MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW_STR))) {
1039-
ctx->opts.query_type.value = MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW;
1041+
} else if (mstr_eq_ignore_case(qt_str, mstrv_lit(MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW_DEPRECATED_STR))) {
1042+
// TODO: MONGOCRYPT-938 disallow substringPreview
1043+
// _mongocrypt_ctx_fail_w_msg(ctx, "Query type 'substringPreview' is deprecated, please use 'substring'");
1044+
ctx->opts.query_type.value = MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW_DEPRECATED;
10401045
ctx->opts.query_type.set = true;
10411046
} else {
10421047
/* don't check if qt_str.len fits in int; we want the diagnostic output */
@@ -1068,9 +1073,10 @@ const char *_mongocrypt_query_type_to_string(mongocrypt_query_type_t val) {
10681073
case MONGOCRYPT_QUERY_TYPE_RANGE: return "Range";
10691074
case MONGOCRYPT_QUERY_TYPE_PREFIX: return "Prefix";
10701075
case MONGOCRYPT_QUERY_TYPE_SUFFIX: return "Suffix";
1076+
case MONGOCRYPT_QUERY_TYPE_SUBSTRING: return "Substring";
10711077
case MONGOCRYPT_QUERY_TYPE_PREFIXPREVIEW_DEPRECATED: return "PrefixPreview";
10721078
case MONGOCRYPT_QUERY_TYPE_SUFFIXPREVIEW_DEPRECATED: return "SuffixPreview";
1073-
case MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW: return "SubstringPreview";
1079+
case MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW_DEPRECATED: return "SubstringPreview";
10741080
default: return "Unknown";
10751081
}
10761082
}

src/mongocrypt.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,7 +1559,6 @@ bool mongocrypt_ctx_setopt_algorithm_range(mongocrypt_ctx_t *ctx, mongocrypt_bin
15591559
/**
15601560
* Set options for explicit encryption with the "string" algorithm.
15611561
*
1562-
* NOTE: Use of the "substringPreview" query type is experimental only and may be removed in a future non-major release.
15631562
* @p opts is a BSON document of the form:
15641563
* {
15651564
* "caseSensitive": bool,
@@ -1601,8 +1600,9 @@ bool mongocrypt_setopt_key_expiration(mongocrypt_t *crypt, uint64_t cache_expira
16011600
// DEPRECATED: Support "rangePreview" has been removed in favor of "range".
16021601
#define MONGOCRYPT_QUERY_TYPE_RANGEPREVIEW_DEPRECATED_STR "rangePreview"
16031602
#define MONGOCRYPT_QUERY_TYPE_RANGE_STR "range"
1604-
/// NOTE: "substringPreview" is experimental and may be removed in a future non-major release.
1605-
#define MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW_STR "substringPreview"
1603+
/// DEPRECATED: Support for "substringPreview" has been removed in favor of "substring"
1604+
#define MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW_DEPRECATED_STR "substringPreview"
1605+
#define MONGOCRYPT_QUERY_TYPE_SUBSTRING_STR "substring"
16061606
/// DEPRECATED: Support for "suffixPreview" has been removed in favor of "suffix"
16071607
#define MONGOCRYPT_QUERY_TYPE_SUFFIXPREVIEW_DEPRECATED_STR "suffixPreview"
16081608
#define MONGOCRYPT_QUERY_TYPE_SUFFIX_STR "suffix"

test/data/efc/efc-textSearchFields.json

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,22 @@
6666
}
6767
}
6868
]
69-
}
69+
},
70+
{
71+
"keyId": {
72+
"$binary": {
73+
"base64": "q83vqxI0mHYSNBI0VniQEg==",
74+
"subType": "04"
75+
}
76+
},
77+
"path": "preferredName",
78+
"bsonType": "string",
79+
"queries": {
80+
"queryType": "substring",
81+
"contention": {
82+
"$numberLong": "0"
83+
}
84+
}
85+
}
7086
]
71-
}
87+
}

test/test-mc-efc.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@ static void _test_efc(_mongocrypt_tester_t *tester) {
3131
_mongocrypt_buffer_t expect_keyId1;
3232
_mongocrypt_buffer_t expect_keyId2;
3333
_mongocrypt_buffer_t expect_keyId3;
34+
_mongocrypt_buffer_t expect_keyId4;
3435

3536
_mongocrypt_buffer_copy_from_hex(&expect_keyId1, "12345678123498761234123456789012");
3637
_mongocrypt_buffer_copy_from_hex(&expect_keyId2, "abcdefab123498761234123456789012");
3738
_mongocrypt_buffer_copy_from_hex(&expect_keyId3, "12345678123498761234123456abcdef");
39+
_mongocrypt_buffer_copy_from_hex(&expect_keyId4, "abcdefab123498761234123456789012");
3840

3941
{
4042
_load_test_file(tester, "./test/data/efc/efc-oneField.json", &efc_bson);
@@ -112,6 +114,11 @@ static void _test_efc(_mongocrypt_tester_t *tester) {
112114
ASSERT_CMPUINT8(efc.str_encode_version, ==, LATEST_STR_ENCODE_VERSION);
113115
ptr = efc.fields;
114116
ASSERT(ptr);
117+
ASSERT_STREQUAL(ptr->path, "preferredName");
118+
ASSERT_CMPBUF(expect_keyId4, ptr->keyId);
119+
ASSERT(ptr->supported_queries == SUPPORTS_SUBSTRING_QUERIES);
120+
ASSERT(ptr->next != NULL);
121+
ptr = ptr->next;
115122
ASSERT_STREQUAL(ptr->path, "middleName");
116123
ASSERT_CMPBUF(expect_keyId3, ptr->keyId);
117124
ASSERT(ptr->supported_queries == (SUPPORTS_SUFFIX_QUERIES | SUPPORTS_PREFIX_QUERIES));
@@ -124,7 +131,7 @@ static void _test_efc(_mongocrypt_tester_t *tester) {
124131
ptr = ptr->next;
125132
ASSERT_STREQUAL(ptr->path, "firstName");
126133
ASSERT_CMPBUF(expect_keyId1, ptr->keyId);
127-
ASSERT(ptr->supported_queries == SUPPORTS_SUBSTRING_PREVIEW_QUERIES);
134+
ASSERT(ptr->supported_queries == SUPPORTS_SUBSTRING_QUERIES);
128135
ASSERT(ptr->next == NULL);
129136
mc_EncryptedFieldConfig_cleanup(&efc);
130137
}
@@ -142,7 +149,7 @@ static void _test_efc(_mongocrypt_tester_t *tester) {
142149
ptr = ptr->next;
143150
ASSERT_STREQUAL(ptr->path, "firstName");
144151
ASSERT_CMPBUF(expect_keyId1, ptr->keyId);
145-
ASSERT(ptr->supported_queries == SUPPORTS_SUBSTRING_PREVIEW_QUERIES);
152+
ASSERT(ptr->supported_queries == SUPPORTS_SUBSTRING_QUERIES);
146153
ASSERT(ptr->next == NULL);
147154
mc_EncryptedFieldConfig_cleanup(&efc);
148155
}
@@ -165,6 +172,7 @@ static void _test_efc(_mongocrypt_tester_t *tester) {
165172
_mongocrypt_status_reset(status);
166173
}
167174

175+
_mongocrypt_buffer_cleanup(&expect_keyId4);
168176
_mongocrypt_buffer_cleanup(&expect_keyId3);
169177
_mongocrypt_buffer_cleanup(&expect_keyId2);
170178
_mongocrypt_buffer_cleanup(&expect_keyId1);

test/test-mc-textopts.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ static void test_mc_TextOpts_to_FLE2TextSearchInsertSpec_for_query(_mongocrypt_t
245245
"substring" : {"strMaxLength" : 10, "strMinQueryLength" : 3, "strMaxQueryLength" : 8}
246246
}),
247247
.v = RAW_STRING({"v" : "test"}),
248-
.qt = MONGOCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW,
248+
.qt = MONGOCRYPT_QUERY_TYPE_SUBSTRING,
249249
.expect = RAW_STRING(
250250
{"v" : {"v" : "test", "casef" : false, "diacf" : true, "substr" : {"mlen" : 10, "ub" : 8, "lb" : 3}}})},
251251
{.desc = "Works with prefix",

0 commit comments

Comments
 (0)