From 3dfdab0afc83210d3ce17f4cc1ac1570a0b064a6 Mon Sep 17 00:00:00 2001 From: mdb-ad <198671546+mdb-ad@users.noreply.github.com> Date: Tue, 25 Nov 2025 19:16:57 -0800 Subject: [PATCH 1/5] initial implementation + part of prose test --- .../encryptedFields-prefix-suffix.json | 38 + .../encryptedFields-substring.json | 30 + .../v_noabi/mongocxx/options/encrypt.hpp | 27 + .../v_noabi/mongocxx/options/prefix-fwd.hpp | 42 + .../v_noabi/mongocxx/options/prefix.hpp | 81 ++ .../mongocxx/options/substring-fwd.hpp | 42 + .../v_noabi/mongocxx/options/substring.hpp | 93 +++ .../v_noabi/mongocxx/options/suffix-fwd.hpp | 42 + .../v_noabi/mongocxx/options/suffix.hpp | 84 ++ .../v_noabi/mongocxx/options/text-fwd.hpp | 42 + .../v_noabi/mongocxx/options/text.hpp | 121 +++ src/mongocxx/lib/mongocxx/private/mongoc.hh | 729 +++++++++--------- .../v_noabi/mongocxx/options/encrypt.cpp | 140 ++++ .../test/v_noabi/client_side_encryption.cpp | 147 +++- 14 files changed, 1284 insertions(+), 374 deletions(-) create mode 100644 data/client_side_encryption/explicit-encryption/encryptedFields-prefix-suffix.json create mode 100644 data/client_side_encryption/explicit-encryption/encryptedFields-substring.json create mode 100644 src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/prefix-fwd.hpp create mode 100644 src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/prefix.hpp create mode 100644 src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/substring-fwd.hpp create mode 100644 src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/substring.hpp create mode 100644 src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/suffix-fwd.hpp create mode 100644 src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/suffix.hpp create mode 100644 src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text-fwd.hpp create mode 100644 src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text.hpp diff --git a/data/client_side_encryption/explicit-encryption/encryptedFields-prefix-suffix.json b/data/client_side_encryption/explicit-encryption/encryptedFields-prefix-suffix.json new file mode 100644 index 0000000000..ec4489fa09 --- /dev/null +++ b/data/client_side_encryption/explicit-encryption/encryptedFields-prefix-suffix.json @@ -0,0 +1,38 @@ +{ + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encryptedText", + "bsonType": "string", + "queries": [ + { + "queryType": "prefixPreview", + "strMinQueryLength": { + "$numberInt": "2" + }, + "strMaxQueryLength": { + "$numberInt": "10" + }, + "caseSensitive": true, + "diacriticSensitive": true + }, + { + "queryType": "suffixPreview", + "strMinQueryLength": { + "$numberInt": "2" + }, + "strMaxQueryLength": { + "$numberInt": "10" + }, + "caseSensitive": true, + "diacriticSensitive": true + } + ] + } + ] +} diff --git a/data/client_side_encryption/explicit-encryption/encryptedFields-substring.json b/data/client_side_encryption/explicit-encryption/encryptedFields-substring.json new file mode 100644 index 0000000000..ee22def77b --- /dev/null +++ b/data/client_side_encryption/explicit-encryption/encryptedFields-substring.json @@ -0,0 +1,30 @@ +{ + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encryptedText", + "bsonType": "string", + "queries": [ + { + "queryType": "substringPreview", + "strMaxLength": { + "$numberInt": "10" + }, + "strMinQueryLength": { + "$numberInt": "2" + }, + "strMaxQueryLength": { + "$numberInt": "10" + }, + "caseSensitive": true, + "diacriticSensitive": true + } + ] + } + ] +} diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/encrypt.hpp b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/encrypt.hpp index 51383222b6..8dab38839a 100644 --- a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/encrypt.hpp +++ b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/encrypt.hpp @@ -24,6 +24,7 @@ #include #include +#include #include @@ -118,6 +119,11 @@ class encrypt { /// Use range encryption. /// k_range, + + /// + /// Use textPreview encryption. + /// + k_textPreview, }; /// @@ -130,6 +136,15 @@ class encrypt { /// @brief Use query type "range". k_range, + + /// @brief Use query type "prefixPreview". + k_prefixPreview, + + /// @brief Use query type "suffixPreview". + k_suffixPreview, + + /// @brief Use query type "substringPreview". + k_substringPreview, }; /// @@ -213,6 +228,17 @@ class encrypt { MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v_noabi::stdx::optional const&) range_opts() const; + /// + /// Sets the text options to use for encryption. + /// + MONGOCXX_ABI_EXPORT_CDECL(encrypt&) text_opts(options::text opts); + + /// + /// Gets the current text options + /// + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v_noabi::stdx::optional const&) + text_opts() const; + private: friend ::mongocxx::v_noabi::client_encryption; @@ -224,6 +250,7 @@ class encrypt { bsoncxx::v_noabi::stdx::optional _contention_factor; bsoncxx::v_noabi::stdx::optional _query_type; bsoncxx::v_noabi::stdx::optional _range_opts; + bsoncxx::v_noabi::stdx::optional _text_opts; }; } // namespace options diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/prefix-fwd.hpp b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/prefix-fwd.hpp new file mode 100644 index 0000000000..6e94b7a572 --- /dev/null +++ b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/prefix-fwd.hpp @@ -0,0 +1,42 @@ +// Copyright 2009-present MongoDB, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +namespace mongocxx { +namespace v_noabi { +namespace options { + +class prefix; + +} // namespace options +} // namespace v_noabi +} // namespace mongocxx + +namespace mongocxx { +namespace options { + +using v_noabi::options::prefix; + +} // namespace options +} // namespace mongocxx + +#include + +/// +/// @file +/// Declares @ref mongocxx::v_noabi::options::prefix. +/// diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/prefix.hpp b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/prefix.hpp new file mode 100644 index 0000000000..0d005c5d81 --- /dev/null +++ b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/prefix.hpp @@ -0,0 +1,81 @@ +// Copyright 2009-present MongoDB, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include // IWYU pragma: export + +// + +#include + +#include + +namespace mongocxx { +namespace v_noabi { +namespace options { + +/// +/// Used by @ref mongocxx::v_noabi::options::encrypt::text_opts. +/// +/// Specifies index options (`RangeOpts`) for a Queryable Encryption field supporting "textPreview" +/// queries. +/// +/// @note `caseSensitive`, `diacriticSensitive`, `prefix`, `suffix`, and `substring` must match the values set in the +/// encryptedFields of the destination collection. +/// +class prefix { + public: + /// + /// Default initialization. + /// + prefix() = default; + + /// @brief Sets `PrefixOpts.strMaxQueryLength` + prefix& str_max_query_length(int32_t value) { + _max_query_length = value; + return *this; + } + + /// @brief Gets `PrefixOpts.strMaxQueryLength` + bsoncxx::v_noabi::stdx::optional const& str_max_query_length() const { + return _max_query_length; + } + + /// @brief Sets `PrefixOpts.strMinQueryLength` + prefix& str_min_query_length(int32_t value) { + _min_query_length = value; + return *this; + } + + /// @brief Gets `PrefixOpts.strMinQueryLength` + bsoncxx::v_noabi::stdx::optional const& str_min_query_length() const { + return _min_query_length; + } + + private: + bsoncxx::v_noabi::stdx::optional _min_query_length; + bsoncxx::v_noabi::stdx::optional _max_query_length; +}; + +} // namespace options +} // namespace v_noabi +} // namespace mongocxx + +#include + +/// +/// @file +/// Provides @ref mongocxx::v_noabi::options::prefix. +/// diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/substring-fwd.hpp b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/substring-fwd.hpp new file mode 100644 index 0000000000..0c19fbfddd --- /dev/null +++ b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/substring-fwd.hpp @@ -0,0 +1,42 @@ +// Copyright 2009-present MongoDB, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +namespace mongocxx { +namespace v_noabi { +namespace options { + +class substring; + +} // namespace options +} // namespace v_noabi +} // namespace mongocxx + +namespace mongocxx { +namespace options { + +using v_noabi::options::substring; + +} // namespace options +} // namespace mongocxx + +#include + +/// +/// @file +/// Declares @ref mongocxx::v_noabi::options::substring. +/// diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/substring.hpp b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/substring.hpp new file mode 100644 index 0000000000..995e7ccddc --- /dev/null +++ b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/substring.hpp @@ -0,0 +1,93 @@ +// Copyright 2009-present MongoDB, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include // IWYU pragma: export + +// + +#include + +#include + +namespace mongocxx { +namespace v_noabi { +namespace options { + +/// +/// Used by @ref mongocxx::v_noabi::options::encrypt::text_opts. +/// +/// Specifies index options (`SubstringOpts`) for a Queryable Encryption field supporting "substringPreview" +/// queries. +/// +/// @note `strMaxQueryLength`, `strMinQueryLength`, and `strMaxLength` must match the values set in the +/// encryptedFields of the destination collection. +/// +class substring { + public: + /// + /// Default initialization. + /// + substring() = default; + + /// @brief Sets `SubstringOpts.strMaxQueryLength` + substring& str_max_query_length(int32_t value) { + _max_query_length = value; + return *this; + } + + /// @brief Gets `SubstringOpts.strMaxQueryLength` + bsoncxx::v_noabi::stdx::optional const& str_max_query_length() const { + return _max_query_length; + } + + /// @brief Sets `SubstringOpts.strMinQueryLength` + substring& str_min_query_length(int32_t value) { + _min_query_length = value; + return *this; + } + + /// @brief Gets `SubstringOpts.strMinQueryLength` + bsoncxx::v_noabi::stdx::optional const& str_min_query_length() const { + return _min_query_length; + } + + /// @brief Sets `SubstringOpts.strMaxLength` + substring& str_max_length(int32_t value) { + _max_length = value; + return *this; + } + + /// @brief Gets `substringOpts.strMaxLength` + bsoncxx::v_noabi::stdx::optional const& str_max_length() const { + return _max_length; + } + + private: + bsoncxx::v_noabi::stdx::optional _min_query_length; + bsoncxx::v_noabi::stdx::optional _max_query_length; + bsoncxx::v_noabi::stdx::optional _max_length; +}; + +} // namespace options +} // namespace v_noabi +} // namespace mongocxx + +#include + +/// +/// @file +/// Provides @ref mongocxx::v_noabi::options::substring. +/// diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/suffix-fwd.hpp b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/suffix-fwd.hpp new file mode 100644 index 0000000000..0e93b5a81b --- /dev/null +++ b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/suffix-fwd.hpp @@ -0,0 +1,42 @@ +// Copyright 2009-present MongoDB, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +namespace mongocxx { +namespace v_noabi { +namespace options { + +class suffix; + +} // namespace options +} // namespace v_noabi +} // namespace mongocxx + +namespace mongocxx { +namespace options { + +using v_noabi::options::suffix; + +} // namespace options +} // namespace mongocxx + +#include + +/// +/// @file +/// Declares @ref mongocxx::v_noabi::options::suffix +/// diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/suffix.hpp b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/suffix.hpp new file mode 100644 index 0000000000..67fed62695 --- /dev/null +++ b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/suffix.hpp @@ -0,0 +1,84 @@ +// Copyright 2009-present MongoDB, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include // IWYU pragma: export + +// + +#include + +#include + +namespace mongocxx { +namespace v_noabi { +namespace options { + +/// +/// Used by @ref mongocxx::v_noabi::options::encrypt::text_opts. +/// +/// Specifies index options (`SuffixOpts`) for a Queryable Encryption field supporting "suffixPreview" +/// queries. +/// +/// @note `strMaxQueryLength` and `strMinQueryLength` must match the values set in the encryptedFields +/// of the destination collection. +/// +/// @note For double and decimal128, `min`, `max`, and `precision` must all be set, or all be +/// unset. +/// +class suffix { + public: + /// + /// Default initialization. + /// + suffix() = default; + + /// @brief Sets `SuffixOpts.strMaxQueryLength` + suffix& str_max_query_length(int32_t value) { + _max_query_length = value; + return *this; + } + + /// @brief Gets `SuffixOpts.strMaxQueryLength` + bsoncxx::v_noabi::stdx::optional const& str_max_query_length() const { + return _max_query_length; + } + + /// @brief Sets `SuffixOpts.strMinQueryLength` + suffix& str_min_query_length(int32_t value) { + _min_query_length = value; + return *this; + } + + /// @brief Gets `SuffixOpts.strMinQueryLength` + bsoncxx::v_noabi::stdx::optional const& str_min_query_length() const { + return _min_query_length; + } + + private: + bsoncxx::v_noabi::stdx::optional _min_query_length; + bsoncxx::v_noabi::stdx::optional _max_query_length; +}; + +} // namespace options +} // namespace v_noabi +} // namespace mongocxx + +#include + +/// +/// @file +/// Provides @ref mongocxx::v_noabi::options::suffix. +/// diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text-fwd.hpp b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text-fwd.hpp new file mode 100644 index 0000000000..adba80ab25 --- /dev/null +++ b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text-fwd.hpp @@ -0,0 +1,42 @@ +// Copyright 2009-present MongoDB, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +namespace mongocxx { +namespace v_noabi { +namespace options { + +class text; + +} // namespace options +} // namespace v_noabi +} // namespace mongocxx + +namespace mongocxx { +namespace options { + +using v_noabi::options::text; + +} // namespace options +} // namespace mongocxx + +#include + +/// +/// @file +/// Declares @ref mongocxx::v_noabi::options::range. +/// diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text.hpp b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text.hpp new file mode 100644 index 0000000000..38e9500cda --- /dev/null +++ b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text.hpp @@ -0,0 +1,121 @@ +// Copyright 2009-present MongoDB, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include // IWYU pragma: export + +#include +#include +#include + +// + +#include + +#include + +namespace mongocxx { +namespace v_noabi { +namespace options { + +/// +/// Used by @ref mongocxx::v_noabi::options::encrypt::text_opts. +/// +/// Specifies index options (`TextOpts`) for a Queryable Encryption field supporting "textPreview" +/// queries. +/// +/// @note `caseSensitive`, `diacriticSensitive`, `prefix`, `suffix`, and `substring` must match the values set in the +/// encryptedFields of the destination collection. +/// +class text { + public: + /// + /// Default initialization. + /// + text() = default; + + /// @brief Sets `TextOpts.caseSensitive` + text& case_sensitive(bool value) { + _case_sensitive = value; + return *this; + } + + /// @brief Gets `TextOpts.caseSensitive` + bsoncxx::v_noabi::stdx::optional const& case_sensitive() const { + return _case_sensitive; + } + + /// @brief Sets `TextOpts.diacriticSensitive` + text& diacritic_sensitive(bool value) { + _diacritic_sensitive = value; + return *this; + } + + /// @brief Gets `TextOpts.diacriticSensitive` + bsoncxx::v_noabi::stdx::optional const& diacritic_sensitive() const { + return _diacritic_sensitive; + } + + /// @brief Sets `TextOpts.PrefixOpts` + text& prefix(options::prefix opts) { + _prefix = opts; + return *this; + } + + /// @brief Gets `TextOpts.PrefixOpts` + bsoncxx::v_noabi::stdx::optional const& prefix() const { + return _prefix; + } + + /// @brief Sets `TextOpts.SuffixOpts` + text& suffix(options::suffix opts) { + _suffix = opts; + return *this; + } + + /// @brief Gets `TextOpts.SuffixOpts` + bsoncxx::v_noabi::stdx::optional const& suffix() const { + return _suffix; + } + + /// @brief Sets `TextOpts.SubstringOpts` + text& substring(options::substring opts) { + _substring = opts; + return *this; + } + + /// @brief Gets `TextOpts.SubstringOpts` + bsoncxx::v_noabi::stdx::optional const& substring() const { + return _substring; + } + + private: + bsoncxx::v_noabi::stdx::optional _case_sensitive; + bsoncxx::v_noabi::stdx::optional _diacritic_sensitive; + bsoncxx::v_noabi::stdx::optional _prefix; + bsoncxx::v_noabi::stdx::optional _suffix; + bsoncxx::v_noabi::stdx::optional _substring; +}; + +} // namespace options +} // namespace v_noabi +} // namespace mongocxx + +#include + +/// +/// @file +/// Provides @ref mongocxx::v_noabi::options::text. +/// diff --git a/src/mongocxx/lib/mongocxx/private/mongoc.hh b/src/mongocxx/lib/mongocxx/private/mongoc.hh index d0855e5bd3..a557a33ea6 100644 --- a/src/mongocxx/lib/mongocxx/private/mongoc.hh +++ b/src/mongocxx/lib/mongocxx/private/mongoc.hh @@ -51,360 +51,381 @@ BSONCXX_PRIVATE_WARNINGS_POP(); #endif #pragma push_macro("MONGOC_SYMBOLS_XMACRO") -#define MONGOC_SYMBOLS_XMACRO(X) \ - MONGOC_SYMBOLS_SSL_XMACRO(X) \ - X(apm_callbacks_destroy) \ - X(apm_callbacks_new) \ - X(apm_command_failed_get_command_name) \ - X(apm_command_failed_get_context) \ - X(apm_command_failed_get_duration) \ - X(apm_command_failed_get_error) \ - X(apm_command_failed_get_host) \ - X(apm_command_failed_get_operation_id) \ - X(apm_command_failed_get_reply) \ - X(apm_command_failed_get_request_id) \ - X(apm_command_failed_get_server_id) \ - X(apm_command_failed_get_service_id) \ - X(apm_command_started_get_command_name) \ - X(apm_command_started_get_command) \ - X(apm_command_started_get_context) \ - X(apm_command_started_get_database_name) \ - X(apm_command_started_get_host) \ - X(apm_command_started_get_operation_id) \ - X(apm_command_started_get_request_id) \ - X(apm_command_started_get_server_id) \ - X(apm_command_started_get_service_id) \ - X(apm_command_succeeded_get_command_name) \ - X(apm_command_succeeded_get_context) \ - X(apm_command_succeeded_get_duration) \ - X(apm_command_succeeded_get_host) \ - X(apm_command_succeeded_get_operation_id) \ - X(apm_command_succeeded_get_reply) \ - X(apm_command_succeeded_get_request_id) \ - X(apm_command_succeeded_get_server_id) \ - X(apm_command_succeeded_get_service_id) \ - X(apm_server_changed_get_context) \ - X(apm_server_changed_get_host) \ - X(apm_server_changed_get_new_description) \ - X(apm_server_changed_get_previous_description) \ - X(apm_server_changed_get_topology_id) \ - X(apm_server_closed_get_context) \ - X(apm_server_closed_get_host) \ - X(apm_server_closed_get_topology_id) \ - X(apm_server_heartbeat_failed_get_awaited) \ - X(apm_server_heartbeat_failed_get_context) \ - X(apm_server_heartbeat_failed_get_duration) \ - X(apm_server_heartbeat_failed_get_error) \ - X(apm_server_heartbeat_failed_get_host) \ - X(apm_server_heartbeat_started_get_awaited) \ - X(apm_server_heartbeat_started_get_context) \ - X(apm_server_heartbeat_started_get_host) \ - X(apm_server_heartbeat_succeeded_get_awaited) \ - X(apm_server_heartbeat_succeeded_get_context) \ - X(apm_server_heartbeat_succeeded_get_duration) \ - X(apm_server_heartbeat_succeeded_get_host) \ - X(apm_server_heartbeat_succeeded_get_reply) \ - X(apm_server_opening_get_context) \ - X(apm_server_opening_get_host) \ - X(apm_server_opening_get_topology_id) \ - X(apm_set_command_failed_cb) \ - X(apm_set_command_started_cb) \ - X(apm_set_command_succeeded_cb) \ - X(apm_set_server_changed_cb) \ - X(apm_set_server_closed_cb) \ - X(apm_set_server_heartbeat_failed_cb) \ - X(apm_set_server_heartbeat_started_cb) \ - X(apm_set_server_heartbeat_succeeded_cb) \ - X(apm_set_server_opening_cb) \ - X(apm_set_topology_changed_cb) \ - X(apm_set_topology_closed_cb) \ - X(apm_set_topology_opening_cb) \ - X(apm_topology_changed_get_context) \ - X(apm_topology_changed_get_new_description) \ - X(apm_topology_changed_get_previous_description) \ - X(apm_topology_changed_get_topology_id) \ - X(apm_topology_closed_get_context) \ - X(apm_topology_closed_get_topology_id) \ - X(apm_topology_opening_get_context) \ - X(apm_topology_opening_get_topology_id) \ - X(auto_encryption_opts_destroy) \ - X(auto_encryption_opts_new) \ - X(auto_encryption_opts_set_bypass_auto_encryption) \ - X(auto_encryption_opts_set_bypass_query_analysis) \ - X(auto_encryption_opts_set_encrypted_fields_map) \ - X(auto_encryption_opts_set_extra) \ - X(auto_encryption_opts_set_keyvault_client_pool) \ - X(auto_encryption_opts_set_keyvault_client) \ - X(auto_encryption_opts_set_keyvault_namespace) \ - X(auto_encryption_opts_set_kms_providers) \ - X(auto_encryption_opts_set_schema_map) \ - X(auto_encryption_opts_set_tls_opts) \ - X(bulk_operation_destroy) \ - X(bulk_operation_execute) \ - X(bulk_operation_get_write_concern) \ - X(bulk_operation_insert_with_opts) \ - X(bulk_operation_new) \ - X(bulk_operation_remove_many_with_opts) \ - X(bulk_operation_remove_one_with_opts) \ - X(bulk_operation_replace_one_with_opts) \ - X(bulk_operation_set_bypass_document_validation) \ - X(bulk_operation_set_client_session) \ - X(bulk_operation_set_client) \ - X(bulk_operation_set_collection) \ - X(bulk_operation_set_database) \ - X(bulk_operation_set_write_concern) \ - X(bulk_operation_update_many_with_opts) \ - X(bulk_operation_update_one_with_opts) \ - X(change_stream_destroy) \ - X(change_stream_error_document) \ - X(change_stream_get_resume_token) \ - X(change_stream_next) \ - X(cleanup) \ - X(client_command_simple_with_server_id) \ - X(client_destroy) \ - X(client_enable_auto_encryption) \ - X(client_encryption_add_key_alt_name) \ - X(client_encryption_create_datakey) \ - X(client_encryption_create_encrypted_collection) \ - X(client_encryption_datakey_opts_destroy) \ - X(client_encryption_datakey_opts_new) \ - X(client_encryption_datakey_opts_set_keyaltnames) \ - X(client_encryption_datakey_opts_set_keymaterial) \ - X(client_encryption_datakey_opts_set_masterkey) \ - X(client_encryption_decrypt) \ - X(client_encryption_delete_key) \ - X(client_encryption_destroy) \ - X(client_encryption_encrypt_expression) \ - X(client_encryption_encrypt_opts_destroy) \ - X(client_encryption_encrypt_opts_new) \ - X(client_encryption_encrypt_opts_set_algorithm) \ - X(client_encryption_encrypt_opts_set_contention_factor) \ - X(client_encryption_encrypt_opts_set_keyaltname) \ - X(client_encryption_encrypt_opts_set_keyid) \ - X(client_encryption_encrypt_opts_set_query_type) \ - X(client_encryption_encrypt_opts_set_range_opts) \ - X(client_encryption_encrypt_range_opts_destroy) \ - X(client_encryption_encrypt_range_opts_new) \ - X(client_encryption_encrypt_range_opts_set_max) \ - X(client_encryption_encrypt_range_opts_set_min) \ - X(client_encryption_encrypt_range_opts_set_precision) \ - X(client_encryption_encrypt_range_opts_set_sparsity) \ - X(client_encryption_encrypt_range_opts_set_trim_factor) \ - X(client_encryption_encrypt) \ - X(client_encryption_get_key_by_alt_name) \ - X(client_encryption_get_key) \ - X(client_encryption_get_keys) \ - X(client_encryption_new) \ - X(client_encryption_opts_destroy) \ - X(client_encryption_opts_new) \ - X(client_encryption_opts_set_keyvault_client) \ - X(client_encryption_opts_set_keyvault_namespace) \ - X(client_encryption_opts_set_kms_providers) \ - X(client_encryption_opts_set_tls_opts) \ - X(client_encryption_remove_key_alt_name) \ - X(client_encryption_rewrap_many_datakey_result_destroy) \ - X(client_encryption_rewrap_many_datakey_result_get_bulk_write_result) \ - X(client_encryption_rewrap_many_datakey_result_new) \ - X(client_encryption_rewrap_many_datakey) \ - X(client_find_databases_with_opts) \ - X(client_get_collection) \ - X(client_get_database_names_with_opts) \ - X(client_get_database) \ - X(client_get_read_concern) \ - X(client_get_read_prefs) \ - X(client_get_uri) \ - X(client_get_write_concern) \ - X(client_new_from_uri) \ - X(client_pool_destroy) \ - X(client_pool_enable_auto_encryption) \ - X(client_pool_new_with_error) \ - X(client_pool_new) \ - X(client_pool_pop) \ - X(client_pool_push) \ - X(client_pool_set_apm_callbacks) \ - X(client_pool_set_server_api) \ - X(client_pool_try_pop) \ - X(client_reset) \ - X(client_select_server) \ - X(client_session_abort_transaction) \ - X(client_session_advance_cluster_time) \ - X(client_session_advance_operation_time) \ - X(client_session_append) \ - X(client_session_commit_transaction) \ - X(client_session_destroy) \ - X(client_session_get_cluster_time) \ - X(client_session_get_dirty) \ - X(client_session_get_lsid) \ - X(client_session_get_operation_time) \ - X(client_session_get_opts) \ - X(client_session_get_server_id) \ - X(client_session_get_transaction_state) \ - X(client_session_in_transaction) \ - X(client_session_start_transaction) \ - X(client_session_with_transaction) \ - X(client_set_apm_callbacks) \ - X(client_set_read_concern) \ - X(client_set_read_prefs) \ - X(client_set_server_api) \ - X(client_set_write_concern) \ - X(client_start_session) \ - X(client_watch) \ - X(collection_aggregate) \ - X(collection_command_simple) \ - X(collection_copy) \ - X(collection_count_documents) \ - X(collection_create_bulk_operation_with_opts) \ - X(collection_destroy) \ - X(collection_drop_index) \ - X(collection_drop_with_opts) \ - X(collection_drop) \ - X(collection_estimated_document_count) \ - X(collection_find_and_modify_with_opts) \ - X(collection_find_indexes_with_opts) \ - X(collection_find_with_opts) \ - X(collection_get_name) \ - X(collection_get_read_concern) \ - X(collection_get_read_prefs) \ - X(collection_get_write_concern) \ - X(collection_keys_to_index_string) \ - X(collection_read_command_with_opts) \ - X(collection_rename_with_opts) \ - X(collection_rename) \ - X(collection_set_read_concern) \ - X(collection_set_read_prefs) \ - X(collection_set_write_concern) \ - X(collection_watch) \ - X(collection_write_command_with_opts) \ - X(cursor_destroy) \ - X(cursor_error_document) \ - X(cursor_error) \ - X(cursor_new_from_command_reply_with_opts) \ - X(cursor_next) \ - X(cursor_set_max_await_time_ms) \ - X(database_aggregate) \ - X(database_command_with_opts) \ - X(database_copy) \ - X(database_create_collection) \ - X(database_destroy) \ - X(database_drop_with_opts) \ - X(database_drop) \ - X(database_find_collections_with_opts) \ - X(database_get_collection_names_with_opts) \ - X(database_get_collection) \ - X(database_get_read_concern) \ - X(database_get_read_prefs) \ - X(database_get_write_concern) \ - X(database_has_collection) \ - X(database_set_read_concern) \ - X(database_set_read_prefs) \ - X(database_set_write_concern) \ - X(database_watch) \ - X(error_has_label) \ - X(find_and_modify_opts_append) \ - X(find_and_modify_opts_destroy) \ - X(find_and_modify_opts_new) \ - X(find_and_modify_opts_set_bypass_document_validation) \ - X(find_and_modify_opts_set_fields) \ - X(find_and_modify_opts_set_flags) \ - X(find_and_modify_opts_set_max_time_ms) \ - X(find_and_modify_opts_set_sort) \ - X(find_and_modify_opts_set_update) \ - X(handshake_data_append) \ - X(init) \ - /* X(log_set_handler) CDRIVER-5678: not __cdecl. */ \ - X(read_concern_copy) \ - X(read_concern_destroy) \ - X(read_concern_get_level) \ - X(read_concern_new) \ - X(read_concern_set_level) \ - X(read_prefs_copy) \ - X(read_prefs_destroy) \ - BSONCXX_SUPPRESS_DEPRECATION_WARNINGS_BEGIN \ - X(read_prefs_get_hedge) /* CXX-3241 */ \ - BSONCXX_SUPPRESS_DEPRECATION_WARNINGS_END \ - X(read_prefs_get_max_staleness_seconds) \ - X(read_prefs_get_mode) \ - X(read_prefs_get_tags) \ - X(read_prefs_new) \ - BSONCXX_SUPPRESS_DEPRECATION_WARNINGS_BEGIN \ - X(read_prefs_set_hedge) /* CXX-3241 */ \ - BSONCXX_SUPPRESS_DEPRECATION_WARNINGS_END \ - X(read_prefs_set_max_staleness_seconds) \ - X(read_prefs_set_mode) \ - X(read_prefs_set_tags) \ - X(server_api_copy) \ - X(server_api_deprecation_errors) \ - X(server_api_destroy) \ - X(server_api_get_deprecation_errors) \ - X(server_api_get_strict) \ - X(server_api_get_version) \ - X(server_api_new) \ - X(server_api_strict) \ - X(server_api_version_from_string) \ - X(server_api_version_to_string) \ - X(server_description_hello_response) \ - X(server_description_host) \ - X(server_description_id) \ - X(server_description_round_trip_time) \ - X(server_description_type) \ - X(server_descriptions_destroy_all) \ - X(session_opts_destroy) \ - X(session_opts_get_causal_consistency) \ - X(session_opts_get_snapshot) \ - X(session_opts_new) \ - X(session_opts_set_causal_consistency) \ - X(session_opts_set_default_transaction_opts) \ - X(session_opts_set_snapshot) \ - X(topology_description_get_servers) \ - X(topology_description_has_readable_server) \ - X(topology_description_has_writable_server) \ - X(topology_description_type) \ - X(transaction_opts_clone) \ - X(transaction_opts_destroy) \ - X(transaction_opts_get_max_commit_time_ms) \ - X(transaction_opts_get_read_concern) \ - X(transaction_opts_get_read_prefs) \ - X(transaction_opts_get_write_concern) \ - X(transaction_opts_new) \ - X(transaction_opts_set_max_commit_time_ms) \ - X(transaction_opts_set_read_concern) \ - X(transaction_opts_set_read_prefs) \ - X(transaction_opts_set_write_concern) \ - X(uri_copy) \ - X(uri_destroy) \ - X(uri_get_auth_mechanism) \ - X(uri_get_auth_source) \ - X(uri_get_compressors) \ - X(uri_get_credentials) \ - X(uri_get_database) \ - X(uri_get_hosts) \ - X(uri_get_option_as_utf8) \ - X(uri_get_options) \ - X(uri_get_password) \ - X(uri_get_read_concern) \ - X(uri_get_read_prefs_t) \ - X(uri_get_replica_set) \ - X(uri_get_string) \ - X(uri_get_tls) \ - X(uri_get_username) \ - X(uri_get_write_concern) \ - X(uri_new_with_error) \ - X(write_concern_copy) \ - X(write_concern_destroy) \ - X(write_concern_get_journal) \ - X(write_concern_get_w) \ - X(write_concern_get_wmajority) \ - X(write_concern_get_wtag) \ - X(write_concern_get_wtimeout) \ - X(write_concern_get_wtimeout_int64) \ - X(write_concern_is_acknowledged) \ - X(write_concern_journal_is_set) \ - X(write_concern_new) \ - X(write_concern_set_journal) \ - X(write_concern_set_w) \ - X(write_concern_set_wmajority) \ - X(write_concern_set_wtag) \ - X(write_concern_set_wtimeout) \ +#define MONGOC_SYMBOLS_XMACRO(X) \ + MONGOC_SYMBOLS_SSL_XMACRO(X) \ + X(apm_callbacks_destroy) \ + X(apm_callbacks_new) \ + X(apm_command_failed_get_command_name) \ + X(apm_command_failed_get_context) \ + X(apm_command_failed_get_duration) \ + X(apm_command_failed_get_error) \ + X(apm_command_failed_get_host) \ + X(apm_command_failed_get_operation_id) \ + X(apm_command_failed_get_reply) \ + X(apm_command_failed_get_request_id) \ + X(apm_command_failed_get_server_id) \ + X(apm_command_failed_get_service_id) \ + X(apm_command_started_get_command_name) \ + X(apm_command_started_get_command) \ + X(apm_command_started_get_context) \ + X(apm_command_started_get_database_name) \ + X(apm_command_started_get_host) \ + X(apm_command_started_get_operation_id) \ + X(apm_command_started_get_request_id) \ + X(apm_command_started_get_server_id) \ + X(apm_command_started_get_service_id) \ + X(apm_command_succeeded_get_command_name) \ + X(apm_command_succeeded_get_context) \ + X(apm_command_succeeded_get_duration) \ + X(apm_command_succeeded_get_host) \ + X(apm_command_succeeded_get_operation_id) \ + X(apm_command_succeeded_get_reply) \ + X(apm_command_succeeded_get_request_id) \ + X(apm_command_succeeded_get_server_id) \ + X(apm_command_succeeded_get_service_id) \ + X(apm_server_changed_get_context) \ + X(apm_server_changed_get_host) \ + X(apm_server_changed_get_new_description) \ + X(apm_server_changed_get_previous_description) \ + X(apm_server_changed_get_topology_id) \ + X(apm_server_closed_get_context) \ + X(apm_server_closed_get_host) \ + X(apm_server_closed_get_topology_id) \ + X(apm_server_heartbeat_failed_get_awaited) \ + X(apm_server_heartbeat_failed_get_context) \ + X(apm_server_heartbeat_failed_get_duration) \ + X(apm_server_heartbeat_failed_get_error) \ + X(apm_server_heartbeat_failed_get_host) \ + X(apm_server_heartbeat_started_get_awaited) \ + X(apm_server_heartbeat_started_get_context) \ + X(apm_server_heartbeat_started_get_host) \ + X(apm_server_heartbeat_succeeded_get_awaited) \ + X(apm_server_heartbeat_succeeded_get_context) \ + X(apm_server_heartbeat_succeeded_get_duration) \ + X(apm_server_heartbeat_succeeded_get_host) \ + X(apm_server_heartbeat_succeeded_get_reply) \ + X(apm_server_opening_get_context) \ + X(apm_server_opening_get_host) \ + X(apm_server_opening_get_topology_id) \ + X(apm_set_command_failed_cb) \ + X(apm_set_command_started_cb) \ + X(apm_set_command_succeeded_cb) \ + X(apm_set_server_changed_cb) \ + X(apm_set_server_closed_cb) \ + X(apm_set_server_heartbeat_failed_cb) \ + X(apm_set_server_heartbeat_started_cb) \ + X(apm_set_server_heartbeat_succeeded_cb) \ + X(apm_set_server_opening_cb) \ + X(apm_set_topology_changed_cb) \ + X(apm_set_topology_closed_cb) \ + X(apm_set_topology_opening_cb) \ + X(apm_topology_changed_get_context) \ + X(apm_topology_changed_get_new_description) \ + X(apm_topology_changed_get_previous_description) \ + X(apm_topology_changed_get_topology_id) \ + X(apm_topology_closed_get_context) \ + X(apm_topology_closed_get_topology_id) \ + X(apm_topology_opening_get_context) \ + X(apm_topology_opening_get_topology_id) \ + X(auto_encryption_opts_destroy) \ + X(auto_encryption_opts_new) \ + X(auto_encryption_opts_set_bypass_auto_encryption) \ + X(auto_encryption_opts_set_bypass_query_analysis) \ + X(auto_encryption_opts_set_encrypted_fields_map) \ + X(auto_encryption_opts_set_extra) \ + X(auto_encryption_opts_set_keyvault_client_pool) \ + X(auto_encryption_opts_set_keyvault_client) \ + X(auto_encryption_opts_set_keyvault_namespace) \ + X(auto_encryption_opts_set_kms_providers) \ + X(auto_encryption_opts_set_schema_map) \ + X(auto_encryption_opts_set_tls_opts) \ + X(bulk_operation_destroy) \ + X(bulk_operation_execute) \ + X(bulk_operation_get_write_concern) \ + X(bulk_operation_insert_with_opts) \ + X(bulk_operation_new) \ + X(bulk_operation_remove_many_with_opts) \ + X(bulk_operation_remove_one_with_opts) \ + X(bulk_operation_replace_one_with_opts) \ + X(bulk_operation_set_bypass_document_validation) \ + X(bulk_operation_set_client_session) \ + X(bulk_operation_set_client) \ + X(bulk_operation_set_collection) \ + X(bulk_operation_set_database) \ + X(bulk_operation_set_write_concern) \ + X(bulk_operation_update_many_with_opts) \ + X(bulk_operation_update_one_with_opts) \ + X(change_stream_destroy) \ + X(change_stream_error_document) \ + X(change_stream_get_resume_token) \ + X(change_stream_next) \ + X(cleanup) \ + X(client_command_simple_with_server_id) \ + X(client_destroy) \ + X(client_enable_auto_encryption) \ + X(client_encryption_add_key_alt_name) \ + X(client_encryption_create_datakey) \ + X(client_encryption_create_encrypted_collection) \ + X(client_encryption_datakey_opts_destroy) \ + X(client_encryption_datakey_opts_new) \ + X(client_encryption_datakey_opts_set_keyaltnames) \ + X(client_encryption_datakey_opts_set_keymaterial) \ + X(client_encryption_datakey_opts_set_masterkey) \ + X(client_encryption_decrypt) \ + X(client_encryption_delete_key) \ + X(client_encryption_destroy) \ + X(client_encryption_encrypt_expression) \ + X(client_encryption_encrypt_opts_destroy) \ + X(client_encryption_encrypt_opts_new) \ + X(client_encryption_encrypt_opts_set_algorithm) \ + X(client_encryption_encrypt_opts_set_contention_factor) \ + X(client_encryption_encrypt_opts_set_keyaltname) \ + X(client_encryption_encrypt_opts_set_keyid) \ + X(client_encryption_encrypt_opts_set_query_type) \ + X(client_encryption_encrypt_opts_set_range_opts) \ + X(client_encryption_encrypt_opts_set_text_opts) \ + X(client_encryption_encrypt_range_opts_destroy) \ + X(client_encryption_encrypt_range_opts_new) \ + X(client_encryption_encrypt_range_opts_set_max) \ + X(client_encryption_encrypt_range_opts_set_min) \ + X(client_encryption_encrypt_range_opts_set_precision) \ + X(client_encryption_encrypt_range_opts_set_sparsity) \ + X(client_encryption_encrypt_range_opts_set_trim_factor) \ + X(client_encryption_encrypt_text_opts_destroy) \ + X(client_encryption_encrypt_text_opts_new) \ + X(client_encryption_encrypt_text_opts_set_case_sensitive) \ + X(client_encryption_encrypt_text_opts_set_diacritic_sensitive) \ + X(client_encryption_encrypt_text_opts_set_prefix) \ + X(client_encryption_encrypt_text_opts_set_suffix) \ + X(client_encryption_encrypt_text_opts_set_substring) \ + X(client_encryption_encrypt_text_prefix_opts_destroy) \ + X(client_encryption_encrypt_text_prefix_opts_new) \ + X(client_encryption_encrypt_text_prefix_opts_set_str_min_query_length) \ + X(client_encryption_encrypt_text_prefix_opts_set_str_max_query_length) \ + X(client_encryption_encrypt_text_suffix_opts_destroy) \ + X(client_encryption_encrypt_text_suffix_opts_new) \ + X(client_encryption_encrypt_text_suffix_opts_set_str_min_query_length) \ + X(client_encryption_encrypt_text_suffix_opts_set_str_max_query_length) \ + X(client_encryption_encrypt_text_substring_opts_destroy) \ + X(client_encryption_encrypt_text_substring_opts_new) \ + X(client_encryption_encrypt_text_substring_opts_set_str_min_query_length)\ + X(client_encryption_encrypt_text_substring_opts_set_str_max_query_length)\ + X(client_encryption_encrypt_text_substring_opts_set_str_max_length) \ + X(client_encryption_encrypt) \ + X(client_encryption_get_key_by_alt_name) \ + X(client_encryption_get_key) \ + X(client_encryption_get_keys) \ + X(client_encryption_new) \ + X(client_encryption_opts_destroy) \ + X(client_encryption_opts_new) \ + X(client_encryption_opts_set_keyvault_client) \ + X(client_encryption_opts_set_keyvault_namespace) \ + X(client_encryption_opts_set_kms_providers) \ + X(client_encryption_opts_set_tls_opts) \ + X(client_encryption_remove_key_alt_name) \ + X(client_encryption_rewrap_many_datakey_result_destroy) \ + X(client_encryption_rewrap_many_datakey_result_get_bulk_write_result) \ + X(client_encryption_rewrap_many_datakey_result_new) \ + X(client_encryption_rewrap_many_datakey) \ + X(client_find_databases_with_opts) \ + X(client_get_collection) \ + X(client_get_database_names_with_opts) \ + X(client_get_database) \ + X(client_get_read_concern) \ + X(client_get_read_prefs) \ + X(client_get_uri) \ + X(client_get_write_concern) \ + X(client_new_from_uri) \ + X(client_pool_destroy) \ + X(client_pool_enable_auto_encryption) \ + X(client_pool_new_with_error) \ + X(client_pool_new) \ + X(client_pool_pop) \ + X(client_pool_push) \ + X(client_pool_set_apm_callbacks) \ + X(client_pool_set_server_api) \ + X(client_pool_try_pop) \ + X(client_reset) \ + X(client_select_server) \ + X(client_session_abort_transaction) \ + X(client_session_advance_cluster_time) \ + X(client_session_advance_operation_time) \ + X(client_session_append) \ + X(client_session_commit_transaction) \ + X(client_session_destroy) \ + X(client_session_get_cluster_time) \ + X(client_session_get_dirty) \ + X(client_session_get_lsid) \ + X(client_session_get_operation_time) \ + X(client_session_get_opts) \ + X(client_session_get_server_id) \ + X(client_session_get_transaction_state) \ + X(client_session_in_transaction) \ + X(client_session_start_transaction) \ + X(client_session_with_transaction) \ + X(client_set_apm_callbacks) \ + X(client_set_read_concern) \ + X(client_set_read_prefs) \ + X(client_set_server_api) \ + X(client_set_write_concern) \ + X(client_start_session) \ + X(client_watch) \ + X(collection_aggregate) \ + X(collection_command_simple) \ + X(collection_copy) \ + X(collection_count_documents) \ + X(collection_create_bulk_operation_with_opts) \ + X(collection_destroy) \ + X(collection_drop_index) \ + X(collection_drop_with_opts) \ + X(collection_drop) \ + X(collection_estimated_document_count) \ + X(collection_find_and_modify_with_opts) \ + X(collection_find_indexes_with_opts) \ + X(collection_find_with_opts) \ + X(collection_get_name) \ + X(collection_get_read_concern) \ + X(collection_get_read_prefs) \ + X(collection_get_write_concern) \ + X(collection_keys_to_index_string) \ + X(collection_read_command_with_opts) \ + X(collection_rename_with_opts) \ + X(collection_rename) \ + X(collection_set_read_concern) \ + X(collection_set_read_prefs) \ + X(collection_set_write_concern) \ + X(collection_watch) \ + X(collection_write_command_with_opts) \ + X(cursor_destroy) \ + X(cursor_error_document) \ + X(cursor_error) \ + X(cursor_new_from_command_reply_with_opts) \ + X(cursor_next) \ + X(cursor_set_max_await_time_ms) \ + X(database_aggregate) \ + X(database_command_with_opts) \ + X(database_copy) \ + X(database_create_collection) \ + X(database_destroy) \ + X(database_drop_with_opts) \ + X(database_drop) \ + X(database_find_collections_with_opts) \ + X(database_get_collection_names_with_opts) \ + X(database_get_collection) \ + X(database_get_read_concern) \ + X(database_get_read_prefs) \ + X(database_get_write_concern) \ + X(database_has_collection) \ + X(database_set_read_concern) \ + X(database_set_read_prefs) \ + X(database_set_write_concern) \ + X(database_watch) \ + X(error_has_label) \ + X(find_and_modify_opts_append) \ + X(find_and_modify_opts_destroy) \ + X(find_and_modify_opts_new) \ + X(find_and_modify_opts_set_bypass_document_validation) \ + X(find_and_modify_opts_set_fields) \ + X(find_and_modify_opts_set_flags) \ + X(find_and_modify_opts_set_max_time_ms) \ + X(find_and_modify_opts_set_sort) \ + X(find_and_modify_opts_set_update) \ + X(handshake_data_append) \ + X(init) \ + /* X(log_set_handler) CDRIVER-5678: not __cdecl. */ \ + X(read_concern_copy) \ + X(read_concern_destroy) \ + X(read_concern_get_level) \ + X(read_concern_new) \ + X(read_concern_set_level) \ + X(read_prefs_copy) \ + X(read_prefs_destroy) \ + BSONCXX_SUPPRESS_DEPRECATION_WARNINGS_BEGIN \ + X(read_prefs_get_hedge) /* CXX-3241 */ \ + BSONCXX_SUPPRESS_DEPRECATION_WARNINGS_END \ + X(read_prefs_get_max_staleness_seconds) \ + X(read_prefs_get_mode) \ + X(read_prefs_get_tags) \ + X(read_prefs_new) \ + BSONCXX_SUPPRESS_DEPRECATION_WARNINGS_BEGIN \ + X(read_prefs_set_hedge) /* CXX-3241 */ \ + BSONCXX_SUPPRESS_DEPRECATION_WARNINGS_END \ + X(read_prefs_set_max_staleness_seconds) \ + X(read_prefs_set_mode) \ + X(read_prefs_set_tags) \ + X(server_api_copy) \ + X(server_api_deprecation_errors) \ + X(server_api_destroy) \ + X(server_api_get_deprecation_errors) \ + X(server_api_get_strict) \ + X(server_api_get_version) \ + X(server_api_new) \ + X(server_api_strict) \ + X(server_api_version_from_string) \ + X(server_api_version_to_string) \ + X(server_description_hello_response) \ + X(server_description_host) \ + X(server_description_id) \ + X(server_description_round_trip_time) \ + X(server_description_type) \ + X(server_descriptions_destroy_all) \ + X(session_opts_destroy) \ + X(session_opts_get_causal_consistency) \ + X(session_opts_get_snapshot) \ + X(session_opts_new) \ + X(session_opts_set_causal_consistency) \ + X(session_opts_set_default_transaction_opts) \ + X(session_opts_set_snapshot) \ + X(topology_description_get_servers) \ + X(topology_description_has_readable_server) \ + X(topology_description_has_writable_server) \ + X(topology_description_type) \ + X(transaction_opts_clone) \ + X(transaction_opts_destroy) \ + X(transaction_opts_get_max_commit_time_ms) \ + X(transaction_opts_get_read_concern) \ + X(transaction_opts_get_read_prefs) \ + X(transaction_opts_get_write_concern) \ + X(transaction_opts_new) \ + X(transaction_opts_set_max_commit_time_ms) \ + X(transaction_opts_set_read_concern) \ + X(transaction_opts_set_read_prefs) \ + X(transaction_opts_set_write_concern) \ + X(uri_copy) \ + X(uri_destroy) \ + X(uri_get_auth_mechanism) \ + X(uri_get_auth_source) \ + X(uri_get_compressors) \ + X(uri_get_credentials) \ + X(uri_get_database) \ + X(uri_get_hosts) \ + X(uri_get_option_as_utf8) \ + X(uri_get_options) \ + X(uri_get_password) \ + X(uri_get_read_concern) \ + X(uri_get_read_prefs_t) \ + X(uri_get_replica_set) \ + X(uri_get_string) \ + X(uri_get_tls) \ + X(uri_get_username) \ + X(uri_get_write_concern) \ + X(uri_new_with_error) \ + X(write_concern_copy) \ + X(write_concern_destroy) \ + X(write_concern_get_journal) \ + X(write_concern_get_w) \ + X(write_concern_get_wmajority) \ + X(write_concern_get_wtag) \ + X(write_concern_get_wtimeout) \ + X(write_concern_get_wtimeout_int64) \ + X(write_concern_is_acknowledged) \ + X(write_concern_journal_is_set) \ + X(write_concern_new) \ + X(write_concern_set_journal) \ + X(write_concern_set_w) \ + X(write_concern_set_wmajority) \ + X(write_concern_set_wtag) \ + X(write_concern_set_wtimeout) \ X(write_concern_set_wtimeout_int64) namespace mongocxx { diff --git a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/encrypt.cpp b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/encrypt.cpp index e11f7dc38a..3eee5f858f 100644 --- a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/encrypt.cpp +++ b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/encrypt.cpp @@ -79,6 +79,15 @@ bsoncxx::v_noabi::stdx::optional const& encrypt::range_opts() co return _range_opts; } +encrypt& encrypt::text_opts(options::text opts) { + _text_opts = std::move(opts); + return *this; +} + +bsoncxx::v_noabi::stdx::optional const& encrypt::text_opts() const { + return _text_opts; +} + void* encrypt::convert() const { struct encrypt_opts_deleter { void operator()(mongoc_client_encryption_encrypt_opts_t* ptr) noexcept { @@ -128,6 +137,9 @@ void* encrypt::convert() const { case encryption_algorithm::k_range: libmongoc::client_encryption_encrypt_opts_set_algorithm(opts, MONGOC_ENCRYPT_ALGORITHM_RANGE); break; + case encryption_algorithm::k_textPreview: + libmongoc::client_encryption_encrypt_opts_set_algorithm(opts, MONGOC_ENCRYPT_ALGORITHM_TEXTPREVIEW); + break; default: throw exception{error_code::k_invalid_parameter, "unsupported encryption algorithm"}; } @@ -147,6 +159,15 @@ void* encrypt::convert() const { case encryption_query_type::k_range: libmongoc::client_encryption_encrypt_opts_set_query_type(opts, MONGOC_ENCRYPT_QUERY_TYPE_RANGE); break; + case encryption_query_type::k_prefixPreview: + libmongoc::client_encryption_encrypt_opts_set_query_type(opts, MONGOC_ENCRYPT_QUERY_TYPE_PREFIXPREVIEW); + break; + case encryption_query_type::k_suffixPreview: + libmongoc::client_encryption_encrypt_opts_set_query_type(opts, MONGOC_ENCRYPT_QUERY_TYPE_SUFFIXPREVIEW); + break; + case encryption_query_type::k_substringPreview: + libmongoc::client_encryption_encrypt_opts_set_query_type(opts, MONGOC_ENCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW); + break; default: throw exception{error_code::k_invalid_parameter, "unsupported query type"}; } @@ -194,6 +215,125 @@ void* encrypt::convert() const { libmongoc::client_encryption_encrypt_opts_set_range_opts(opts, range_opts); } + if (_text_opts) { + struct text_opts_deleter { + void operator()(mongoc_client_encryption_encrypt_text_opts_t* ptr) noexcept { + libmongoc::client_encryption_encrypt_text_opts_destroy(ptr); + } + }; + + auto text_opts_owner = std::unique_ptr( + libmongoc::client_encryption_encrypt_text_opts_new()); + auto const text_opts = text_opts_owner.get(); + + auto const& case_sensitive = _text_opts->case_sensitive(); + auto const& diacritic_sensitive = _text_opts->diacritic_sensitive(); + auto const& prefix = _text_opts->prefix(); + auto const& suffix = _text_opts->suffix(); + auto const& substring = _text_opts->substring(); + + if (case_sensitive) { + libmongoc::client_encryption_encrypt_text_opts_set_case_sensitive(text_opts, case_sensitive.value()); + } + + if (diacritic_sensitive) { + libmongoc::client_encryption_encrypt_text_opts_set_diacritic_sensitive( + text_opts, diacritic_sensitive.value()); + } + + if (prefix) { + struct prefix_opts_deleter { + void operator()(mongoc_client_encryption_encrypt_text_prefix_opts_t* ptr) noexcept { + libmongoc::client_encryption_encrypt_text_prefix_opts_destroy(ptr); + } + }; + + auto prefix_opts_owner = + std::unique_ptr( + libmongoc::client_encryption_encrypt_text_prefix_opts_new()); + auto const prefix_opts = prefix_opts_owner.get(); + + auto const& str_max_query_length = prefix->str_max_query_length(); + auto const& str_min_query_length = prefix->str_min_query_length(); + + if (str_max_query_length) { + libmongoc::client_encryption_encrypt_text_prefix_opts_set_str_max_query_length( + prefix_opts, str_max_query_length.value()); + } + + if (str_min_query_length) { + libmongoc::client_encryption_encrypt_text_prefix_opts_set_str_min_query_length( + prefix_opts, str_min_query_length.value()); + } + + libmongoc::client_encryption_encrypt_text_opts_set_prefix(text_opts, prefix_opts); + } + + if (suffix) { + struct suffix_opts_deleter { + void operator()(mongoc_client_encryption_encrypt_text_suffix_opts_t* ptr) noexcept { + libmongoc::client_encryption_encrypt_text_suffix_opts_destroy(ptr); + } + }; + + auto suffix_opts_owner = + std::unique_ptr( + libmongoc::client_encryption_encrypt_text_suffix_opts_new()); + auto const suffix_opts = suffix_opts_owner.get(); + + auto const& str_max_query_length = suffix->str_max_query_length(); + auto const& str_min_query_length = suffix->str_min_query_length(); + + if (str_max_query_length) { + libmongoc::client_encryption_encrypt_text_suffix_opts_set_str_max_query_length( + suffix_opts, str_max_query_length.value()); + } + + if (str_min_query_length) { + libmongoc::client_encryption_encrypt_text_suffix_opts_set_str_min_query_length( + suffix_opts, str_min_query_length.value()); + } + + libmongoc::client_encryption_encrypt_text_opts_set_suffix(text_opts, suffix_opts); + } + + if (substring) { + struct substring_opts_deleter { + void operator()(mongoc_client_encryption_encrypt_text_substring_opts_t* ptr) noexcept { + libmongoc::client_encryption_encrypt_text_substring_opts_destroy(ptr); + } + }; + + auto substring_opts_owner = + std::unique_ptr( + libmongoc::client_encryption_encrypt_text_substring_opts_new()); + auto const substring_opts = substring_opts_owner.get(); + + auto const& str_max_query_length = substring->str_max_query_length(); + auto const& str_min_query_length = substring->str_min_query_length(); + auto const& str_max_length = substring->str_max_length(); + + if (str_max_query_length) { + libmongoc::client_encryption_encrypt_text_substring_opts_set_str_max_query_length( + substring_opts, str_max_query_length.value()); + } + + if (str_min_query_length) { + libmongoc::client_encryption_encrypt_text_substring_opts_set_str_min_query_length( + substring_opts, str_min_query_length.value()); + } + + if (str_max_length) { + libmongoc::client_encryption_encrypt_text_substring_opts_set_str_max_length( + substring_opts, str_max_length.value()); + } + + libmongoc::client_encryption_encrypt_text_opts_set_substring(text_opts, substring_opts); + } + + libmongoc::client_encryption_encrypt_opts_set_text_opts(opts, text_opts); + } + return opts_owner.release(); } diff --git a/src/mongocxx/test/v_noabi/client_side_encryption.cpp b/src/mongocxx/test/v_noabi/client_side_encryption.cpp index 4a4a0c4a71..281a194ad7 100644 --- a/src/mongocxx/test/v_noabi/client_side_encryption.cpp +++ b/src/mongocxx/test/v_noabi/client_side_encryption.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -51,6 +52,7 @@ #include #include +#include #include @@ -1955,6 +1957,31 @@ TEST_CASE("KMS TLS Options Tests", "[client_side_encryption][!mayfail]") { } } +void _drop_and_create_collection( + std::string const& db_name, + std::string const& coll_name, + bsoncxx::stdx::optional encrypted_fields_path) { + mongocxx::client client{ + uri{}, + test_util::add_test_server_api(), + }; + + auto opts_doc_builder = bsoncxx::builder::basic::document{}; + if (encrypted_fields_path.has_value()) { + auto encrypted_fields = _doc_from_file(encrypted_fields_path.value()); + opts_doc_builder.append(kvp("encryptedFields", encrypted_fields)); + } + bsoncxx::document::value opts_doc{opts_doc_builder.extract()}; + + write_concern wc_majority; + wc_majority.acknowledge_level(write_concern::level::k_majority); + + auto coll = client[db_name][coll_name]; + coll.drop(wc_majority, opts_doc.view()); + + client[db_name].create_collection(coll_name, opts_doc.view(), wc_majority); +} + // https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.md#test-setup std::tuple _setup_explicit_encryption( bsoncxx::document::view key1_document, @@ -1970,28 +1997,10 @@ std::tuple _setup_explicit_encryp // Drop and create the collection db.explicit_encryption using // encryptedFields as an option. See FLE 2 CreateCollection() and // Collection.Drop(). - { - write_concern wc_majority; - wc_majority.acknowledge_level(write_concern::level::k_majority); - - auto coll = client["db"]["explicit_encryption"]; - auto drop_doc = make_document(kvp("encryptedFields", encrypted_fields)); - coll.drop(wc_majority, drop_doc.view()); - - client["db"].create_collection("explicit_encryption", drop_doc.view(), wc_majority); - } + _drop_and_create_collection("db", "explicit_encryption", "/explicit-encryption/encryptedFields.json"); // Drop and create the collection keyvault.datakeys. - { - write_concern wc_majority; - wc_majority.acknowledge_level(write_concern::level::k_majority); - - auto coll = client["keyvault"]["datakeys"]; - coll.drop(wc_majority); - - auto const empty_doc = make_document(); - client["keyvault"].create_collection("datakeys", empty_doc.view(), wc_majority); - } + _drop_and_create_collection("keyvault", "datakeys", bsoncxx::stdx::nullopt); // Insert key1Document in keyvault.datakeys with majority write concern. { @@ -3471,4 +3480,102 @@ TEST_CASE("16. Rewrap. Case 2: RewrapManyDataKeyOpts.provider is not optional", Catch::Matchers::ContainsSubstring("expected 'provider' to be set to identify type of 'master_key'")); } +TEST_CASE("Text Explicit Encryption", "[client_side_encryption]") { + CLIENT_SIDE_ENCRYPTION_ENABLED_OR_SKIP(); + + mongocxx::client conn{ + mongocxx::uri{}, + test_util::add_test_server_api(), + }; + + if (!test_util::server_version_is_at_least("8.1")) { + SKIP("MongoDB server 8.1 or newer required"); + } + + if (test_util::get_topology() == "single") { + SKIP("must not run against a standalone server"); + } + + // Load the file key1-document.json as key1Document. + auto key1_document = _doc_from_file("/explicit-encryption/key1-document.json"); + + // Read the "_id" field of key1Document as key1ID. + auto key1_id = key1_document["_id"].get_value(); + + mongocxx::client key_vault_client{ + uri{}, + test_util::add_test_server_api(), + }; + auto [client_encryption, encrypted_client] = _setup_explicit_encryption(key1_document, &key_vault_client); + _drop_and_create_collection("db", "prefix-suffix", "/explicit-encryption/encryptedFields-prefix-suffix.json"); + _drop_and_create_collection("db", "substring", "/explicit-encryption/encryptedFields-substring.json"); + + auto const prefix_opts = options::prefix().str_max_query_length(10).str_min_query_length(2); + auto const suffix_opts = options::suffix().str_max_query_length(10).str_min_query_length(2); + auto const substring_opts = + options::substring().str_max_length(10).str_max_query_length(10).str_min_query_length(2); + + auto const default_encrypt_opts = [&]() { + return options::encrypt() + .key_id(key1_id) + .algorithm(options::encrypt::encryption_algorithm::k_textPreview) + .contention_factor(0); + }; + auto const default_text_opts = [&]() { + return options::text().case_sensitive(true).diacritic_sensitive(true); + }; + + const auto foobarbaz_doc = make_document(kvp("_id", 0), kvp("encryptedText", "foobarbaz")); + + auto client_substring = encrypted_client["db"]["substring"]; + auto client_prefix_suffix = encrypted_client["db"]["prefix-suffix"]; + { + // Use clientEncryption to encrypt the string "foobarbaz" with the following EncryptOpts: + // TODO + auto const encrypt_opts = + default_encrypt_opts().text_opts(default_text_opts().prefix(prefix_opts).suffix(suffix_opts)); + auto const encrypted_foobarbaz = client_encryption.encrypt(make_value("foobarbaz"), encrypt_opts); + + // Use encryptedClient to insert the following document into db.prefix-suffix with majority write concern: + client_prefix_suffix.insert_one(make_document(kvp("_id", 0), kvp("encryptedText", encrypted_foobarbaz))); + } + + // TODO same for substring + { + // Use clientEncryption to encrypt the string "foobarbaz" with the following EncryptOpts: + // TODO + auto const encrypt_opts = default_encrypt_opts().text_opts(default_text_opts().substring(substring_opts)); + auto const encrypted_foobarbaz = client_encryption.encrypt(make_value("foobarbaz"), encrypt_opts); + + // Use encryptedClient to insert the following document into db.prefix-suffix with majority write concern: + client_substring.insert_one(make_document(kvp("_id", 0), kvp("encryptedText", encrypted_foobarbaz))); + } + + SECTION("can find a document by prefix") { + auto const encrypt_opts = default_encrypt_opts() + .query_type(options::encrypt::encryption_query_type::k_prefixPreview) + .text_opts(default_text_opts().prefix(prefix_opts)); + auto const encrypted_foo = client_encryption.encrypt(make_value("foo"), encrypt_opts); + auto const query = make_document( + kvp("$expr", make_document(kvp("$encStrStartsWith", make_document(kvp("input", "$encryptedText"), kvp("prefix", encrypted_foo)))))); + + auto cursor = client_prefix_suffix.find(query.view()); + auto const found = std::vector(cursor.begin(), cursor.end()); + REQUIRE(found.size() == 1); + REQUIRE(found == std::vector{foobarbaz_doc}); + std::cout << bsoncxx::to_json(found[0].view()) << std::endl; + // TODO expected + } + + SECTION("can find a document by suffix") {} + + SECTION("assert no document found by prefix") {} + + SECTION("assert no document found by suffix") {} + + SECTION("can find a document by substring") {} + + SECTION("assert no document found by substring") {} +} + } // namespace From 5cf48d8b204fe48438a4333d556fba90b6d993f5 Mon Sep 17 00:00:00 2001 From: mdb-ad <198671546+mdb-ad@users.noreply.github.com> Date: Wed, 3 Dec 2025 19:14:02 -0800 Subject: [PATCH 2/5] v1 abi relocation --- .../mongocxx/options/prefix-fwd.hpp => v1/prefix_options-fwd.hpp} | 0 .../mongocxx/options/prefix.hpp => v1/prefix_options.hpp} | 0 .../options/substring-fwd.hpp => v1/substring_options-fwd.hpp} | 0 .../mongocxx/options/substring.hpp => v1/substring_options.hpp} | 0 .../mongocxx/options/suffix-fwd.hpp => v1/suffix_options-fwd.hpp} | 0 .../mongocxx/options/suffix.hpp => v1/suffix_options.hpp} | 0 .../mongocxx/options/text-fwd.hpp => v1/text_options-fwd.hpp} | 0 .../{v_noabi/mongocxx/options/text.hpp => v1/text_options.hpp} | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename src/mongocxx/include/mongocxx/{v_noabi/mongocxx/options/prefix-fwd.hpp => v1/prefix_options-fwd.hpp} (100%) rename src/mongocxx/include/mongocxx/{v_noabi/mongocxx/options/prefix.hpp => v1/prefix_options.hpp} (100%) rename src/mongocxx/include/mongocxx/{v_noabi/mongocxx/options/substring-fwd.hpp => v1/substring_options-fwd.hpp} (100%) rename src/mongocxx/include/mongocxx/{v_noabi/mongocxx/options/substring.hpp => v1/substring_options.hpp} (100%) rename src/mongocxx/include/mongocxx/{v_noabi/mongocxx/options/suffix-fwd.hpp => v1/suffix_options-fwd.hpp} (100%) rename src/mongocxx/include/mongocxx/{v_noabi/mongocxx/options/suffix.hpp => v1/suffix_options.hpp} (100%) rename src/mongocxx/include/mongocxx/{v_noabi/mongocxx/options/text-fwd.hpp => v1/text_options-fwd.hpp} (100%) rename src/mongocxx/include/mongocxx/{v_noabi/mongocxx/options/text.hpp => v1/text_options.hpp} (100%) diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/prefix-fwd.hpp b/src/mongocxx/include/mongocxx/v1/prefix_options-fwd.hpp similarity index 100% rename from src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/prefix-fwd.hpp rename to src/mongocxx/include/mongocxx/v1/prefix_options-fwd.hpp diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/prefix.hpp b/src/mongocxx/include/mongocxx/v1/prefix_options.hpp similarity index 100% rename from src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/prefix.hpp rename to src/mongocxx/include/mongocxx/v1/prefix_options.hpp diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/substring-fwd.hpp b/src/mongocxx/include/mongocxx/v1/substring_options-fwd.hpp similarity index 100% rename from src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/substring-fwd.hpp rename to src/mongocxx/include/mongocxx/v1/substring_options-fwd.hpp diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/substring.hpp b/src/mongocxx/include/mongocxx/v1/substring_options.hpp similarity index 100% rename from src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/substring.hpp rename to src/mongocxx/include/mongocxx/v1/substring_options.hpp diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/suffix-fwd.hpp b/src/mongocxx/include/mongocxx/v1/suffix_options-fwd.hpp similarity index 100% rename from src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/suffix-fwd.hpp rename to src/mongocxx/include/mongocxx/v1/suffix_options-fwd.hpp diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/suffix.hpp b/src/mongocxx/include/mongocxx/v1/suffix_options.hpp similarity index 100% rename from src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/suffix.hpp rename to src/mongocxx/include/mongocxx/v1/suffix_options.hpp diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text-fwd.hpp b/src/mongocxx/include/mongocxx/v1/text_options-fwd.hpp similarity index 100% rename from src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text-fwd.hpp rename to src/mongocxx/include/mongocxx/v1/text_options-fwd.hpp diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text.hpp b/src/mongocxx/include/mongocxx/v1/text_options.hpp similarity index 100% rename from src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text.hpp rename to src/mongocxx/include/mongocxx/v1/text_options.hpp From a36bfc0f9b094d6034e23d4fc04433e965a0a9b6 Mon Sep 17 00:00:00 2001 From: mdb-ad <198671546+mdb-ad@users.noreply.github.com> Date: Wed, 3 Dec 2025 20:17:02 -0800 Subject: [PATCH 3/5] text_options in v1 ABI --- .../include/mongocxx/v1/text_options.hpp | 400 ++++++++++++++---- 1 file changed, 320 insertions(+), 80 deletions(-) diff --git a/src/mongocxx/include/mongocxx/v1/text_options.hpp b/src/mongocxx/include/mongocxx/v1/text_options.hpp index 38e9500cda..34bbb826de 100644 --- a/src/mongocxx/include/mongocxx/v1/text_options.hpp +++ b/src/mongocxx/include/mongocxx/v1/text_options.hpp @@ -14,108 +14,348 @@ #pragma once -#include // IWYU pragma: export - -#include -#include -#include - -// - #include #include namespace mongocxx { -namespace v_noabi { -namespace options { +namespace v_1 { /// -/// Used by @ref mongocxx::v_noabi::options::encrypt::text_opts. +/// Options related to text_options queries for Queryable Encryption. +/// +/// Supported fields include: +/// - `case_sensitive` ("caseSensitive") +/// - `diacritic_sensitive` ("diacriticSensitive") +/// - `prefix` +/// - `suffix` +/// - `substring` /// -/// Specifies index options (`TextOpts`) for a Queryable Encryption field supporting "textPreview" -/// queries. +/// @see +/// - [Client Side Encryption (MongoDB Specifications)](https://specifications.readthedocs.io/en/latest/client-side-encryption/client-side-encryption/) +/// - [Encrypted Fields and Enabled Queries (MongoDB Manual)](https://www.mongodb.com/docs/manual/core/queryable-encryption/fundamentals/encrypt-and-query/) /// -/// @note `caseSensitive`, `diacriticSensitive`, `prefix`, `suffix`, and `substring` must match the values set in the -/// encryptedFields of the destination collection. +/// @attention This feature is experimental! It is not ready for use! /// -class text { +class text_options { public: + class prefix; + class suffix; + class substring; + + /// + /// Destroy this object. + /// + /// @warning Invalidates all associated views. + /// + MONGOCXX_ABI_EXPORT_CDECL() ~text_options(); + + /// + /// Move constructor. + /// + /// @par Postconditions: + /// - `other` is in an assign-or-destroy-only state. + /// + MONGOCXX_ABI_EXPORT_CDECL() text_options(text_options&& other) noexcept; + + /// + /// Move assignment. + /// + /// @par Postconditions: + /// - `other` is in an assign-or-destroy-only state. + /// + MONGOCXX_ABI_EXPORT_CDECL(text_options&) operator=(text_options&& other) noexcept; + + /// + /// Copy construction. + /// + MONGOCXX_ABI_EXPORT_CDECL() text_options(text_options const& other); + + /// + /// Copy assignment. + /// + MONGOCXX_ABI_EXPORT_CDECL(text_options&) operator=(text_options const& other); + /// /// Default initialization. /// - text() = default; - - /// @brief Sets `TextOpts.caseSensitive` - text& case_sensitive(bool value) { - _case_sensitive = value; - return *this; - } - - /// @brief Gets `TextOpts.caseSensitive` - bsoncxx::v_noabi::stdx::optional const& case_sensitive() const { - return _case_sensitive; - } - - /// @brief Sets `TextOpts.diacriticSensitive` - text& diacritic_sensitive(bool value) { - _diacritic_sensitive = value; - return *this; - } - - /// @brief Gets `TextOpts.diacriticSensitive` - bsoncxx::v_noabi::stdx::optional const& diacritic_sensitive() const { - return _diacritic_sensitive; - } - - /// @brief Sets `TextOpts.PrefixOpts` - text& prefix(options::prefix opts) { - _prefix = opts; - return *this; - } - - /// @brief Gets `TextOpts.PrefixOpts` - bsoncxx::v_noabi::stdx::optional const& prefix() const { - return _prefix; - } - - /// @brief Sets `TextOpts.SuffixOpts` - text& suffix(options::suffix opts) { - _suffix = opts; - return *this; - } - - /// @brief Gets `TextOpts.SuffixOpts` - bsoncxx::v_noabi::stdx::optional const& suffix() const { - return _suffix; - } - - /// @brief Sets `TextOpts.SubstringOpts` - text& substring(options::substring opts) { - _substring = opts; - return *this; - } - - /// @brief Gets `TextOpts.SubstringOpts` - bsoncxx::v_noabi::stdx::optional const& substring() const { - return _substring; - } + /// @par Postconditions: + /// - All supported fields are "unset" or zero-initialized. + /// + MONGOCXX_ABI_EXPORT_CDECL() text_options(); + + /// + /// Set the "caseSensitive" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(text_options&) case_sensitive(bool value); + + /// + /// Gets the current "caseSensitive" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional) const& case_sensitive() const; + + /// + /// Set the "diacriticSensitive" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(text_options&) diacritic_sensitive(bool value); + + /// + /// Gets the current "diacriticSensitive" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional) const& diacritic_sensitive() const; + + /// + /// Sets the "prefix" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(text_options&) prefix_opts(prefix opts); + + /// + /// Gets the current "prefix" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional const&) prefix_opts() const; + + /// + /// Sets the "suffix" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(text_options&) suffix_opts(suffix opts); + + /// + /// Gets the current "suffix" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional const&) suffix_opts() const; + + /// + /// Sets the "substring" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(text_options&) substring_opts(substring opts); + + /// + /// Gets the current "substring" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional const&) substring_opts() const; private: - bsoncxx::v_noabi::stdx::optional _case_sensitive; - bsoncxx::v_noabi::stdx::optional _diacritic_sensitive; - bsoncxx::v_noabi::stdx::optional _prefix; - bsoncxx::v_noabi::stdx::optional _suffix; - bsoncxx::v_noabi::stdx::optional _substring; + class impl; + void* _impl; +}; + +class text_options::prefix { + private: + class impl; + void* _impl; + + public: + /// + /// Destroy this object. + /// + /// @warning Invalidates all associated views. + /// + MONGOCXX_ABI_EXPORT_CDECL() ~prefix(); + + /// + /// Move constructor. + /// + /// @par Postconditions: + /// - `other` is in an assign-or-destroy-only state. + /// + MONGOCXX_ABI_EXPORT_CDECL() prefix(prefix&& other) noexcept; + + /// + /// Move assignment. + /// + /// @par Postconditions: + /// - `other` is in an assign-or-destroy-only state. + /// + MONGOCXX_ABI_EXPORT_CDECL(prefix&) operator=(prefix&& other) noexcept; + + /// + /// Copy construction. + /// + MONGOCXX_ABI_EXPORT_CDECL() prefix(prefix const& other); + + /// + /// Copy assignment. + /// + MONGOCXX_ABI_EXPORT_CDECL(prefix&) operator=(prefix const& other); + + /// + /// Default initialization. + /// + /// @par Postconditions: + /// - All supported fields are "unset" or zero-initialized. + /// + MONGOCXX_ABI_EXPORT_CDECL() prefix(); + + /// + /// Set the "strMaxQueryLength" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(prefix&) str_max_query_length(int32_t value); + + /// + /// Return the current "strMaxQueryLength" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional const&) str_max_query_length() const; + + /// + /// Set the "strminQueryLength" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(prefix&) str_min_query_length(int32_t value); + + /// + /// Return the current "strminQueryLength" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional const&) str_min_query_length() const; +}; +class text_options::suffix { + private: + class impl; + void* _impl; + + public: + /// + /// Destroy this object. + /// + /// @warning Invalidates all associated views. + /// + MONGOCXX_ABI_EXPORT_CDECL() ~suffix(); + + /// + /// Move constructor. + /// + /// @par Postconditions: + /// - `other` is in an assign-or-destroy-only state. + /// + MONGOCXX_ABI_EXPORT_CDECL() suffix(suffix&& other) noexcept; + + /// + /// Move assignment. + /// + /// @par Postconditions: + /// - `other` is in an assign-or-destroy-only state. + /// + MONGOCXX_ABI_EXPORT_CDECL(suffix&) operator=(suffix&& other) noexcept; + + /// + /// Copy construction. + /// + MONGOCXX_ABI_EXPORT_CDECL() suffix(suffix const& other); + + /// + /// Copy assignment. + /// + MONGOCXX_ABI_EXPORT_CDECL(suffix&) operator=(suffix const& other); + + /// + /// Default initialization. + /// + /// @par Postconditions: + /// - All supported fields are "unset" or zero-initialized. + /// + MONGOCXX_ABI_EXPORT_CDECL() suffix(); + + /// + /// Set the "strMaxQueryLength" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(suffix&) str_max_query_length(int32_t value); + + /// + /// Return the current "strMaxQueryLength" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional const&) str_max_query_length() const; + + /// + /// Set the "strminQueryLength" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(suffix&) str_min_query_length(int32_t value); + + /// + /// Return the current "strminQueryLength" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional const&) str_min_query_length() const; +}; +class text_options::substring { + private: + class impl; + void* _impl; + + public: + /// + /// Destroy this object. + /// + /// @warning Invalidates all associated views. + /// + MONGOCXX_ABI_EXPORT_CDECL() ~substring(); + + /// + /// Move constructor. + /// + /// @par Postconditions: + /// - `other` is in an assign-or-destroy-only state. + /// + MONGOCXX_ABI_EXPORT_CDECL() substring(substring&& other) noexcept; + + /// + /// Move assignment. + /// + /// @par Postconditions: + /// - `other` is in an assign-or-destroy-only state. + /// + MONGOCXX_ABI_EXPORT_CDECL(substring&) operator=(substring&& other) noexcept; + + /// + /// Copy construction. + /// + MONGOCXX_ABI_EXPORT_CDECL() substring(substring const& other); + + /// + /// Copy assignment. + /// + MONGOCXX_ABI_EXPORT_CDECL(substring&) operator=(substring const& other); + + /// + /// Default initialization. + /// + /// @par Postconditions: + /// - All supported fields are "unset" or zero-initialized. + /// + MONGOCXX_ABI_EXPORT_CDECL() substring(); + + /// + /// Set the "strMaxLength" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(substring&) str_max_length(int32_t value); + + /// + /// Return the current "strMaxLength" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional const&) str_max_length() const; + /// + /// Set the "strMaxQueryLength" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(substring&) str_max_query_length(int32_t value); + + /// + /// Return the current "strMaxQueryLength" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional const&) str_max_query_length() const; + + /// + /// Set the "strminQueryLength" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(substring&) str_min_query_length(int32_t value); + + /// + /// Return the current "strminQueryLength" field. + /// + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional const&) str_min_query_length() const; }; -} // namespace options -} // namespace v_noabi +} // namespace v_1 } // namespace mongocxx #include /// /// @file -/// Provides @ref mongocxx::v_noabi::options::text. +/// Provides @ref mongocxx::v1::text_options. /// From 06616e0e20362c00b497a5551d48d4eaea46c91c Mon Sep 17 00:00:00 2001 From: mdb-ad <198671546+mdb-ad@users.noreply.github.com> Date: Wed, 3 Dec 2025 21:33:48 -0800 Subject: [PATCH 4/5] v1 implementation --- .../include/mongocxx/v1/text_options.hpp | 26 +-- src/mongocxx/lib/mongocxx/v1/text_options.cpp | 211 ++++++++++++++++++ 2 files changed, 224 insertions(+), 13 deletions(-) create mode 100644 src/mongocxx/lib/mongocxx/v1/text_options.cpp diff --git a/src/mongocxx/include/mongocxx/v1/text_options.hpp b/src/mongocxx/include/mongocxx/v1/text_options.hpp index 34bbb826de..54258e4550 100644 --- a/src/mongocxx/include/mongocxx/v1/text_options.hpp +++ b/src/mongocxx/include/mongocxx/v1/text_options.hpp @@ -19,7 +19,7 @@ #include namespace mongocxx { -namespace v_1 { +namespace v1 { /// /// Options related to text_options queries for Queryable Encryption. @@ -92,7 +92,7 @@ class text_options { /// /// Gets the current "caseSensitive" field. /// - MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional) const& case_sensitive() const; + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional) case_sensitive() const; /// /// Set the "diacriticSensitive" field. @@ -102,7 +102,7 @@ class text_options { /// /// Gets the current "diacriticSensitive" field. /// - MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional) const& diacritic_sensitive() const; + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional) diacritic_sensitive() const; /// /// Sets the "prefix" field. @@ -194,17 +194,17 @@ class text_options::prefix { /// /// Return the current "strMaxQueryLength" field. /// - MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional const&) str_max_query_length() const; + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional) str_max_query_length() const; /// - /// Set the "strminQueryLength" field. + /// Set the "strMinQueryLength" field. /// MONGOCXX_ABI_EXPORT_CDECL(prefix&) str_min_query_length(int32_t value); /// - /// Return the current "strminQueryLength" field. + /// Return the current "strMinQueryLength" field. /// - MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional const&) str_min_query_length() const; + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional) str_min_query_length() const; }; class text_options::suffix { private: @@ -261,7 +261,7 @@ class text_options::suffix { /// /// Return the current "strMaxQueryLength" field. /// - MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional const&) str_max_query_length() const; + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional) str_max_query_length() const; /// /// Set the "strminQueryLength" field. @@ -271,7 +271,7 @@ class text_options::suffix { /// /// Return the current "strminQueryLength" field. /// - MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional const&) str_min_query_length() const; + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional) str_min_query_length() const; }; class text_options::substring { private: @@ -328,7 +328,7 @@ class text_options::substring { /// /// Return the current "strMaxLength" field. /// - MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional const&) str_max_length() const; + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional) str_max_length() const; /// /// Set the "strMaxQueryLength" field. /// @@ -337,7 +337,7 @@ class text_options::substring { /// /// Return the current "strMaxQueryLength" field. /// - MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional const&) str_max_query_length() const; + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional) str_max_query_length() const; /// /// Set the "strminQueryLength" field. @@ -347,10 +347,10 @@ class text_options::substring { /// /// Return the current "strminQueryLength" field. /// - MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional const&) str_min_query_length() const; + MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v1::stdx::optional) str_min_query_length() const; }; -} // namespace v_1 +} // namespace v1 } // namespace mongocxx #include diff --git a/src/mongocxx/lib/mongocxx/v1/text_options.cpp b/src/mongocxx/lib/mongocxx/v1/text_options.cpp new file mode 100644 index 0000000000..e74df944e7 --- /dev/null +++ b/src/mongocxx/lib/mongocxx/v1/text_options.cpp @@ -0,0 +1,211 @@ +// Copyright 2009-present MongoDB, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +#include +#include +#include // IWYU pragma: export + +#include + +namespace mongocxx { +namespace v1 { + +class common_opts_impl { + public: + bsoncxx::v1::stdx::optional _min_query_length; + bsoncxx::v1::stdx::optional _max_query_length; + bsoncxx::v1::stdx::optional _max_length; + + static common_opts_impl& with(void* ptr) { + return *static_cast(ptr); + } + + static common_opts_impl const& with(void const* ptr) { + return *static_cast(ptr); + } +}; + +class text_options::prefix::impl final : public common_opts_impl {}; +class text_options::suffix::impl final : public common_opts_impl {}; +class text_options::substring::impl final : public common_opts_impl {}; + +class text_options::impl { + public: + bsoncxx::v1::stdx::optional _case_sensitive; + bsoncxx::v1::stdx::optional _diacritic_sensitive; + bsoncxx::v1::stdx::optional _prefix; + bsoncxx::v1::stdx::optional _suffix; + bsoncxx::v1::stdx::optional _substring; + + static impl const& with(text_options const& other) { + return *static_cast(other._impl); + } + + static impl const* with(text_options const* other) { + return static_cast(other->_impl); + } + + static impl& with(text_options& other) { + return *static_cast(other._impl); + } + + static impl* with(text_options* other) { + return static_cast(other->_impl); + } + + static impl* with(void* ptr) { + return static_cast(ptr); + } +}; + +text_options::~text_options() { + delete impl::with(_impl); +} + +text_options::text_options(text_options&& other) noexcept : _impl{exchange(other._impl, nullptr)} {} + +text_options& text_options::operator=(text_options&& other) noexcept { + if (this != &other) { + delete impl::with(exchange(_impl, exchange(other._impl, nullptr))); + } + + return *this; +} + +text_options::text_options(text_options const& other) : _impl{new impl{impl::with(other)}} {} + +text_options& text_options::operator=(text_options const& other) { + if (this != &other) { + delete impl::with(exchange(_impl, new impl{impl::with(other)})); + } + + return *this; +} + +text_options::text_options() : _impl{new impl{}} {} + +text_options& text_options::case_sensitive(bool value) { + impl::with(this)->_case_sensitive = value; + return *this; +} + +bsoncxx::v1::stdx::optional text_options::case_sensitive() const { + return impl::with(this)->_case_sensitive; +} + +text_options& text_options::diacritic_sensitive(bool value) { + impl::with(this)->_diacritic_sensitive = value; + return *this; +} + +bsoncxx::v1::stdx::optional text_options::diacritic_sensitive() const { + return impl::with(this)->_diacritic_sensitive; +} + +text_options& text_options::prefix_opts(prefix value) { + impl::with(this)->_prefix = std::move(value); + return *this; +} + +bsoncxx::v1::stdx::optional const& text_options::prefix_opts() const { + return impl::with(this)->_prefix; +} + +text_options& text_options::suffix_opts(suffix value) { + impl::with(this)->_suffix = std::move(value); + return *this; +} + +bsoncxx::v1::stdx::optional const& text_options::suffix_opts() const { + return impl::with(this)->_suffix; +} + +text_options& text_options::substring_opts(substring value) { + impl::with(this)->_substring = std::move(value); + return *this; +} + +bsoncxx::v1::stdx::optional const& text_options::substring_opts() const { + return impl::with(this)->_substring; +} + +bsoncxx::v1::stdx::optional text_options::prefix::str_max_query_length() const { + return common_opts_impl::with(this)._max_query_length; +} + +text_options::prefix& text_options::prefix::str_max_query_length(int32_t value) { + common_opts_impl::with(this)._max_query_length = value; + return *this; +} + +bsoncxx::v1::stdx::optional text_options::prefix::str_min_query_length() const { + return common_opts_impl::with(this)._min_query_length; +} + +text_options::prefix& text_options::prefix::str_min_query_length(int32_t value) { + common_opts_impl::with(this)._min_query_length = value; + return *this; +} + +bsoncxx::v1::stdx::optional text_options::suffix::str_max_query_length() const { + return common_opts_impl::with(this)._max_query_length; +} + +text_options::suffix& text_options::suffix::str_max_query_length(int32_t value) { + common_opts_impl::with(this)._max_query_length = value; + return *this; +} + +bsoncxx::v1::stdx::optional text_options::suffix::str_min_query_length() const { + return common_opts_impl::with(this)._min_query_length; +} + +text_options::suffix& text_options::suffix::str_min_query_length(int32_t value) { + common_opts_impl::with(this)._min_query_length = value; + return *this; +} + +bsoncxx::v1::stdx::optional text_options::substring::str_max_query_length() const { + return common_opts_impl::with(this)._max_query_length; +} + +text_options::substring& text_options::substring::str_max_query_length(int32_t value) { + common_opts_impl::with(this)._max_query_length = value; + return *this; +} + +bsoncxx::v1::stdx::optional text_options::substring::str_min_query_length() const { + return common_opts_impl::with(this)._min_query_length; +} + +text_options::substring& text_options::substring::str_min_query_length(int32_t value) { + common_opts_impl::with(this)._min_query_length = value; + return *this; +} + +text_options::substring& text_options::substring::str_max_length(int32_t value) { + common_opts_impl::with(this)._max_length = value; + return *this; +} + +bsoncxx::v1::stdx::optional text_options::substring::str_max_length() const { + return common_opts_impl::with(this)._max_length; +} + +} // namespace v1 +} // namespace mongocxx From c27c4b4c53f16581ea174e3ff525d27d3feeff18 Mon Sep 17 00:00:00 2001 From: mdb-ad <198671546+mdb-ad@users.noreply.github.com> Date: Wed, 3 Dec 2025 22:00:52 -0800 Subject: [PATCH 5/5] noabi headers --- .../include/mongocxx/v1/text_options-fwd.hpp | 22 +++----- .../v_noabi/mongocxx/options/text-fwd.hpp | 44 ++++++++++++++++ .../v_noabi/mongocxx/options/text.hpp | 51 +++++++++++++++++++ .../v_noabi/mongocxx/options/encrypt.cpp | 9 ++-- .../test/v_noabi/client_side_encryption.cpp | 25 ++++----- 5 files changed, 120 insertions(+), 31 deletions(-) create mode 100644 src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text-fwd.hpp create mode 100644 src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text.hpp diff --git a/src/mongocxx/include/mongocxx/v1/text_options-fwd.hpp b/src/mongocxx/include/mongocxx/v1/text_options-fwd.hpp index adba80ab25..014293ec13 100644 --- a/src/mongocxx/include/mongocxx/v1/text_options-fwd.hpp +++ b/src/mongocxx/include/mongocxx/v1/text_options-fwd.hpp @@ -14,29 +14,21 @@ #pragma once -#include +#include -namespace mongocxx { -namespace v_noabi { -namespace options { - -class text; - -} // namespace options -} // namespace v_noabi -} // namespace mongocxx +#include namespace mongocxx { -namespace options { +namespace v1 { -using v_noabi::options::text; +class text_options; -} // namespace options +} // namespace v1 } // namespace mongocxx -#include +#include /// /// @file -/// Declares @ref mongocxx::v_noabi::options::range. +/// Declares @ref mongocxx::v1::text_options. /// diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text-fwd.hpp b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text-fwd.hpp new file mode 100644 index 0000000000..ba877c187a --- /dev/null +++ b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text-fwd.hpp @@ -0,0 +1,44 @@ +// Copyright 2009-present MongoDB, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "mongocxx/v1/text_options.hpp" +#include // IWYU pragma: export + +#include + +namespace mongocxx { +namespace v_noabi { + +using v1::text_options; + +} // namespace v_noabi +} // namespace mongocxx + +namespace mongocxx { + +using v1::text_options; + +} // namespace mongocxx + +#include + +/// +/// @file +/// Declares utilities related to mongocxx logging. +/// +/// @par Includes +/// - @ref mongocxx/v1/text_options-fwd.hpp +/// diff --git a/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text.hpp b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text.hpp new file mode 100644 index 0000000000..51a9c574a7 --- /dev/null +++ b/src/mongocxx/include/mongocxx/v_noabi/mongocxx/options/text.hpp @@ -0,0 +1,51 @@ +// Copyright 2009-present MongoDB, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include // IWYU pragma: export + +// + +#include // IWYU pragma: export + +#include + +namespace mongocxx { +namespace v_noabi { +namespace options { + +using text = v1::text_options; + +} // namespace options +} // namespace v_noabi +} // namespace mongocxx + +namespace mongocxx { +namespace options { + +using v_noabi::options::text; + +} // namespace options +} // namespace mongocxx + +#include + +/// +/// @file +/// Declares @ref mongocxx::v_noabi::options::range. +/// +/// @par Includes +/// - @ref mongocxx/v1/range_options.hpp +/// diff --git a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/encrypt.cpp b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/encrypt.cpp index 3eee5f858f..40ca287010 100644 --- a/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/encrypt.cpp +++ b/src/mongocxx/lib/mongocxx/v_noabi/mongocxx/options/encrypt.cpp @@ -166,7 +166,8 @@ void* encrypt::convert() const { libmongoc::client_encryption_encrypt_opts_set_query_type(opts, MONGOC_ENCRYPT_QUERY_TYPE_SUFFIXPREVIEW); break; case encryption_query_type::k_substringPreview: - libmongoc::client_encryption_encrypt_opts_set_query_type(opts, MONGOC_ENCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW); + libmongoc::client_encryption_encrypt_opts_set_query_type( + opts, MONGOC_ENCRYPT_QUERY_TYPE_SUBSTRINGPREVIEW); break; default: throw exception{error_code::k_invalid_parameter, "unsupported query type"}; @@ -228,9 +229,9 @@ void* encrypt::convert() const { auto const& case_sensitive = _text_opts->case_sensitive(); auto const& diacritic_sensitive = _text_opts->diacritic_sensitive(); - auto const& prefix = _text_opts->prefix(); - auto const& suffix = _text_opts->suffix(); - auto const& substring = _text_opts->substring(); + auto const& prefix = _text_opts->prefix_opts(); + auto const& suffix = _text_opts->suffix_opts(); + auto const& substring = _text_opts->substring_opts(); if (case_sensitive) { libmongoc::client_encryption_encrypt_text_opts_set_case_sensitive(text_opts, case_sensitive.value()); diff --git a/src/mongocxx/test/v_noabi/client_side_encryption.cpp b/src/mongocxx/test/v_noabi/client_side_encryption.cpp index 281a194ad7..5c2129c266 100644 --- a/src/mongocxx/test/v_noabi/client_side_encryption.cpp +++ b/src/mongocxx/test/v_noabi/client_side_encryption.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -3510,10 +3511,10 @@ TEST_CASE("Text Explicit Encryption", "[client_side_encryption]") { _drop_and_create_collection("db", "prefix-suffix", "/explicit-encryption/encryptedFields-prefix-suffix.json"); _drop_and_create_collection("db", "substring", "/explicit-encryption/encryptedFields-substring.json"); - auto const prefix_opts = options::prefix().str_max_query_length(10).str_min_query_length(2); - auto const suffix_opts = options::suffix().str_max_query_length(10).str_min_query_length(2); + auto const prefix_opts = text_options::prefix().str_max_query_length(10).str_min_query_length(2); + auto const suffix_opts = text_options::suffix().str_max_query_length(10).str_min_query_length(2); auto const substring_opts = - options::substring().str_max_length(10).str_max_query_length(10).str_min_query_length(2); + text_options::substring().str_max_length(10).str_max_query_length(10).str_min_query_length(2); auto const default_encrypt_opts = [&]() { return options::encrypt() @@ -3521,11 +3522,9 @@ TEST_CASE("Text Explicit Encryption", "[client_side_encryption]") { .algorithm(options::encrypt::encryption_algorithm::k_textPreview) .contention_factor(0); }; - auto const default_text_opts = [&]() { - return options::text().case_sensitive(true).diacritic_sensitive(true); - }; + auto const default_text_opts = [&]() { return text_options().case_sensitive(true).diacritic_sensitive(true); }; - const auto foobarbaz_doc = make_document(kvp("_id", 0), kvp("encryptedText", "foobarbaz")); + auto const foobarbaz_doc = make_document(kvp("_id", 0), kvp("encryptedText", "foobarbaz")); auto client_substring = encrypted_client["db"]["substring"]; auto client_prefix_suffix = encrypted_client["db"]["prefix-suffix"]; @@ -3533,7 +3532,7 @@ TEST_CASE("Text Explicit Encryption", "[client_side_encryption]") { // Use clientEncryption to encrypt the string "foobarbaz" with the following EncryptOpts: // TODO auto const encrypt_opts = - default_encrypt_opts().text_opts(default_text_opts().prefix(prefix_opts).suffix(suffix_opts)); + default_encrypt_opts().text_opts(default_text_opts().prefix_opts(prefix_opts).suffix_opts(suffix_opts)); auto const encrypted_foobarbaz = client_encryption.encrypt(make_value("foobarbaz"), encrypt_opts); // Use encryptedClient to insert the following document into db.prefix-suffix with majority write concern: @@ -3544,7 +3543,7 @@ TEST_CASE("Text Explicit Encryption", "[client_side_encryption]") { { // Use clientEncryption to encrypt the string "foobarbaz" with the following EncryptOpts: // TODO - auto const encrypt_opts = default_encrypt_opts().text_opts(default_text_opts().substring(substring_opts)); + auto const encrypt_opts = default_encrypt_opts().text_opts(default_text_opts().substring_opts(substring_opts)); auto const encrypted_foobarbaz = client_encryption.encrypt(make_value("foobarbaz"), encrypt_opts); // Use encryptedClient to insert the following document into db.prefix-suffix with majority write concern: @@ -3554,10 +3553,12 @@ TEST_CASE("Text Explicit Encryption", "[client_side_encryption]") { SECTION("can find a document by prefix") { auto const encrypt_opts = default_encrypt_opts() .query_type(options::encrypt::encryption_query_type::k_prefixPreview) - .text_opts(default_text_opts().prefix(prefix_opts)); + .text_opts(default_text_opts().prefix_opts(prefix_opts)); auto const encrypted_foo = client_encryption.encrypt(make_value("foo"), encrypt_opts); - auto const query = make_document( - kvp("$expr", make_document(kvp("$encStrStartsWith", make_document(kvp("input", "$encryptedText"), kvp("prefix", encrypted_foo)))))); + auto const query = make_document(kvp( + "$expr", + make_document(kvp( + "$encStrStartsWith", make_document(kvp("input", "$encryptedText"), kvp("prefix", encrypted_foo)))))); auto cursor = client_prefix_suffix.find(query.view()); auto const found = std::vector(cursor.begin(), cursor.end());