Skip to content

Commit ac36a5a

Browse files
committed
CXX-1565 Use mongoc_collection_find_and_modify_with_opts
1 parent d0feb24 commit ac36a5a

File tree

1 file changed

+105
-127
lines changed

1 file changed

+105
-127
lines changed

src/mongocxx/collection.cpp

Lines changed: 105 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -76,32 +76,95 @@ using bsoncxx::document::view_or_value;
7676

7777
namespace {
7878

79+
using bsoncxx::stdx::make_unique;
80+
using mongocxx::libbson::scoped_bson_t;
81+
7982
const char* get_collection_name(mongoc_collection_t* collection) {
8083
return mongocxx::libmongoc::collection_get_name(collection);
8184
}
8285

86+
void destroy_fam_opts(mongoc_find_and_modify_opts_t* opts) {
87+
mongocxx::libmongoc::find_and_modify_opts_destroy(opts);
88+
}
89+
90+
template <typename T>
8391
mongocxx::stdx::optional<bsoncxx::document::value> find_and_modify(
84-
mongoc_collection_t* collection,
85-
bsoncxx::document::view command,
86-
bsoncxx::document::view opts,
87-
const bsoncxx::stdx::optional<mongocxx::write_concern>& wc) {
88-
bsoncxx::builder::basic::document opts_builder;
89-
opts_builder.append(concatenate(opts));
92+
mongoc_collection_t* collection_t,
93+
const mongoc_client_session_t* session_t,
94+
view_or_value filter,
95+
view_or_value* update,
96+
mongoc_find_and_modify_flags_t flags,
97+
bool bypass,
98+
const T& options) {
99+
using unique_opts =
100+
std::unique_ptr<mongoc_find_and_modify_opts_t,
101+
std::function<void MONGOCXX_CALL(mongoc_find_and_modify_opts_t*)>>;
90102

91-
if (wc) {
92-
if (!wc->is_acknowledged() && opts["collation"]) {
103+
auto opts = unique_opts(mongocxx::libmongoc::find_and_modify_opts_new(), destroy_fam_opts);
104+
105+
bsoncxx::builder::basic::document extra;
106+
::bson_error_t error;
107+
108+
// Write concern, collation, and session are passed in "extra".
109+
if (options.write_concern()) {
110+
if (!options.write_concern()->is_acknowledged() && options.collation()) {
93111
throw mongocxx::logic_error{mongocxx::error_code::k_invalid_parameter};
94112
}
95-
opts_builder.append(concatenate(wc->to_document()));
113+
extra.append(concatenate(options.write_concern()->to_document()));
114+
}
115+
116+
if (session_t) {
117+
bson_t bson = BSON_INITIALIZER;
118+
if (!mongocxx::libmongoc::client_session_append(session_t, &bson, &error)) {
119+
bson_destroy(&bson);
120+
throw mongocxx::logic_error{mongocxx::error_code::k_invalid_session, error.message};
121+
}
122+
123+
// document::value takes ownership of the bson buffer.
124+
bsoncxx::document::value session_id{bsoncxx::helpers::value_from_bson_t(&bson)};
125+
extra.append(concatenate(session_id.view()));
126+
}
127+
128+
if (options.collation()) {
129+
extra.append(kvp("collation", *options.collation()));
130+
}
131+
132+
scoped_bson_t extra_bson{extra.view()};
133+
mongocxx::libmongoc::find_and_modify_opts_append(opts.get(), extra_bson.bson());
134+
135+
if (update) {
136+
scoped_bson_t update_bson{update->view()};
137+
mongocxx::libmongoc::find_and_modify_opts_set_update(opts.get(), update_bson.bson());
96138
}
97139

98-
mongocxx::libbson::scoped_bson_t command_bson{command};
99-
mongocxx::libbson::scoped_bson_t opts_bson{opts_builder.extract()};
140+
if (bypass) {
141+
mongocxx::libmongoc::find_and_modify_opts_set_bypass_document_validation(opts.get(), true);
142+
}
143+
144+
if (options.sort()) {
145+
scoped_bson_t sort_bson{*options.sort()};
146+
mongocxx::libmongoc::find_and_modify_opts_set_sort(opts.get(), sort_bson.bson());
147+
}
148+
149+
if (options.projection()) {
150+
scoped_bson_t projection_bson{*options.projection()};
151+
mongocxx::libmongoc::find_and_modify_opts_set_fields(opts.get(), projection_bson.bson());
152+
}
153+
154+
if (options.max_time()) {
155+
mongocxx::libmongoc::find_and_modify_opts_set_max_time_ms(
156+
opts.get(), static_cast<uint32_t>(options.max_time()->count()));
157+
}
158+
159+
// Upsert, remove, and new are passed in flags.
160+
mongocxx::libmongoc::find_and_modify_opts_set_flags(opts.get(), flags);
161+
162+
// Call mongoc_collection_find_and_modify_with_opts.
163+
scoped_bson_t filter_bson{filter.view()};
100164
mongocxx::libbson::scoped_bson_t reply;
101-
::bson_error_t error;
102165

103-
bool result = mongocxx::libmongoc::collection_write_command_with_opts(
104-
collection, command_bson.bson(), opts_bson.bson(), reply.bson_for_init(), &error);
166+
bool result = mongocxx::libmongoc::collection_find_and_modify_with_opts(
167+
collection_t, filter_bson.bson(), opts.get(), reply.bson_for_init(), &error);
105168

106169
if (!result) {
107170
if (!reply.view().empty()) {
@@ -801,50 +864,22 @@ stdx::optional<bsoncxx::document::value> collection::_find_one_and_replace(
801864
view_or_value filter,
802865
view_or_value replacement,
803866
const options::find_one_and_replace& options) {
804-
bsoncxx::builder::basic::document command_doc;
805-
bsoncxx::builder::basic::document options_doc;
806-
807-
command_doc.append(
808-
kvp("findAndModify", libmongoc::collection_get_name(_get_impl().collection_t)));
809-
810-
options_doc.append(kvp("query", filter));
811-
812-
options_doc.append(kvp("update", replacement.view()));
813-
814-
if (options.sort()) {
815-
options_doc.append(kvp("sort", *options.sort()));
816-
}
817-
818-
if (options.bypass_document_validation()) {
819-
options_doc.append(kvp("bypassDocumentValidation", *options.bypass_document_validation()));
820-
}
821-
822-
if (options.collation()) {
823-
options_doc.append(kvp("collation", *options.collation()));
824-
}
825-
826-
if (options.projection()) {
827-
options_doc.append(kvp("fields", *options.projection()));
828-
}
829-
867+
mongoc_find_and_modify_flags_t flags = MONGOC_FIND_AND_MODIFY_NONE;
830868
if (options.upsert().value_or(false)) {
831-
options_doc.append(kvp("upsert", *options.upsert()));
869+
flags = (mongoc_find_and_modify_flags_t)(flags | MONGOC_FIND_AND_MODIFY_UPSERT);
832870
}
833871

834872
if (options.return_document() == options::return_document::k_after) {
835-
options_doc.append(kvp("new", true));
873+
flags = (mongoc_find_and_modify_flags_t)(flags | MONGOC_FIND_AND_MODIFY_RETURN_NEW);
836874
}
837875

838-
if (options.max_time()) {
839-
options_doc.append(kvp("maxTimeMS", bsoncxx::types::b_int64{options.max_time()->count()}));
840-
}
841-
842-
if (session) {
843-
options_doc.append(bsoncxx::builder::concatenate_doc{session->_get_impl().to_document()});
844-
}
845-
846-
return find_and_modify(
847-
_get_impl().collection_t, command_doc.view(), options_doc.view(), options.write_concern());
876+
return find_and_modify(_get_impl().collection_t,
877+
session ? session->_get_impl().get_session_t() : nullptr,
878+
filter,
879+
&replacement,
880+
flags,
881+
options.bypass_document_validation().value_or(false),
882+
options);
848883
}
849884

850885
stdx::optional<bsoncxx::document::value> collection::find_one_and_replace(
@@ -865,50 +900,22 @@ stdx::optional<bsoncxx::document::value> collection::_find_one_and_update(
865900
view_or_value filter,
866901
view_or_value update,
867902
const options::find_one_and_update& options) {
868-
bsoncxx::builder::basic::document command_doc;
869-
bsoncxx::builder::basic::document options_doc;
870-
871-
command_doc.append(
872-
kvp("findAndModify", libmongoc::collection_get_name(_get_impl().collection_t)));
873-
874-
options_doc.append(kvp("query", filter));
875-
876-
options_doc.append(kvp("update", update));
877-
878-
if (options.sort()) {
879-
options_doc.append(kvp("sort", *options.sort()));
880-
}
881-
882-
if (options.return_document() == options::return_document::k_after) {
883-
options_doc.append(kvp("new", true));
884-
}
885-
886-
if (options.bypass_document_validation()) {
887-
options_doc.append(kvp("bypassDocumentValidation", *options.bypass_document_validation()));
888-
}
889-
890-
if (options.collation()) {
891-
options_doc.append(kvp("collation", *options.collation()));
892-
}
893-
894-
if (options.projection()) {
895-
options_doc.append(kvp("fields", *options.projection()));
896-
}
897-
903+
mongoc_find_and_modify_flags_t flags = MONGOC_FIND_AND_MODIFY_NONE;
898904
if (options.upsert().value_or(false)) {
899-
options_doc.append(kvp("upsert", *options.upsert()));
900-
}
901-
902-
if (options.max_time()) {
903-
options_doc.append(kvp("maxTimeMS", bsoncxx::types::b_int64{options.max_time()->count()}));
905+
flags = (mongoc_find_and_modify_flags_t)(flags | MONGOC_FIND_AND_MODIFY_UPSERT);
904906
}
905907

906-
if (session) {
907-
options_doc.append(bsoncxx::builder::concatenate_doc{session->_get_impl().to_document()});
908+
if (options.return_document() == options::return_document::k_after) {
909+
flags = (mongoc_find_and_modify_flags_t)(flags | MONGOC_FIND_AND_MODIFY_RETURN_NEW);
908910
}
909911

910-
return find_and_modify(
911-
_get_impl().collection_t, command_doc.view(), options_doc.view(), options.write_concern());
912+
return find_and_modify(_get_impl().collection_t,
913+
session ? session->_get_impl().get_session_t() : nullptr,
914+
filter,
915+
&update,
916+
flags,
917+
options.bypass_document_validation().value_or(false),
918+
options);
912919
}
913920

914921
stdx::optional<bsoncxx::document::value> collection::find_one_and_update(
@@ -928,42 +935,13 @@ stdx::optional<bsoncxx::document::value> collection::_find_one_and_delete(
928935
const client_session* session,
929936
view_or_value filter,
930937
const options::find_one_and_delete& options) {
931-
bsoncxx::builder::basic::document command_doc;
932-
bsoncxx::builder::basic::document options_doc;
933-
934-
command_doc.append(
935-
kvp("findAndModify", libmongoc::collection_get_name(_get_impl().collection_t)));
936-
937-
options_doc.append(kvp("query", filter));
938-
939-
options_doc.append(kvp("remove", true));
940-
941-
if (options.sort()) {
942-
options_doc.append(kvp("sort", *options.sort()));
943-
}
944-
945-
if (options.collation()) {
946-
options_doc.append(kvp("collation", *options.collation()));
947-
}
948-
949-
if (options.projection()) {
950-
options_doc.append(kvp("fields", *options.projection()));
951-
}
952-
953-
if (options.max_time()) {
954-
options_doc.append(kvp("maxTimeMS", bsoncxx::types::b_int64{options.max_time()->count()}));
955-
}
956-
957-
if (options.write_concern()) {
958-
options_doc.append(kvp("writeConcern", options.write_concern()->to_document()));
959-
}
960-
961-
if (session) {
962-
options_doc.append(bsoncxx::builder::concatenate_doc{session->_get_impl().to_document()});
963-
}
964-
965-
return find_and_modify(
966-
_get_impl().collection_t, command_doc.view(), options_doc.view(), options.write_concern());
938+
return find_and_modify(_get_impl().collection_t,
939+
session ? session->_get_impl().get_session_t() : nullptr,
940+
filter,
941+
nullptr,
942+
MONGOC_FIND_AND_MODIFY_REMOVE,
943+
false,
944+
options);
967945
}
968946

969947
stdx::optional<bsoncxx::document::value> collection::find_one_and_delete(

0 commit comments

Comments
 (0)