Skip to content

Commit 6131491

Browse files
authored
RUST-276 Properly construct findAndModify without options (#117)
1 parent c8f391d commit 6131491

File tree

3 files changed

+121
-18
lines changed

3 files changed

+121
-18
lines changed

src/operation/find_and_modify/mod.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use crate::{
2525
pub(crate) struct FindAndModify {
2626
ns: Namespace,
2727
query: Document,
28-
options: Option<FindAndModifyOptions>,
28+
options: FindAndModifyOptions,
2929
}
3030

3131
impl FindAndModify {
@@ -34,7 +34,8 @@ impl FindAndModify {
3434
query: Document,
3535
options: Option<FindOneAndDeleteOptions>,
3636
) -> Self {
37-
let options = options.map(FindAndModifyOptions::from_find_one_and_delete_options);
37+
let options =
38+
FindAndModifyOptions::from_find_one_and_delete_options(options.unwrap_or_default());
3839
FindAndModify { ns, query, options }
3940
}
4041

@@ -45,8 +46,10 @@ impl FindAndModify {
4546
options: Option<FindOneAndReplaceOptions>,
4647
) -> Result<Self> {
4748
bson_util::replacement_document_check(&replacement)?;
48-
let options = options
49-
.map(|opts| FindAndModifyOptions::from_find_one_and_replace_options(replacement, opts));
49+
let options = FindAndModifyOptions::from_find_one_and_replace_options(
50+
replacement,
51+
options.unwrap_or_default(),
52+
);
5053
Ok(FindAndModify { ns, query, options })
5154
}
5255

@@ -59,8 +62,10 @@ impl FindAndModify {
5962
if let UpdateModifications::Document(ref d) = update {
6063
bson_util::update_document_check(d)?;
6164
};
62-
let options = options
63-
.map(|opts| FindAndModifyOptions::from_find_one_and_update_options(update, opts));
65+
let options = FindAndModifyOptions::from_find_one_and_update_options(
66+
update,
67+
options.unwrap_or_default(),
68+
);
6469
Ok(FindAndModify { ns, query, options })
6570
}
6671
}
@@ -75,7 +80,7 @@ impl Operation for FindAndModify {
7580
"query": self.query.clone(),
7681
};
7782

78-
append_options(&mut body, self.options.as_ref())?;
83+
append_options(&mut body, Some(&self.options))?;
7984

8085
Ok(Command::new(
8186
Self::NAME.to_string(),

src/operation/find_and_modify/options.rs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::time::Duration;
22

33
use bson::{doc, Document};
4-
use serde::Serialize;
4+
use serde::{Serialize, Serializer};
55
use typed_builder::TypedBuilder;
66

77
use crate::{
@@ -17,18 +17,27 @@ use crate::{
1717
concern::WriteConcern,
1818
};
1919

20+
#[derive(Debug, Serialize)]
21+
pub(super) enum Modification {
22+
#[serde(rename = "remove", serialize_with = "self::serialize_true")]
23+
Delete,
24+
#[serde(rename = "update")]
25+
Update(UpdateModifications),
26+
}
27+
28+
fn serialize_true<S: Serializer>(s: S) -> std::result::Result<S::Ok, S::Error> {
29+
s.serialize_bool(true)
30+
}
31+
2032
#[serde_with::skip_serializing_none]
21-
#[derive(Debug, Default, TypedBuilder, Serialize)]
33+
#[derive(Debug, TypedBuilder, Serialize)]
2234
#[serde(rename_all = "camelCase")]
2335
pub(super) struct FindAndModifyOptions {
24-
#[builder(default)]
25-
pub(crate) sort: Option<Document>,
26-
27-
#[builder(default)]
28-
pub(crate) remove: Option<bool>,
36+
#[serde(flatten)]
37+
pub(crate) modification: Modification,
2938

3039
#[builder(default)]
31-
pub(crate) update: Option<UpdateModifications>,
40+
pub(crate) sort: Option<Document>,
3241

3342
#[builder(default)]
3443
pub(crate) new: Option<bool>,
@@ -65,11 +74,11 @@ impl FindAndModifyOptions {
6574
opts: FindOneAndDeleteOptions,
6675
) -> FindAndModifyOptions {
6776
FindAndModifyOptions::builder()
77+
.modification(Modification::Delete)
6878
.collation(opts.collation)
6979
.max_time(opts.max_time)
7080
.projection(opts.projection)
7181
.sort(opts.sort)
72-
.remove(true)
7382
.write_concern(opts.write_concern)
7483
.build()
7584
}
@@ -80,14 +89,14 @@ impl FindAndModifyOptions {
8089
) -> FindAndModifyOptions {
8190
let replacement = UpdateModifications::Document(replacement);
8291
FindAndModifyOptions::builder()
92+
.modification(Modification::Update(replacement))
8393
.collation(opts.collation)
8494
.bypass_document_validation(opts.bypass_document_validation)
8595
.max_time(opts.max_time)
8696
.projection(opts.projection)
8797
.new(return_document_to_bool(opts.return_document))
8898
.sort(opts.sort)
8999
.upsert(opts.upsert)
90-
.update(replacement)
91100
.write_concern(opts.write_concern)
92101
.build()
93102
}
@@ -97,6 +106,7 @@ impl FindAndModifyOptions {
97106
opts: FindOneAndUpdateOptions,
98107
) -> FindAndModifyOptions {
99108
FindAndModifyOptions::builder()
109+
.modification(Modification::Update(update))
100110
.collation(opts.collation)
101111
.array_filters(opts.array_filters)
102112
.bypass_document_validation(opts.bypass_document_validation)
@@ -105,7 +115,6 @@ impl FindAndModifyOptions {
105115
.new(return_document_to_bool(opts.return_document))
106116
.sort(opts.sort)
107117
.upsert(opts.upsert)
108-
.update(update)
109118
.write_concern(opts.write_concern)
110119
.build()
111120
}

src/operation/find_and_modify/test.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,36 @@ fn empty_delete() -> FindAndModify {
2727
FindAndModify::with_delete(ns, filter, None)
2828
}
2929

30+
#[test]
31+
fn build_with_delete_no_options() {
32+
let ns = Namespace {
33+
db: "test_db".to_string(),
34+
coll: "test_coll".to_string(),
35+
};
36+
let filter = doc! { "x": { "$gt": 1 } };
37+
let max_time = Duration::from_millis(2u64);
38+
39+
let op = FindAndModify::with_delete(ns, filter.clone(), None);
40+
41+
let description = StreamDescription::new_testing();
42+
let mut cmd = op.build(&description).unwrap();
43+
44+
assert_eq!(cmd.name.as_str(), "findAndModify");
45+
assert_eq!(cmd.target_db.as_str(), "test_db");
46+
assert_eq!(cmd.read_pref.as_ref(), None);
47+
48+
let mut expected_body = doc! {
49+
"findAndModify": "test_coll",
50+
"query": filter,
51+
"remove": true
52+
};
53+
54+
bson_util::sort_document(&mut cmd.body);
55+
bson_util::sort_document(&mut expected_body);
56+
57+
assert_eq!(cmd.body, expected_body);
58+
}
59+
3060
#[test]
3161
fn build_with_delete() {
3262
let ns = Namespace {
@@ -123,6 +153,36 @@ fn empty_replace() -> FindAndModify {
123153
FindAndModify::with_replace(ns, filter, replacement, None).unwrap()
124154
}
125155

156+
#[test]
157+
fn build_with_replace_no_options() {
158+
let ns = Namespace {
159+
db: "test_db".to_string(),
160+
coll: "test_coll".to_string(),
161+
};
162+
let filter = doc! { "x": { "$gt": 1 } };
163+
let replacement = doc! { "x": { "inc": 1 } };
164+
165+
let op = FindAndModify::with_replace(ns, filter.clone(), replacement.clone(), None).unwrap();
166+
167+
let description = StreamDescription::new_testing();
168+
let mut cmd = op.build(&description).unwrap();
169+
170+
assert_eq!(cmd.name.as_str(), "findAndModify");
171+
assert_eq!(cmd.target_db.as_str(), "test_db");
172+
assert_eq!(cmd.read_pref.as_ref(), None);
173+
174+
let mut expected_body = doc! {
175+
"findAndModify": "test_coll",
176+
"query": filter,
177+
"update": replacement,
178+
};
179+
180+
bson_util::sort_document(&mut cmd.body);
181+
bson_util::sort_document(&mut expected_body);
182+
183+
assert_eq!(cmd.body, expected_body);
184+
}
185+
126186
#[test]
127187
fn build_with_replace() {
128188
let ns = Namespace {
@@ -224,6 +284,35 @@ fn empty_update() -> FindAndModify {
224284
FindAndModify::with_update(ns, filter, update, None).unwrap()
225285
}
226286

287+
#[test]
288+
fn build_with_update_no_options() {
289+
let ns = Namespace {
290+
db: "test_db".to_string(),
291+
coll: "test_coll".to_string(),
292+
};
293+
let filter = doc! { "x": { "$gt": 1 } };
294+
let update = UpdateModifications::Document(doc! { "$x": { "$inc": 1 } });
295+
let op = FindAndModify::with_update(ns, filter.clone(), update.clone(), None).unwrap();
296+
297+
let description = StreamDescription::new_testing();
298+
let mut cmd = op.build(&description).unwrap();
299+
300+
assert_eq!(cmd.name.as_str(), "findAndModify");
301+
assert_eq!(cmd.target_db.as_str(), "test_db");
302+
assert_eq!(cmd.read_pref.as_ref(), None);
303+
304+
let mut expected_body = doc! {
305+
"findAndModify": "test_coll",
306+
"query": filter,
307+
"update": update.to_bson(),
308+
};
309+
310+
bson_util::sort_document(&mut cmd.body);
311+
bson_util::sort_document(&mut expected_body);
312+
313+
assert_eq!(cmd.body, expected_body);
314+
}
315+
227316
#[test]
228317
fn build_with_update() {
229318
let ns = Namespace {

0 commit comments

Comments
 (0)