@ -4,14 +4,14 @@ use std::borrow::Cow;
use mongo_c_driver_wrapper ::bindings ;
use mongo_c_driver_wrapper ::bindings ;
use bson ::Document ;
use bson ::{ Bson , Document } ;
use super ::Result ;
use super ::Result ;
use super ::{ BsoncError , InvalidParamsError } ;
use super ::{ BsoncError , InvalidParamsError } ;
use super ::bsonc ::Bsonc ;
use super ::bsonc ::Bsonc ;
use super ::client ::Client ;
use super ::client ::Client ;
use super ::cursor ;
use super ::cursor ;
use super ::cursor ::Cursor ;
use super ::cursor ::{ Cursor , TailingCursor } ;
use super ::database ::Database ;
use super ::database ::Database ;
use super ::flags ::{ Flags , FlagsValue , InsertFlag , QueryFlag , RemoveFlag } ;
use super ::flags ::{ Flags , FlagsValue , InsertFlag , QueryFlag , RemoveFlag } ;
use super ::write_concern ::WriteConcern ;
use super ::write_concern ::WriteConcern ;
@ -27,6 +27,90 @@ pub struct Collection<'a> {
inner : * mut bindings ::mongoc_collection_t
inner : * mut bindings ::mongoc_collection_t
}
}
pub struct CountOptions {
pub query_flags : Flags < QueryFlag > ,
pub skip : u32 ,
pub limit : u32 ,
pub opts : Option < Document > ,
pub read_prefs : Option < ReadPrefs >
}
impl CountOptions {
pub fn default ( ) -> CountOptions {
CountOptions {
query_flags : Flags ::new ( ) ,
skip : 0 ,
limit : 0 ,
opts : None ,
read_prefs : None
}
}
}
pub struct FindOptions {
pub query_flags : Flags < QueryFlag > ,
pub skip : u32 ,
pub limit : u32 ,
pub batch_size : u32 ,
pub fields : Option < Document > ,
pub read_prefs : Option < ReadPrefs >
}
impl FindOptions {
pub fn default ( ) -> FindOptions {
FindOptions {
query_flags : Flags ::new ( ) ,
skip : 0 ,
limit : 0 ,
batch_size : 0 ,
fields : None ,
read_prefs : None
}
}
}
pub struct InsertOptions {
pub insert_flags : Flags < InsertFlag > ,
pub write_concern : WriteConcern
}
impl InsertOptions {
pub fn default ( ) -> InsertOptions {
InsertOptions {
insert_flags : Flags ::new ( ) ,
write_concern : WriteConcern ::new ( )
}
}
}
pub struct RemoveOptions {
pub remove_flags : Flags < RemoveFlag > ,
pub write_concern : WriteConcern
}
impl RemoveOptions {
pub fn default ( ) -> RemoveOptions {
RemoveOptions {
remove_flags : Flags ::new ( ) ,
write_concern : WriteConcern ::new ( )
}
}
}
pub struct TailOptions {
pub wait_time_ms : u32 ,
pub max_retries : u32
}
impl TailOptions {
pub fn default ( ) -> TailOptions {
TailOptions {
wait_time_ms : 500 ,
max_retries : 5
}
}
}
impl < ' a > Collection < ' a > {
impl < ' a > Collection < ' a > {
pub fn new (
pub fn new (
created_by : CreatedBy < ' a > ,
created_by : CreatedBy < ' a > ,
@ -39,31 +123,30 @@ impl<'a> Collection<'a> {
}
}
}
}
pub fn count _with_options (
pub fn count (
& self ,
& self ,
query_flags : & Flags < QueryFlag > ,
query : & Document ,
query : & Document ,
skip : u32 ,
options : Option < & CountOptions >
limit : u32 ,
opts : Option < & Document > ,
read_prefs : Option < & ReadPrefs >
) -> Result < i64 > {
) -> Result < i64 > {
assert! ( ! self . inner . is_null ( ) ) ;
assert! ( ! self . inner . is_null ( ) ) ;
let default_options = CountOptions ::default ( ) ;
let options = options . unwrap_or ( & default_options ) ;
let mut error = BsoncError ::empty ( ) ;
let mut error = BsoncError ::empty ( ) ;
let count = unsafe {
let count = unsafe {
bindings ::mongoc_collection_count_with_opts (
bindings ::mongoc_collection_count_with_opts (
self . inner ,
self . inner ,
query_flags. flags ( ) ,
options. query_flags. flags ( ) ,
try ! ( Bsonc ::from_document ( query ) ) . inner ( ) ,
try ! ( Bsonc ::from_document ( query ) ) . inner ( ) ,
skip as i64 ,
options. skip as i64 ,
limit as i64 ,
options. limit as i64 ,
match opt s {
match opt ions. opt s {
Some ( o ) = > try ! ( Bsonc ::from_document ( o ) ) . inner ( ) ,
Some ( ref o ) = > try ! ( Bsonc ::from_document ( o ) ) . inner ( ) ,
None = > ptr ::null ( )
None = > ptr ::null ( )
} ,
} ,
match read_prefs {
match options. read_prefs {
Some ( prefs ) = > prefs . inner ( ) ,
Some ( ref prefs ) = > prefs . inner ( ) ,
None = > ptr ::null ( )
None = > ptr ::null ( )
} ,
} ,
error . mut_inner ( )
error . mut_inner ( )
@ -77,20 +160,6 @@ impl<'a> Collection<'a> {
}
}
}
}
pub fn count (
& self ,
query : & Document
) -> Result < i64 > {
self . count_with_options (
& Flags ::new ( ) ,
query ,
0 ,
0 ,
None ,
None
)
}
pub fn drop ( & mut self ) -> Result < ( ) > {
pub fn drop ( & mut self ) -> Result < ( ) > {
assert! ( ! self . inner . is_null ( ) ) ;
assert! ( ! self . inner . is_null ( ) ) ;
let mut error = BsoncError ::empty ( ) ;
let mut error = BsoncError ::empty ( ) ;
@ -107,34 +176,32 @@ impl<'a> Collection<'a> {
Ok ( ( ) )
Ok ( ( ) )
}
}
pub fn find _with_options (
pub fn find (
& ' a self ,
& ' a self ,
query_flags : & Flags < QueryFlag > ,
skip : u32 ,
limit : u32 ,
batch_size : u32 ,
query : & Document ,
query : & Document ,
fields : Option < & Document > ,
options : Option < & FindOptions >
read_prefs : Option < & ReadPrefs >
) -> Result < Cursor < ' a > > {
) -> Result < Cursor < ' a > > {
assert! ( ! self . inner . is_null ( ) ) ;
assert! ( ! self . inner . is_null ( ) ) ;
let default_options = FindOptions ::default ( ) ;
let options = options . unwrap_or ( & default_options ) ;
let inner = unsafe {
let inner = unsafe {
bindings ::mongoc_collection_find (
bindings ::mongoc_collection_find (
self . inner ,
self . inner ,
query_flags. flags ( ) ,
options. query_flags. flags ( ) ,
skip,
options. skip,
limit,
options. limit,
batch_size,
options. batch_size,
try ! ( Bsonc ::from_document ( query ) ) . inner ( ) ,
try ! ( Bsonc ::from_document ( query ) ) . inner ( ) ,
match fields {
match options. fields {
Some ( f ) = > {
Some ( ref f ) = > {
try ! ( Bsonc ::from_document ( f ) ) . inner ( )
try ! ( Bsonc ::from_document ( f ) ) . inner ( )
} ,
} ,
None = > ptr ::null ( )
None = > ptr ::null ( )
} ,
} ,
match read_prefs {
match options. read_prefs {
Some ( prefs ) = > prefs . inner ( ) ,
Some ( ref prefs ) = > prefs . inner ( ) ,
None = > ptr ::null ( )
None = > ptr ::null ( )
}
}
)
)
@ -147,21 +214,6 @@ impl<'a> Collection<'a> {
Ok ( Cursor ::new ( cursor ::CreatedBy ::Collection ( self ) , inner ) )
Ok ( Cursor ::new ( cursor ::CreatedBy ::Collection ( self ) , inner ) )
}
}
pub fn find (
& ' a self ,
query : & Document
) -> Result < Cursor < ' a > > {
self . find_with_options (
& Flags ::new ( ) ,
0 ,
0 ,
0 ,
& query ,
None ,
None
)
}
pub fn get_name ( & self ) -> Cow < str > {
pub fn get_name ( & self ) -> Cow < str > {
let cstr = unsafe {
let cstr = unsafe {
CStr ::from_ptr ( bindings ::mongoc_collection_get_name ( self . inner ) )
CStr ::from_ptr ( bindings ::mongoc_collection_get_name ( self . inner ) )
@ -169,21 +221,23 @@ impl<'a> Collection<'a> {
String ::from_utf8_lossy ( cstr . to_bytes ( ) )
String ::from_utf8_lossy ( cstr . to_bytes ( ) )
}
}
pub fn insert _with_options (
pub fn insert (
& ' a self ,
& ' a self ,
insert_flags : & Flags < InsertFlag > ,
document : & Document ,
document : & Document ,
write_concern: & WriteConcern
options: Option < & InsertOptions >
) -> Result < ( ) > {
) -> Result < ( ) > {
assert! ( ! self . inner . is_null ( ) ) ;
assert! ( ! self . inner . is_null ( ) ) ;
let default_options = InsertOptions ::default ( ) ;
let options = options . unwrap_or ( & default_options ) ;
let mut error = BsoncError ::empty ( ) ;
let mut error = BsoncError ::empty ( ) ;
let success = unsafe {
let success = unsafe {
bindings ::mongoc_collection_insert (
bindings ::mongoc_collection_insert (
self . inner ,
self . inner ,
insert_flags. flags ( ) ,
options. insert_flags. flags ( ) ,
try ! ( Bsonc ::from_document ( & document ) ) . inner ( ) ,
try ! ( Bsonc ::from_document ( & document ) ) . inner ( ) ,
write_concern. inner ( ) ,
options. write_concern. inner ( ) ,
error . mut_inner ( )
error . mut_inner ( )
)
)
} ;
} ;
@ -195,29 +249,23 @@ impl<'a> Collection<'a> {
}
}
}
}
pub fn insert ( & ' a self , document : & Document ) -> Result < ( ) > {
pub fn remove (
self . insert_with_options (
& Flags ::new ( ) ,
document ,
& WriteConcern ::new ( )
)
}
pub fn remove_with_options (
& self ,
& self ,
remove_flags : & Flags < RemoveFlag > ,
selector : & Document ,
selector : & Document ,
write_concern: & WriteConcern
options : Option < & RemoveOptions >
) -> Result < ( ) > {
) -> Result < ( ) > {
assert! ( ! self . inner . is_null ( ) ) ;
assert! ( ! self . inner . is_null ( ) ) ;
let default_options = RemoveOptions ::default ( ) ;
let options = options . unwrap_or ( & default_options ) ;
let mut error = BsoncError ::empty ( ) ;
let mut error = BsoncError ::empty ( ) ;
let success = unsafe {
let success = unsafe {
bindings ::mongoc_collection_remove (
bindings ::mongoc_collection_remove (
self . inner ,
self . inner ,
remove_flags. flags ( ) ,
options. remove_flags. flags ( ) ,
try ! ( Bsonc ::from_document ( & selector ) ) . inner ( ) ,
try ! ( Bsonc ::from_document ( & selector ) ) . inner ( ) ,
write_concern. inner ( ) ,
options. write_concern. inner ( ) ,
error . mut_inner ( )
error . mut_inner ( )
)
)
} ;
} ;
@ -229,24 +277,16 @@ impl<'a> Collection<'a> {
}
}
}
}
pub fn remove (
pub fn save (
& self ,
selector : & Document
) -> Result < ( ) > {
self . remove_with_options (
& Flags ::new ( ) ,
selector ,
& WriteConcern ::new ( )
)
}
pub fn save_with_options (
& self ,
& self ,
document : & Document ,
document : & Document ,
write_concern : & WriteConcern
write_concern : Option < & WriteConcern >
) -> Result < ( ) > {
) -> Result < ( ) > {
assert! ( ! self . inner . is_null ( ) ) ;
assert! ( ! self . inner . is_null ( ) ) ;
let default_write_concern = WriteConcern ::new ( ) ;
let write_concern = write_concern . unwrap_or ( & default_write_concern ) ;
let mut error = BsoncError ::empty ( ) ;
let mut error = BsoncError ::empty ( ) ;
let success = unsafe {
let success = unsafe {
bindings ::mongoc_collection_save (
bindings ::mongoc_collection_save (
@ -264,13 +304,37 @@ impl<'a> Collection<'a> {
}
}
}
}
pub fn save (
/// Tails a query
& self ,
///
document : & Document ,
/// Takes ownership of query and options because they could be
) -> Result < ( ) > {
/// modified and reused when the connections is disrupted and
self . save_with_options (
/// we need to restart the query. The query will be placed in a
document ,
/// $query key, so the function can add configuration needed for
& WriteConcern ::new ( )
/// proper tailing.
///
/// The query is executed when iterating, so this function doesn't
/// return a result itself.
///
/// The necessary flags to configure a tailing query will be added
/// to the configured flags if you choose to supply options.
pub fn tail (
& ' a self ,
query : Document ,
find_options : Option < FindOptions > ,
tail_options : Option < TailOptions >
) -> TailingCursor < ' a > {
let mut query_with_options = Document ::new ( ) ;
query_with_options . insert (
"$query" . to_string ( ) ,
Bson ::Document ( query )
) ;
query_with_options . insert ( "$natural" . to_string ( ) , Bson ::I32 ( 1 ) ) ;
TailingCursor ::new (
self ,
query_with_options ,
find_options . unwrap_or ( FindOptions ::default ( ) ) ,
tail_options . unwrap_or ( TailOptions ::default ( ) )
)
)
}
}
}
}
@ -304,23 +368,23 @@ mod tests {
let mut document = bson ::Document ::new ( ) ;
let mut document = bson ::Document ::new ( ) ;
document . insert ( "key_1" . to_string ( ) , bson ::Bson ::String ( "Value 1" . to_string ( ) ) ) ;
document . insert ( "key_1" . to_string ( ) , bson ::Bson ::String ( "Value 1" . to_string ( ) ) ) ;
document . insert ( "key_2" . to_string ( ) , bson ::Bson ::String ( "Value 2" . to_string ( ) ) ) ;
document . insert ( "key_2" . to_string ( ) , bson ::Bson ::String ( "Value 2" . to_string ( ) ) ) ;
assert! ( collection . insert ( & document ). is_ok ( ) ) ;
assert! ( collection . insert ( & document , None ). is_ok ( ) ) ;
let mut second_document = bson ::Document ::new ( ) ;
let mut second_document = bson ::Document ::new ( ) ;
second_document . insert ( "key_1" . to_string ( ) , bson ::Bson ::String ( "Value 3" . to_string ( ) ) ) ;
second_document . insert ( "key_1" . to_string ( ) , bson ::Bson ::String ( "Value 3" . to_string ( ) ) ) ;
assert! ( collection . insert ( & second_document ). is_ok ( ) ) ;
assert! ( collection . insert ( & second_document , None ). is_ok ( ) ) ;
let query = bson ::Document ::new ( ) ;
let query = bson ::Document ::new ( ) ;
// Count the documents in the collection
// Count the documents in the collection
assert_eq! ( 2 , collection . count ( & query ). unwrap ( ) ) ;
assert_eq! ( 2 , collection . count ( & query , None ). unwrap ( ) ) ;
// Find the documents
// Find the documents
assert_eq! (
assert_eq! (
collection . find ( & document ). unwrap ( ) . next ( ) . unwrap ( ) . unwrap ( ) . get ( "key_1" ) . unwrap ( ) . to_json ( ) ,
collection . find ( & document , None ). unwrap ( ) . next ( ) . unwrap ( ) . unwrap ( ) . get ( "key_1" ) . unwrap ( ) . to_json ( ) ,
bson ::Bson ::String ( "Value 1" . to_string ( ) ) . to_json ( )
bson ::Bson ::String ( "Value 1" . to_string ( ) ) . to_json ( )
) ;
) ;
let mut found_document = collection . find ( & second_document ). unwrap ( ) . next ( ) . unwrap ( ) . unwrap ( ) ;
let mut found_document = collection . find ( & second_document , None ). unwrap ( ) . next ( ) . unwrap ( ) . unwrap ( ) ;
assert_eq! (
assert_eq! (
found_document . get ( "key_1" ) . unwrap ( ) . to_json ( ) ,
found_document . get ( "key_1" ) . unwrap ( ) . to_json ( ) ,
bson ::Bson ::String ( "Value 3" . to_string ( ) ) . to_json ( )
bson ::Bson ::String ( "Value 3" . to_string ( ) ) . to_json ( )
@ -328,42 +392,42 @@ mod tests {
// Update the second document
// Update the second document
found_document . insert ( "key_1" . to_string ( ) , bson ::Bson ::String ( "Value 4" . to_string ( ) ) ) ;
found_document . insert ( "key_1" . to_string ( ) , bson ::Bson ::String ( "Value 4" . to_string ( ) ) ) ;
assert! ( collection . save ( & found_document ). is_ok ( ) ) ;
assert! ( collection . save ( & found_document , None ). is_ok ( ) ) ;
// Reload and check value
// Reload and check value
let found_document = collection . find ( & found_document ). unwrap ( ) . next ( ) . unwrap ( ) . unwrap ( ) ;
let found_document = collection . find ( & found_document , None ). unwrap ( ) . next ( ) . unwrap ( ) . unwrap ( ) ;
assert_eq! (
assert_eq! (
found_document . get ( "key_1" ) . unwrap ( ) . to_json ( ) ,
found_document . get ( "key_1" ) . unwrap ( ) . to_json ( ) ,
bson ::Bson ::String ( "Value 4" . to_string ( ) ) . to_json ( )
bson ::Bson ::String ( "Value 4" . to_string ( ) ) . to_json ( )
) ;
) ;
// Remove one
// Remove one
assert! ( collection . remove ( & found_document ). is_ok ( ) ) ;
assert! ( collection . remove ( & found_document , None ). is_ok ( ) ) ;
// Count again
// Count again
assert_eq! ( 1 , collection . count ( & query ). unwrap ( ) ) ;
assert_eq! ( 1 , collection . count ( & query , None ). unwrap ( ) ) ;
// Find the document and see if it has the keys we expect
// Find the document and see if it has the keys we expect
{
{
let mut cursor = collection . find ( & query ). unwrap ( ) ;
let mut cursor = collection . find ( & query , None ). unwrap ( ) ;
let next_document = cursor . next ( ) . unwrap ( ) . unwrap ( ) ;
let next_document = cursor . next ( ) . unwrap ( ) . unwrap ( ) ;
assert! ( next_document . contains_key ( "key_1" ) ) ;
assert! ( next_document . contains_key ( "key_1" ) ) ;
assert! ( next_document . contains_key ( "key_2" ) ) ;
assert! ( next_document . contains_key ( "key_2" ) ) ;
}
}
// Find the document with fields set
// Find the document with fields set
{
let mut fields = bson ::Document ::new ( ) ;
let mut fields = bson ::Document ::new ( ) ;
fields . insert ( "key_1" . to_string ( ) , bson ::Bson ::Boolean ( true ) ) ;
fields . insert ( "key_1" . to_string ( ) , bson ::Bson ::Boolean ( true ) ) ;
{
let options = super ::FindOptions {
let mut cursor = collection . find_with_options (
query_flags : flags ::Flags ::new ( ) ,
& flags ::Flags ::new ( ) ,
skip : 0 ,
0 ,
limit : 0 ,
0 ,
batch_size : 0 ,
0 ,
fields : Some ( fields ) ,
& query ,
read_prefs : None
Some ( & fields ) ,
} ;
None
let mut cursor = collection . find ( & query , Some ( & options ) ) . unwrap ( ) ;
) . unwrap ( ) ;
let next_document = cursor . next ( ) . unwrap ( ) . unwrap ( ) ;
let next_document = cursor . next ( ) . unwrap ( ) . unwrap ( ) ;
assert! ( next_document . contains_key ( "key_1" ) ) ;
assert! ( next_document . contains_key ( "key_1" ) ) ;
assert! ( ! next_document . contains_key ( "key_2" ) ) ;
assert! ( ! next_document . contains_key ( "key_2" ) ) ;
@ -371,7 +435,7 @@ mod tests {
// Drop collection
// Drop collection
collection . drop ( ) . unwrap ( ) ;
collection . drop ( ) . unwrap ( ) ;
assert_eq! ( 0 , collection . count ( & query ). unwrap ( ) ) ;
assert_eq! ( 0 , collection . count ( & query , None ). unwrap ( ) ) ;
}
}
#[ test ]
#[ test ]
@ -382,7 +446,7 @@ mod tests {
let collection = client . get_collection ( "rust_driver_test" , "items" ) ;
let collection = client . get_collection ( "rust_driver_test" , "items" ) ;
let document = bson ::Document ::new ( ) ;
let document = bson ::Document ::new ( ) ;
let result = collection . insert ( & document );
let result = collection . insert ( & document , None );
assert! ( result . is_err ( ) ) ;
assert! ( result . is_err ( ) ) ;
assert_eq! (
assert_eq! (
"MongoError (BsoncError: Failed to connect to target host: localhost:27018)" ,
"MongoError (BsoncError: Failed to connect to target host: localhost:27018)" ,