From 8b3a94a6e8284235abb75271e4e3c2874b909234 Mon Sep 17 00:00:00 2001 From: Thijs Cadier Date: Mon, 28 Sep 2015 20:27:06 +0200 Subject: [PATCH] Add collection update --- src/collection.rs | 49 ++++++++++++++++++++++++++++++++++++++++++++- src/flags.rs | 23 +++++++++++++++++++++ tests/collection.rs | 20 +++++++++++++++--- tests/flags.rs | 18 +++++++++++++---- 4 files changed, 102 insertions(+), 8 deletions(-) diff --git a/src/collection.rs b/src/collection.rs index 4351fbf..cff6058 100644 --- a/src/collection.rs +++ b/src/collection.rs @@ -16,7 +16,7 @@ use super::client::Client; use super::cursor; use super::cursor::{Cursor,TailingCursor}; use super::database::Database; -use super::flags::{Flags,FlagsValue,InsertFlag,QueryFlag,RemoveFlag}; +use super::flags::{Flags,FlagsValue,InsertFlag,QueryFlag,RemoveFlag,UpdateFlag}; use super::write_concern::WriteConcern; use super::read_prefs::ReadPrefs; @@ -123,6 +123,20 @@ impl RemoveOptions { } } +pub struct UpdateOptions { + pub update_flags: Flags, + pub write_concern: WriteConcern +} + +impl UpdateOptions { + pub fn default() -> UpdateOptions { + UpdateOptions { + update_flags: Flags::new(), + write_concern: WriteConcern::new() + } + } +} + pub struct TailOptions { pub wait_time_ms: u32, pub max_retries: u32 @@ -518,6 +532,39 @@ impl<'a> Collection<'a> { } } + /// This function shall update documents in collection that match selector. + /// + /// See: http://api.mongodb.org/c/current/mongoc_collection_update.html + pub fn update( + &self, + selector: &Document, + update: &Document, + options: Option<&UpdateOptions> + ) -> Result<()> { + assert!(!self.inner.is_null()); + + let default_options = UpdateOptions::default(); + let options = options.unwrap_or(&default_options); + + let mut error = BsoncError::empty(); + let success = unsafe { + bindings::mongoc_collection_update( + self.inner, + options.update_flags.flags(), + try!(Bsonc::from_document(&selector)).inner(), + try!(Bsonc::from_document(&update)).inner(), + options.write_concern.inner(), + error.mut_inner() + ) + }; + + if success == 1 { + Ok(()) + } else { + Err(error.into()) + } + } + /// Tails a query /// /// Takes ownership of query and options because they could be diff --git a/src/flags.rs b/src/flags.rs index 54dae63..7a3445f 100644 --- a/src/flags.rs +++ b/src/flags.rs @@ -94,3 +94,26 @@ impl FlagsValue for Flags { } } } + +/// Flags for update operations +/// See: http://api.mongodb.org/c/current/mongoc_update_flags_t.html +#[derive(Eq,PartialEq,Ord,PartialOrd)] +pub enum UpdateFlag { + Upsert, + MultiUpdate +} + +impl FlagsValue for Flags { + fn flags(&self) -> u32 { + if self.flags.is_empty() { + bindings::MONGOC_UPDATE_NONE + } else { + self.flags.iter().fold(0, { |flags, flag| + flags | match flag { + &UpdateFlag::Upsert => bindings::MONGOC_UPDATE_UPSERT, + &UpdateFlag::MultiUpdate => bindings::MONGOC_UPDATE_MULTI_UPDATE + } + }) + } + } +} diff --git a/tests/collection.rs b/tests/collection.rs index 77f028a..b2dde8c 100644 --- a/tests/collection.rs +++ b/tests/collection.rs @@ -69,21 +69,35 @@ fn test_mutation_and_finding() { collection.find(&document, None).unwrap().next().unwrap().unwrap().get("key_1").unwrap().to_json(), bson::Bson::String("Value 1".to_string()).to_json() ); - let mut found_document = collection.find(&second_document, None).unwrap().next().unwrap().unwrap(); + let found_document = collection.find(&second_document, None).unwrap().next().unwrap().unwrap(); assert_eq!( found_document.get("key_1").unwrap().to_json(), bson::Bson::String("Value 3".to_string()).to_json() ); // Update the second document - found_document.insert("key_1".to_string(), bson::Bson::String("Value 4".to_string())); + let update = doc!{"$set" => {"key_1" => "Value 4"}}; + assert!(collection.update(&second_document, &update, None).is_ok()); + + // Reload and check value + let query_after_update = doc! { + "key_1" => "Value 4" + }; + let mut found_document = collection.find(&query_after_update, None).unwrap().next().unwrap().unwrap(); + assert_eq!( + found_document.get("key_1").unwrap().to_json(), + bson::Bson::String("Value 4".to_string()).to_json() + ); + + // Save the second document + found_document.insert("key_1".to_string(), bson::Bson::String("Value 5".to_string())); assert!(collection.save(&found_document, None).is_ok()); // Reload and check value let found_document = collection.find(&found_document, None).unwrap().next().unwrap().unwrap(); assert_eq!( found_document.get("key_1").unwrap().to_json(), - bson::Bson::String("Value 4".to_string()).to_json() + bson::Bson::String("Value 5".to_string()).to_json() ); // Remove one diff --git a/tests/flags.rs b/tests/flags.rs index 5813938..7dd40f5 100644 --- a/tests/flags.rs +++ b/tests/flags.rs @@ -1,7 +1,7 @@ -use mongo_driver::flags::{Flags,FlagsValue,InsertFlag,RemoveFlag,QueryFlag}; +use mongo_driver::flags::*; #[test] -pub fn test_insert_flags() { +fn test_insert_flags() { let mut flags = Flags::new(); assert_eq!(0, flags.flags()); @@ -14,7 +14,7 @@ pub fn test_insert_flags() { } #[test] -pub fn test_query_flags() { +fn test_query_flags() { let mut flags = Flags::new(); assert_eq!(0, flags.flags()); @@ -27,7 +27,7 @@ pub fn test_query_flags() { } #[test] -pub fn test_remove_flags() { +fn test_remove_flags() { let mut flags = Flags::new(); assert_eq!(0, flags.flags()); @@ -35,3 +35,13 @@ pub fn test_remove_flags() { flags.add(RemoveFlag::SingleRemove); assert_eq!(1, flags.flags()); } + +#[test] +fn test_update_flags() { + let mut flags = Flags::new(); + assert_eq!(0, flags.flags()); + + flags.add(UpdateFlag::Upsert); + flags.add(UpdateFlag::MultiUpdate); + assert_eq!(3, flags.flags()); +}