Merge pull request #13 from thijsc/documentation

Documentation
pull/15/head
Thijs Cadier 9 years ago
commit f6ea1ddb15

@ -10,9 +10,12 @@ Bson encoding and decoding is handled by the [bson crate](https://github.com/zon
The API should still be considered experimental, but I'm not expecting changes at the moment. The API should still be considered experimental, but I'm not expecting changes at the moment.
[Documentation](http://thijsc.github.io/mongo-rust-driver/mongo_driver/)
## Compatibility ## Compatibility
The driver currently only builds on Unix, tested on Mac Os X and Linux so far. The driver currently only builds on Unix, tested on Mac Os X and Linux so far. It's compatible with MongoDB 2.4 up to 3.2 and
has full replica set and SSL support.
## Logging ## Logging

@ -1,196 +0,0 @@
use mongoc::bindings;
use bson::Document;
use super::BsoncError;
use super::bsonc::Bsonc;
use super::collection::Collection;
use super::Result;
pub struct BulkOperation<'a> {
_collection: &'a Collection<'a>,
inner: *mut bindings::mongoc_bulk_operation_t
}
impl<'a> BulkOperation<'a> {
pub fn new(
collection: &'a Collection<'a>,
inner: *mut bindings::mongoc_bulk_operation_t
) -> BulkOperation<'a> {
assert!(!inner.is_null());
BulkOperation {
_collection: collection,
inner: inner
}
}
/// Queue an insert of a single document into a bulk operation.
/// The insert is not performed until `execute` is called.
///
/// See: http://api.mongodb.org/c/current/mongoc_bulk_operation_insert.html
pub fn insert(
&self,
document: &Document
) -> Result<()> {
assert!(!self.inner.is_null());
unsafe {
bindings::mongoc_bulk_operation_insert(
self.inner,
try!(Bsonc::from_document(&document)).inner()
)
}
Ok(())
}
/// Queue removal of al documents matching selector into a bulk operation.
/// The removal is not performed until `execute` is called.
///
/// See: http://api.mongodb.org/c/current/mongoc_bulk_operation_remove.html
pub fn remove(
&self,
selector: &Document
) -> Result<()> {
assert!(!self.inner.is_null());
unsafe {
bindings::mongoc_bulk_operation_remove(
self.inner,
try!(Bsonc::from_document(&selector)).inner()
)
}
Ok(())
}
/// Queue removal of a single document into a bulk operation.
/// The removal is not performed until `execute` is called.
///
/// See: http://api.mongodb.org/c/current/mongoc_bulk_operation_remove_one.html
pub fn remove_one(
&self,
selector: &Document
) -> Result<()> {
assert!(!self.inner.is_null());
unsafe {
bindings::mongoc_bulk_operation_remove_one(
self.inner,
try!(Bsonc::from_document(&selector)).inner()
)
}
Ok(())
}
/// Queue replacement of a single document into a bulk operation.
/// The replacement is not performed until `execute` is called.
///
/// See: http://api.mongodb.org/c/current/mongoc_bulk_operation_remove_one.html
pub fn replace_one(
&self,
selector: &Document,
document: &Document,
upsert: bool
) -> Result<()> {
assert!(!self.inner.is_null());
unsafe {
bindings::mongoc_bulk_operation_replace_one(
self.inner,
try!(Bsonc::from_document(&selector)).inner(),
try!(Bsonc::from_document(&document)).inner(),
upsert as u8
)
}
Ok(())
}
/// Queue update of a single documents into a bulk operation.
/// The update is not performed until `execute` is called.
///
/// TODO: document must only contain fields whose key starts
/// with $, these is no error handling for this.
///
/// See: http://api.mongodb.org/c/current/mongoc_bulk_operation_update_one.html
pub fn update_one(
&self,
selector: &Document,
document: &Document,
upsert: bool
) -> Result<()> {
assert!(!self.inner.is_null());
unsafe {
bindings::mongoc_bulk_operation_update_one(
self.inner,
try!(Bsonc::from_document(&selector)).inner(),
try!(Bsonc::from_document(&document)).inner(),
upsert as u8
)
}
Ok(())
}
/// Queue update of multiple documents into a bulk operation.
/// The update is not performed until `execute` is called.
///
/// TODO: document must only contain fields whose key starts
/// with $, these is no error handling for this.
///
/// See: http://api.mongodb.org/c/current/mongoc_bulk_operation_update_one.html
pub fn update(
&self,
selector: &Document,
document: &Document,
upsert: bool
) -> Result<()> {
assert!(!self.inner.is_null());
unsafe {
bindings::mongoc_bulk_operation_update(
self.inner,
try!(Bsonc::from_document(&selector)).inner(),
try!(Bsonc::from_document(&document)).inner(),
upsert as u8
)
}
Ok(())
}
/// This function executes all operations queued into this bulk operation.
/// If ordered was set true, forward progress will be stopped upon the first error.
///
/// This function takes ownership because it is not possible to execute a bulk operation
/// multiple times.
///
/// Returns a document with an overview of the bulk operation if successfull.
///
/// See: http://api.mongodb.org/c/current/mongoc_bulk_operation_execute.html
pub fn execute(self) -> Result<Document> {
// Bsonc to store the reply
let mut reply = Bsonc::new();
// Empty error that might be filled
let mut error = BsoncError::empty();
// Execute the operation. This returns a non-zero hint of the peer node on
// success, otherwise 0 and error is set.
let return_value = unsafe {
bindings::mongoc_bulk_operation_execute(
self.inner,
reply.mut_inner(),
error.mut_inner()
)
};
if return_value != 0 {
match reply.as_document() {
Ok(document) => return Ok(document),
Err(error) => return Err(error.into())
}
} else {
Err(error.into())
}
}
}
impl<'a> Drop for BulkOperation<'a> {
fn drop(&mut self) {
assert!(!self.inner.is_null());
unsafe {
bindings::mongoc_bulk_operation_destroy(self.inner);
}
}
}

@ -1,5 +1,10 @@
//! Client to access a MongoDB node, replica set or sharded cluster.
//!
//! Get started by creating a `ClientPool` you can use to pop a `Client`.
use std::borrow::Cow;
use std::fmt; use std::fmt;
use std::ffi::CString; use std::ffi::{CStr,CString};
use std::path::PathBuf; use std::path::PathBuf;
use std::mem; use std::mem;
use std::ptr; use std::ptr;
@ -17,16 +22,16 @@ use super::collection;
use super::collection::Collection; use super::collection::Collection;
use super::database; use super::database;
use super::database::Database; use super::database::Database;
use super::uri::Uri;
use super::read_prefs::ReadPrefs; use super::read_prefs::ReadPrefs;
/// Client pool to a MongoDB cluster. /// Pool that allows usage of clients out of a single pool from multiple threads.
/// ///
/// This client pool cannot be cloned, but it can be shared between threads by using an `Arc`.
/// Use the pool to pop a client and do operations. The client will be automatically added /// Use the pool to pop a client and do operations. The client will be automatically added
/// back to the pool when it goes out of scope. /// back to the pool when it goes out of scope.
/// ///
/// See: http://api.mongodb.org/c/current/mongoc_client_pool_t.html /// This client pool cannot be cloned, but it can be use from different threads by using an `Arc`.
/// Clients cannot be shared between threads, pop a client from the pool for very single thread
/// where you need a connection.
pub struct ClientPool { pub struct ClientPool {
// Uri and SslOptions need to be present for the lifetime of this pool otherwise the C driver // Uri and SslOptions need to be present for the lifetime of this pool otherwise the C driver
// loses access to resources it needs. // loses access to resources it needs.
@ -36,10 +41,9 @@ pub struct ClientPool {
} }
impl ClientPool { impl ClientPool {
/// Create a new ClientPool with optionally SSL options /// Create a new ClientPool with that can provide clients pointing to the specified uri.
/// /// The pool will connect via SSL if you add `?ssl=true` to the uri. You can optionally pass
/// See: http://api.mongodb.org/c/current/mongoc_client_pool_t.html /// in SSL options to configure SSL certificate usage and so on.
/// And: http://api.mongodb.org/c/current/mongoc_ssl_opt_t.html
pub fn new(uri: Uri, ssl_options: Option<SslOptions>) -> ClientPool { pub fn new(uri: Uri, ssl_options: Option<SslOptions>) -> ClientPool {
super::init(); super::init();
let pool = unsafe { let pool = unsafe {
@ -65,13 +69,12 @@ impl ClientPool {
} }
} }
/// Get a reference to this pool's Uri /// Get a reference to this pool's Uri.
pub fn get_uri(&self) -> &Uri { pub fn get_uri(&self) -> &Uri {
&self.uri &self.uri
} }
/// Retrieve a client from the client pool, possibly blocking until one is available. /// Retrieve a client from the client pool, possibly blocking until one is available.
/// See: http://api.mongodb.org/c/current/mongoc_client_pool_pop.html
pub fn pop(&self) -> Client { pub fn pop(&self) -> Client {
assert!(!self.inner.is_null()); assert!(!self.inner.is_null());
let client = unsafe { bindings::mongoc_client_pool_pop(self.inner) }; let client = unsafe { bindings::mongoc_client_pool_pop(self.inner) };
@ -82,7 +85,6 @@ impl ClientPool {
} }
/// Return a client back to the client pool, called from drop of client. /// Return a client back to the client pool, called from drop of client.
/// See: http://api.mongodb.org/c/current/mongoc_client_pool_push.html
unsafe fn push(&self, mongo_client: *mut bindings::mongoc_client_t) { unsafe fn push(&self, mongo_client: *mut bindings::mongoc_client_t) {
assert!(!self.inner.is_null()); assert!(!self.inner.is_null());
assert!(!mongo_client.is_null()); assert!(!mongo_client.is_null());
@ -111,6 +113,7 @@ impl Drop for ClientPool {
} }
} }
/// Optional SSL configuration for a `ClientPool`.
pub struct SslOptions { pub struct SslOptions {
inner: bindings::mongoc_ssl_opt_t, inner: bindings::mongoc_ssl_opt_t,
// We need to store everything so both memory sticks around // We need to store everything so both memory sticks around
@ -129,6 +132,8 @@ pub struct SslOptions {
} }
impl SslOptions { impl SslOptions {
/// Create a new ssl options instance that can be used to configured
/// a `ClientPool`.
pub fn new( pub fn new(
pem_file: Option<PathBuf>, pem_file: Option<PathBuf>,
pem_password: Option<String>, pem_password: Option<String>,
@ -219,6 +224,11 @@ impl Clone for SslOptions {
} }
} }
/// Client that provides access to a MongoDB MongoDB node, replica-set, or sharded-cluster.
///
/// It maintains management of underlying sockets and routing to individual nodes based on
/// `ReadPrefs` or `WriteConcern`. Clients cannot be shared between threads, pop a new one from
/// a `ClientPool` in every thread that needs a connection instead.
pub struct Client<'a> { pub struct Client<'a> {
client_pool: &'a ClientPool, client_pool: &'a ClientPool,
inner: *mut bindings::mongoc_client_t inner: *mut bindings::mongoc_client_t
@ -273,9 +283,7 @@ impl<'a> Client<'a> {
) )
} }
/// Queries the server for the current server status. /// Queries the server for the current server status, returns a document with this information.
///
/// See: http://api.mongodb.org/c/current/mongoc_client_get_server_status.html
pub fn get_server_status(&self, read_prefs: Option<ReadPrefs>) -> Result<Document> { pub fn get_server_status(&self, read_prefs: Option<ReadPrefs>) -> Result<Document> {
assert!(!self.inner.is_null()); assert!(!self.inner.is_null());
@ -315,3 +323,81 @@ impl<'a> Drop for Client<'a> {
} }
} }
} }
/// Abstraction on top of MongoDB connection URI format.
pub struct Uri {
inner: *mut bindings::mongoc_uri_t
}
impl Uri {
/// Parses a string containing a MongoDB style URI connection string.
///
/// Returns None if the uri is not in the correct format, there is no
/// further information available if this is not the case.
pub fn new<T: Into<Vec<u8>>>(uri_string: T) -> Option<Uri> {
let uri_cstring = CString::new(uri_string).unwrap();
let uri = unsafe { bindings::mongoc_uri_new(uri_cstring.as_ptr()) };
if uri.is_null() {
None
} else {
Some(Uri { inner: uri })
}
}
unsafe fn inner(&self) -> *const bindings::mongoc_uri_t {
assert!(!self.inner.is_null());
self.inner
}
pub fn as_str<'a>(&'a self) -> Cow<'a, str> {
assert!(!self.inner.is_null());
unsafe {
let cstr = CStr::from_ptr(
bindings::mongoc_uri_get_string(self.inner)
);
String::from_utf8_lossy(cstr.to_bytes())
}
}
pub fn get_database<'a>(&'a self) -> Option<Cow<'a, str>> {
assert!(!self.inner.is_null());
unsafe {
let ptr = bindings::mongoc_uri_get_database(self.inner);
if ptr.is_null() {
None
} else {
let cstr = CStr::from_ptr(ptr);
Some(String::from_utf8_lossy(cstr.to_bytes()))
}
}
}
// TODO add various methods that are available on uri
}
impl PartialEq for Uri {
fn eq(&self, other: &Uri) -> bool {
self.as_str() == other.as_str()
}
}
impl fmt::Debug for Uri {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
impl Clone for Uri {
fn clone(&self) -> Uri {
Uri::new(self.as_str().into_owned()).unwrap()
}
}
impl Drop for Uri {
fn drop(&mut self) {
assert!(!self.inner.is_null());
unsafe {
bindings::mongoc_uri_destroy(self.inner);
}
}
}

@ -1,3 +1,7 @@
//! Access to a MongoDB collection.
//!
//! `Collection` is the main type used when accessing collections.
use std::ptr; use std::ptr;
use std::ffi::CStr; use std::ffi::CStr;
use std::borrow::Cow; use std::borrow::Cow;
@ -12,7 +16,6 @@ use super::Result;
use super::CommandAndFindOptions; use super::CommandAndFindOptions;
use super::{BsoncError,InvalidParamsError}; use super::{BsoncError,InvalidParamsError};
use super::bsonc::Bsonc; use super::bsonc::Bsonc;
use super::bulk_operation::BulkOperation;
use super::client::Client; use super::client::Client;
use super::cursor; use super::cursor;
use super::cursor::{Cursor,TailingCursor}; use super::cursor::{Cursor,TailingCursor};
@ -21,6 +24,7 @@ use super::flags::{Flags,FlagsValue,InsertFlag,QueryFlag,RemoveFlag,UpdateFlag};
use super::write_concern::WriteConcern; use super::write_concern::WriteConcern;
use super::read_prefs::ReadPrefs; use super::read_prefs::ReadPrefs;
#[doc(hidden)]
pub enum CreatedBy<'a> { pub enum CreatedBy<'a> {
BorrowedClient(&'a Client<'a>), BorrowedClient(&'a Client<'a>),
OwnedClient(Client<'a>), OwnedClient(Client<'a>),
@ -28,32 +32,46 @@ pub enum CreatedBy<'a> {
OwnedDatabase(Database<'a>) OwnedDatabase(Database<'a>)
} }
/// Provides access to a collection for most CRUD operations, I.e. insert, update, delete, find, etc.
///
/// A collection instance can be created by calling `get_collection` or `take_database` on a `Client` or `Database`
/// instance.
pub struct Collection<'a> { pub struct Collection<'a> {
_created_by: CreatedBy<'a>, _created_by: CreatedBy<'a>,
inner: *mut bindings::mongoc_collection_t inner: *mut bindings::mongoc_collection_t
} }
/// Options to configure a bulk operation.
pub struct BulkOperationOptions { pub struct BulkOperationOptions {
/// If the operations must be performed in order
pub ordered: bool, pub ordered: bool,
/// `WriteConcern` to use
pub write_concern: WriteConcern pub write_concern: WriteConcern
} }
impl BulkOperationOptions { impl BulkOperationOptions {
/// Default options that are used if no options are specified
/// when creating a `BulkOperation`.
pub fn default() -> BulkOperationOptions { pub fn default() -> BulkOperationOptions {
BulkOperationOptions { BulkOperationOptions {
ordered: false, ordered: false,
write_concern: WriteConcern::new() write_concern: WriteConcern::default()
} }
} }
} }
/// Options to configure a find and modify operation.
pub struct FindAndModifyOptions { pub struct FindAndModifyOptions {
/// Sort order for the query
pub sort: Option<Document>, pub sort: Option<Document>,
/// If the new version of the document should be returned
pub new: bool, pub new: bool,
/// The fields to return
pub fields: Option<Document> pub fields: Option<Document>
} }
impl FindAndModifyOptions { impl FindAndModifyOptions {
/// Default options used if none are provided.
pub fn default() -> FindAndModifyOptions { pub fn default() -> FindAndModifyOptions {
FindAndModifyOptions { FindAndModifyOptions {
sort: None, sort: None,
@ -70,21 +88,32 @@ impl FindAndModifyOptions {
} }
} }
/// Possible find and modify operations.
pub enum FindAndModifyOperation<'a> { pub enum FindAndModifyOperation<'a> {
/// Update the matching documents
Update(&'a Document), Update(&'a Document),
/// Upsert the matching documents
Upsert(&'a Document), Upsert(&'a Document),
/// Remove the matching documents
Remove Remove
} }
/// Options to configure a count operation.
pub struct CountOptions { pub struct CountOptions {
/// The query flags to use
pub query_flags: Flags<QueryFlag>, pub query_flags: Flags<QueryFlag>,
/// Number of results to skip, zero to ignore
pub skip: u32, pub skip: u32,
/// Limit to the number of results, zero to ignore
pub limit: u32, pub limit: u32,
/// Optional extra keys to add to the count
pub opts: Option<Document>, pub opts: Option<Document>,
/// Read prefs to use
pub read_prefs: Option<ReadPrefs> pub read_prefs: Option<ReadPrefs>
} }
impl CountOptions { impl CountOptions {
/// Default options used if none are provided.
pub fn default() -> CountOptions { pub fn default() -> CountOptions {
CountOptions { CountOptions {
query_flags: Flags::new(), query_flags: Flags::new(),
@ -96,54 +125,70 @@ impl CountOptions {
} }
} }
/// Options to configure an insert operation.
pub struct InsertOptions { pub struct InsertOptions {
/// Flags to use
pub insert_flags: Flags<InsertFlag>, pub insert_flags: Flags<InsertFlag>,
/// Write concern to use
pub write_concern: WriteConcern pub write_concern: WriteConcern
} }
impl InsertOptions { impl InsertOptions {
/// Default options used if none are provided.
pub fn default() -> InsertOptions { pub fn default() -> InsertOptions {
InsertOptions { InsertOptions {
insert_flags: Flags::new(), insert_flags: Flags::new(),
write_concern: WriteConcern::new() write_concern: WriteConcern::default()
} }
} }
} }
/// Options to configure a remove operation.
pub struct RemoveOptions { pub struct RemoveOptions {
/// Flags to use
pub remove_flags: Flags<RemoveFlag>, pub remove_flags: Flags<RemoveFlag>,
/// Write concern to use
pub write_concern: WriteConcern pub write_concern: WriteConcern
} }
impl RemoveOptions { impl RemoveOptions {
/// Default options used if none are provided.
pub fn default() -> RemoveOptions { pub fn default() -> RemoveOptions {
RemoveOptions { RemoveOptions {
remove_flags: Flags::new(), remove_flags: Flags::new(),
write_concern: WriteConcern::new() write_concern: WriteConcern::default()
} }
} }
} }
/// Options to configure an update operation.
pub struct UpdateOptions { pub struct UpdateOptions {
/// Flags to use
pub update_flags: Flags<UpdateFlag>, pub update_flags: Flags<UpdateFlag>,
/// Write concern to use
pub write_concern: WriteConcern pub write_concern: WriteConcern
} }
impl UpdateOptions { impl UpdateOptions {
/// Default options used if none are provided.
pub fn default() -> UpdateOptions { pub fn default() -> UpdateOptions {
UpdateOptions { UpdateOptions {
update_flags: Flags::new(), update_flags: Flags::new(),
write_concern: WriteConcern::new() write_concern: WriteConcern::default()
} }
} }
} }
/// Options to configure a tailing query.
pub struct TailOptions { pub struct TailOptions {
/// Duration to wait before checking for new results
pub wait_duration: Duration, pub wait_duration: Duration,
/// Maximum number of retries if there is an error
pub max_retries: u32 pub max_retries: u32
} }
impl TailOptions { impl TailOptions {
/// Default options used if none are provided.
pub fn default() -> TailOptions { pub fn default() -> TailOptions {
TailOptions { TailOptions {
wait_duration: Duration::from_millis(500), wait_duration: Duration::from_millis(500),
@ -153,6 +198,7 @@ impl TailOptions {
} }
impl<'a> Collection<'a> { impl<'a> Collection<'a> {
#[doc(hidden)]
pub fn new( pub fn new(
created_by: CreatedBy<'a>, created_by: CreatedBy<'a>,
inner: *mut bindings::mongoc_collection_t inner: *mut bindings::mongoc_collection_t
@ -164,9 +210,8 @@ impl<'a> Collection<'a> {
} }
} }
/// Execute a command on the collection /// Execute a command on the collection.
/// /// This is performed lazily and therefore requires calling `next` on the resulting cursor.
/// See: http://api.mongodb.org/c/current/mongoc_collection_command.html
pub fn command( pub fn command(
&'a self, &'a self,
command: Document, command: Document,
@ -208,19 +253,14 @@ impl<'a> Collection<'a> {
)) ))
} }
/// Simplified version of command that returns the first document /// Simplified version of `command` that returns the first document immediately.
///
/// See: http://api.mongodb.org/c/current/mongoc_database_command_simple.html
pub fn command_simple( pub fn command_simple(
&'a self, &'a self,
command: Document, command: Document,
options: Option<&CommandAndFindOptions> read_prefs: Option<&ReadPrefs>
) -> Result<Document> { ) -> Result<Document> {
assert!(!self.inner.is_null()); assert!(!self.inner.is_null());
let default_options = CommandAndFindOptions::default();
let options = options.unwrap_or(&default_options);
// Bsonc to store the reply // Bsonc to store the reply
let mut reply = Bsonc::new(); let mut reply = Bsonc::new();
// Empty error that might be filled // Empty error that might be filled
@ -230,7 +270,7 @@ impl<'a> Collection<'a> {
bindings::mongoc_collection_command_simple( bindings::mongoc_collection_command_simple(
self.inner, self.inner,
try!(Bsonc::from_document(&command)).inner(), try!(Bsonc::from_document(&command)).inner(),
match options.read_prefs { match read_prefs {
Some(ref prefs) => prefs.inner(), Some(ref prefs) => prefs.inner(),
None => ptr::null() None => ptr::null()
}, },
@ -249,6 +289,10 @@ impl<'a> Collection<'a> {
} }
} }
/// Execute a count query on the underlying collection.
/// The `query` bson is not validated, simply passed along to the server. As such, compatibility and errors should be validated in the appropriate server documentation.
///
/// For more information, see the [query reference](https://docs.mongodb.org/manual/reference/operator/query/) at the MongoDB website.
pub fn count( pub fn count(
&self, &self,
query: &Document, query: &Document,
@ -290,6 +334,9 @@ impl<'a> Collection<'a> {
} }
} }
/// Create a bulk operation. After creating call various functions such as `update`,
/// `insert` and others. When calling `execute` these operations will be executed in
/// batches.
pub fn create_bulk_operation( pub fn create_bulk_operation(
&'a self, &'a self,
options: Option<&BulkOperationOptions> options: Option<&BulkOperationOptions>
@ -310,6 +357,7 @@ impl<'a> Collection<'a> {
BulkOperation::new(self, inner) BulkOperation::new(self, inner)
} }
/// Request that a collection be dropped, including all indexes associated with the collection.
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();
@ -326,6 +374,10 @@ impl<'a> Collection<'a> {
Ok(()) Ok(())
} }
/// Execute a query on the underlying collection.
/// If no options are necessary, query can simply contain a query such as `{a:1}`.
/// If you would like to specify options such as a sort order, the query must be placed inside of `{"$query": {}}`
/// as specified by the server documentation. See the example below for how to properly specify additional options to query.
pub fn find( pub fn find(
&'a self, &'a self,
query: &Document, query: &Document,
@ -367,10 +419,9 @@ impl<'a> Collection<'a> {
)) ))
} }
// Update and return an object. /// Update and return an object.
// /// This is a thin wrapper around the findAndModify command. Pass in
// This is a thin wrapper around the findAndModify command. Pass in /// an operation that either updates, upserts or removes.
// an operation that either updates, upserts or removes.
pub fn find_and_modify( pub fn find_and_modify(
&'a self, &'a self,
query: &Document, query: &Document,
@ -443,6 +494,7 @@ impl<'a> Collection<'a> {
} }
} }
/// Get the name of the collection.
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))
@ -450,6 +502,9 @@ impl<'a> Collection<'a> {
String::from_utf8_lossy(cstr.to_bytes()) String::from_utf8_lossy(cstr.to_bytes())
} }
/// Insert document into collection.
/// If no `_id` element is found in document, then an id will be generated locally and added to the document.
// TODO: You can retrieve a generated _id from mongoc_collection_get_last_error().
pub fn insert( pub fn insert(
&'a self, &'a self,
document: &Document, document: &Document,
@ -478,6 +533,9 @@ impl<'a> Collection<'a> {
} }
} }
/// Remove documents in the given collection that match selector.
/// The bson `selector` is not validated, simply passed along as appropriate to the server. As such, compatibility and errors should be validated in the appropriate server documentation.
/// If you want to limit deletes to a single document, add the `SingleRemove` flag.
pub fn remove( pub fn remove(
&self, &self,
selector: &Document, selector: &Document,
@ -506,6 +564,8 @@ impl<'a> Collection<'a> {
} }
} }
/// Save a document into the collection. If the document has an `_id` field it will be updated.
/// Otherwise it will be inserted.
pub fn save( pub fn save(
&self, &self,
document: &Document, document: &Document,
@ -513,7 +573,7 @@ impl<'a> Collection<'a> {
) -> Result<()> { ) -> Result<()> {
assert!(!self.inner.is_null()); assert!(!self.inner.is_null());
let default_write_concern = WriteConcern::new(); let default_write_concern = WriteConcern::default();
let write_concern = write_concern.unwrap_or(&default_write_concern); let write_concern = write_concern.unwrap_or(&default_write_concern);
let mut error = BsoncError::empty(); let mut error = BsoncError::empty();
@ -533,9 +593,8 @@ impl<'a> Collection<'a> {
} }
} }
/// This function shall update documents in collection that match selector. /// This function updates documents in collection that match selector.
/// /// By default, updates only a single document. Add `MultiUpdate` flag to update multiple documents.
/// See: http://api.mongodb.org/c/current/mongoc_collection_update.html
pub fn update( pub fn update(
&self, &self,
selector: &Document, selector: &Document,
@ -607,3 +666,183 @@ impl<'a> Drop for Collection<'a> {
} }
} }
} }
/// Provides an abstraction for submitting multiple write operations as a single batch.
///
/// Create a `BulkOperation` by calling `create_bulk_operation` on a `Collection`. After adding all of
/// the write operations using the functions on this struct, `execute` to execute the operation on
/// the server in batches. After executing the bulk operation is consumed and cannot be used anymore.
pub struct BulkOperation<'a> {
_collection: &'a Collection<'a>,
inner: *mut bindings::mongoc_bulk_operation_t
}
impl<'a>BulkOperation<'a> {
/// Create a new bulk operation, only for internal usage.
fn new(
collection: &'a Collection<'a>,
inner: *mut bindings::mongoc_bulk_operation_t
) -> BulkOperation<'a> {
assert!(!inner.is_null());
BulkOperation {
_collection: collection,
inner: inner
}
}
/// Queue an insert of a single document into a bulk operation.
/// The insert is not performed until `execute` is called.
pub fn insert(
&self,
document: &Document
) -> Result<()> {
assert!(!self.inner.is_null());
unsafe {
bindings::mongoc_bulk_operation_insert(
self.inner,
try!(Bsonc::from_document(&document)).inner()
)
}
Ok(())
}
/// Queue removal of all documents matching the provided selector into a bulk operation.
/// The removal is not performed until `execute` is called.
pub fn remove(
&self,
selector: &Document
) -> Result<()> {
assert!(!self.inner.is_null());
unsafe {
bindings::mongoc_bulk_operation_remove(
self.inner,
try!(Bsonc::from_document(&selector)).inner()
)
}
Ok(())
}
/// Queue removal of a single document into a bulk operation.
/// The removal is not performed until `execute` is called.
pub fn remove_one(
&self,
selector: &Document
) -> Result<()> {
assert!(!self.inner.is_null());
unsafe {
bindings::mongoc_bulk_operation_remove_one(
self.inner,
try!(Bsonc::from_document(&selector)).inner()
)
}
Ok(())
}
/// Queue replacement of a single document into a bulk operation.
/// The replacement is not performed until `execute` is called.
pub fn replace_one(
&self,
selector: &Document,
document: &Document,
upsert: bool
) -> Result<()> {
assert!(!self.inner.is_null());
unsafe {
bindings::mongoc_bulk_operation_replace_one(
self.inner,
try!(Bsonc::from_document(&selector)).inner(),
try!(Bsonc::from_document(&document)).inner(),
upsert as u8
)
}
Ok(())
}
/// Queue update of a single documents into a bulk operation.
/// The update is not performed until `execute` is called.
///
/// TODO: document must only contain fields whose key starts
/// with $, these is no error handling for this.
pub fn update_one(
&self,
selector: &Document,
document: &Document,
upsert: bool
) -> Result<()> {
assert!(!self.inner.is_null());
unsafe {
bindings::mongoc_bulk_operation_update_one(
self.inner,
try!(Bsonc::from_document(&selector)).inner(),
try!(Bsonc::from_document(&document)).inner(),
upsert as u8
)
}
Ok(())
}
/// Queue update of multiple documents into a bulk operation.
/// The update is not performed until `execute` is called.
///
/// TODO: document must only contain fields whose key starts
/// with $, these is no error handling for this.
pub fn update(
&self,
selector: &Document,
document: &Document,
upsert: bool
) -> Result<()> {
assert!(!self.inner.is_null());
unsafe {
bindings::mongoc_bulk_operation_update(
self.inner,
try!(Bsonc::from_document(&selector)).inner(),
try!(Bsonc::from_document(&document)).inner(),
upsert as u8
)
}
Ok(())
}
/// This function executes all operations queued into this bulk operation.
/// If ordered was set true, forward progress will be stopped upon the first error.
///
/// This function takes ownership because it is not possible to execute a bulk operation
/// multiple times.
///
/// Returns a document with an overview of the bulk operation if successfull.
pub fn execute(self) -> Result<Document> {
// Bsonc to store the reply
let mut reply = Bsonc::new();
// Empty error that might be filled
let mut error = BsoncError::empty();
// Execute the operation. This returns a non-zero hint of the peer node on
// success, otherwise 0 and error is set.
let return_value = unsafe {
bindings::mongoc_bulk_operation_execute(
self.inner,
reply.mut_inner(),
error.mut_inner()
)
};
if return_value != 0 {
match reply.as_document() {
Ok(document) => return Ok(document),
Err(error) => return Err(error.into())
}
} else {
Err(error.into())
}
}
}
impl<'a> Drop for BulkOperation<'a> {
fn drop(&mut self) {
assert!(!self.inner.is_null());
unsafe {
bindings::mongoc_bulk_operation_destroy(self.inner);
}
}
}

@ -1,3 +1,5 @@
//! Access to a MongoDB query cursor.
use std::iter::Iterator; use std::iter::Iterator;
use std::ptr; use std::ptr;
use std::thread; use std::thread;
@ -16,12 +18,22 @@ use super::CommandAndFindOptions;
use super::Result; use super::Result;
#[doc(hidden)]
pub enum CreatedBy<'a> { pub enum CreatedBy<'a> {
Client(&'a Client<'a>), Client(&'a Client<'a>),
Database(&'a Database<'a>), Database(&'a Database<'a>),
Collection(&'a Collection<'a>) Collection(&'a Collection<'a>)
} }
/// Provides access to a MongoDB cursor for a normal operation.
///
/// It wraps up the wire protocol negotiation required to initiate a query and
/// retrieve an unknown number of documents. Cursors are lazy, meaning that no network
/// traffic occurs until the first call to `next`. At this point various functions to get
/// information about the state of the cursor are available.
///
/// `Cursor` implements the `Iterator` trait, so you can use with all normal Rust means
/// of iteration and looping.
pub struct Cursor<'a> { pub struct Cursor<'a> {
_created_by: CreatedBy<'a>, _created_by: CreatedBy<'a>,
inner: *mut bindings::mongoc_cursor_t, inner: *mut bindings::mongoc_cursor_t,
@ -33,6 +45,7 @@ pub struct Cursor<'a> {
} }
impl<'a> Cursor<'a> { impl<'a> Cursor<'a> {
#[doc(hidden)]
pub fn new( pub fn new(
created_by: CreatedBy<'a>, created_by: CreatedBy<'a>,
inner: *mut bindings::mongoc_cursor_t, inner: *mut bindings::mongoc_cursor_t,
@ -140,6 +153,10 @@ impl<'a> Drop for Cursor<'a> {
/// Cursor that will reconnect and resume tailing a collection /// Cursor that will reconnect and resume tailing a collection
/// at the right point if the connection fails. /// at the right point if the connection fails.
///
/// This cursor will wait for new results when there are none, so calling `next`
/// is a blocking operation. If an error occurs the iterator will retry, if errors
/// keep occuring it will eventually return an error result.
pub struct TailingCursor<'a> { pub struct TailingCursor<'a> {
collection: &'a Collection<'a>, collection: &'a Collection<'a>,
query: Document, query: Document,
@ -151,6 +168,7 @@ pub struct TailingCursor<'a> {
} }
impl<'a> TailingCursor<'a> { impl<'a> TailingCursor<'a> {
#[doc(hidden)]
pub fn new( pub fn new(
collection: &'a Collection<'a>, collection: &'a Collection<'a>,
query: Document, query: Document,

@ -1,3 +1,5 @@
//! Access to a MongoDB database.
use std::ffi::{CString,CStr}; use std::ffi::{CString,CStr};
use std::borrow::Cow; use std::borrow::Cow;
use std::ptr; use std::ptr;
@ -14,19 +16,25 @@ use super::collection;
use super::collection::Collection; use super::collection::Collection;
use super::cursor; use super::cursor;
use super::cursor::Cursor; use super::cursor::Cursor;
use super::read_prefs::ReadPrefs;
use flags::FlagsValue; use flags::FlagsValue;
#[doc(hidden)]
pub enum CreatedBy<'a> { pub enum CreatedBy<'a> {
BorrowedClient(&'a Client<'a>), BorrowedClient(&'a Client<'a>),
OwnedClient(Client<'a>) OwnedClient(Client<'a>)
} }
/// Provides access to a MongoDB database.
///
/// A database instance can be created by calling `get_database` or `take_database` on a `Client` instance.
pub struct Database<'a> { pub struct Database<'a> {
_created_by: CreatedBy<'a>, _created_by: CreatedBy<'a>,
inner: *mut bindings::mongoc_database_t inner: *mut bindings::mongoc_database_t
} }
impl<'a> Database<'a> { impl<'a> Database<'a> {
#[doc(ignore)]
pub fn new( pub fn new(
created_by: CreatedBy<'a>, created_by: CreatedBy<'a>,
inner: *mut bindings::mongoc_database_t inner: *mut bindings::mongoc_database_t
@ -38,9 +46,8 @@ impl<'a> Database<'a> {
} }
} }
/// Execute a command on the database /// Execute a command on the database.
/// /// This is performed lazily and therefore requires calling `next` on the resulting cursor.
/// See: http://api.mongodb.org/c/current/mongoc_database_command.html
pub fn command( pub fn command(
&'a self, &'a self,
command: Document, command: Document,
@ -82,19 +89,14 @@ impl<'a> Database<'a> {
)) ))
} }
/// Simplified version of command that returns the first document /// Simplified version of `command` that returns the first document immediately.
///
/// See: http://api.mongodb.org/c/current/mongoc_database_command_simple.html
pub fn command_simple( pub fn command_simple(
&'a self, &'a self,
command: Document, command: Document,
options: Option<&CommandAndFindOptions> read_prefs: Option<&ReadPrefs>
) -> Result<Document> { ) -> Result<Document> {
assert!(!self.inner.is_null()); assert!(!self.inner.is_null());
let default_options = CommandAndFindOptions::default();
let options = options.unwrap_or(&default_options);
// Bsonc to store the reply // Bsonc to store the reply
let mut reply = Bsonc::new(); let mut reply = Bsonc::new();
// Empty error that might be filled // Empty error that might be filled
@ -104,7 +106,7 @@ impl<'a> Database<'a> {
bindings::mongoc_database_command_simple( bindings::mongoc_database_command_simple(
self.inner, self.inner,
try!(Bsonc::from_document(&command)).inner(), try!(Bsonc::from_document(&command)).inner(),
match options.read_prefs { match read_prefs {
Some(ref prefs) => prefs.inner(), Some(ref prefs) => prefs.inner(),
None => ptr::null() None => ptr::null()
}, },
@ -123,6 +125,7 @@ impl<'a> Database<'a> {
} }
} }
/// Create a new collection in this database.
pub fn create_collection<S: Into<Vec<u8>>>( pub fn create_collection<S: Into<Vec<u8>>>(
&self, &self,
name: S, name: S,
@ -179,6 +182,7 @@ impl<'a> Database<'a> {
) )
} }
/// Get the name of this database.
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_database_get_name(self.inner)) CStr::from_ptr(bindings::mongoc_database_get_name(self.inner))

@ -1,23 +1,29 @@
//! Flags to configure various MongoDB operations.
use mongoc::bindings; use mongoc::bindings;
use std::collections::BTreeSet; use std::collections::BTreeSet;
/// Structure to hold flags for various flag types
pub struct Flags<T> { pub struct Flags<T> {
flags: BTreeSet<T> flags: BTreeSet<T>
} }
impl <T> Flags<T> where T: Ord { impl <T> Flags<T> where T: Ord {
/// Creare a new empty flags instance
pub fn new() -> Flags<T> { pub fn new() -> Flags<T> {
Flags { Flags {
flags: BTreeSet::new() flags: BTreeSet::new()
} }
} }
/// Add a flag to this instance
pub fn add(&mut self, flag: T) { pub fn add(&mut self, flag: T) {
self.flags.insert(flag); self.flags.insert(flag);
} }
} }
/// To provide the combined value of all flags.
pub trait FlagsValue { pub trait FlagsValue {
fn flags(&self) -> u32; fn flags(&self) -> u32;
} }

@ -1,3 +1,27 @@
//! This driver is a thin wrapper around the production-ready [Mongo C driver](https://github.com/mongodb/mongo-c-driver).
//!
//! It aims to provide a safe and ergonomic Rust interface which handles all the gnarly usage details of
//! the C driver for you. We use Rust's type system to make sure that we can only use the
//! underlying C driver in the recommended way specified in it's [documentation](http://api.mongodb.org/c/current/).
//!
//! To get started create a client pool wrapped in an `Arc` so we can share it between threads. Then pop a client from it
//! you can use to perform operations.
//!
//! # Example
//!
//! ```
//! use std::sync::Arc;
//! use mongo_driver::client::{ClientPool,Uri};
//!
//! let uri = Uri::new("mongodb://localhost:27017/").unwrap();
//! let pool = Arc::new(ClientPool::new(uri.clone(), None));
//! let client = pool.pop();
//! client.get_server_status(None).unwrap();
//! ```
//!
//! See the documentation for the available modules to find out how you can use the driver beyond
//! this.
extern crate libc; extern crate libc;
extern crate mongoc_sys as mongoc; extern crate mongoc_sys as mongoc;
@ -14,14 +38,12 @@ use std::sync::{Once,ONCE_INIT};
use mongoc::bindings; use mongoc::bindings;
pub mod bulk_operation;
pub mod client; pub mod client;
pub mod collection; pub mod collection;
pub mod cursor; pub mod cursor;
pub mod database; pub mod database;
pub mod flags; pub mod flags;
pub mod read_prefs; pub mod read_prefs;
pub mod uri;
pub mod write_concern; pub mod write_concern;
mod bsonc; mod bsonc;
@ -72,16 +94,24 @@ unsafe extern "C" fn mongoc_log_handler(
} }
} }
/// Options to configure both command and find operations.
pub struct CommandAndFindOptions { pub struct CommandAndFindOptions {
/// Flags to use
pub query_flags: flags::Flags<flags::QueryFlag>, pub query_flags: flags::Flags<flags::QueryFlag>,
/// Number of documents to skip, zero to ignore
pub skip: u32, pub skip: u32,
/// Max number of documents to return, zero to ignore
pub limit: u32, pub limit: u32,
/// Number of documents in each batch, zero to ignore (default is 100)
pub batch_size: u32, pub batch_size: u32,
/// Fields to return, not all commands support this option
pub fields: Option<bson::Document>, pub fields: Option<bson::Document>,
/// Read prefs to use
pub read_prefs: Option<read_prefs::ReadPrefs> pub read_prefs: Option<read_prefs::ReadPrefs>
} }
impl CommandAndFindOptions { impl CommandAndFindOptions {
/// Default options used if none are provided.
pub fn default() -> CommandAndFindOptions { pub fn default() -> CommandAndFindOptions {
CommandAndFindOptions { CommandAndFindOptions {
query_flags: flags::Flags::new(), query_flags: flags::Flags::new(),

@ -1,10 +1,18 @@
//! Abstraction on top of the MongoDB connection read prefences.
use mongoc::bindings; use mongoc::bindings;
/// Describes how reads should be dispatched.
pub enum ReadMode { pub enum ReadMode {
/// Default mode. All operations read from the current replica set primary.
Primary, Primary,
/// All operations read from among the nearest secondary members of the replica set.
Secondary, Secondary,
/// In most situations, operations read from the primary but if it is unavailable, operations read from secondary members.
PrimaryPreferred, PrimaryPreferred,
/// In most situations, operations read from among the nearest secondary members, but if no secondaries are available, operations read from the primary.
SecondaryPreferred, SecondaryPreferred,
/// Operations read from among the nearest members of the replica set, irrespective of the members type.
Nearest Nearest
} }
@ -18,11 +26,16 @@ fn read_mode_value(read_mode: &ReadMode) -> bindings::mongoc_read_mode_t {
} }
} }
/// Provides an abstraction on top of the MongoDB connection read prefences.
///
/// It allows for hinting to the driver which nodes in a replica set should be accessed first.
/// Generally, it makes the most sense to stick with the global default, `Primary`. All of the other modes come with caveats that won't be covered in great detail here.
pub struct ReadPrefs { pub struct ReadPrefs {
inner: *mut bindings::mongoc_read_prefs_t inner: *mut bindings::mongoc_read_prefs_t
} }
impl ReadPrefs { impl ReadPrefs {
/// Create a new empty read prefs.
pub fn new(read_mode: &ReadMode) -> ReadPrefs { pub fn new(read_mode: &ReadMode) -> ReadPrefs {
let read_mode_value = read_mode_value(read_mode); let read_mode_value = read_mode_value(read_mode);
let inner = unsafe { bindings::mongoc_read_prefs_new(read_mode_value) }; let inner = unsafe { bindings::mongoc_read_prefs_new(read_mode_value) };
@ -30,15 +43,18 @@ impl ReadPrefs {
ReadPrefs { inner: inner } ReadPrefs { inner: inner }
} }
/// Get a new instance of the default read pref.
pub fn default() -> ReadPrefs{ pub fn default() -> ReadPrefs{
ReadPrefs::new(&ReadMode::Primary) ReadPrefs::new(&ReadMode::Primary)
} }
#[doc(hidden)]
pub fn inner(&self) -> *const bindings::mongoc_read_prefs_t { pub fn inner(&self) -> *const bindings::mongoc_read_prefs_t {
assert!(!self.inner.is_null()); assert!(!self.inner.is_null());
self.inner self.inner
} }
#[doc(hidden)]
pub fn mut_inner(&self) -> *mut bindings::mongoc_read_prefs_t { pub fn mut_inner(&self) -> *mut bindings::mongoc_read_prefs_t {
assert!(!self.inner.is_null()); assert!(!self.inner.is_null());
self.inner as *mut bindings::mongoc_read_prefs_t self.inner as *mut bindings::mongoc_read_prefs_t

@ -1,87 +0,0 @@
use std::borrow::Cow;
use std::ffi::{CStr,CString};
use std::fmt;
use mongoc::bindings;
/// Abstraction on top of MongoDB connection URI format.
/// See: http://api.mongodb.org/c/current/mongoc_uri_t.html
pub struct Uri {
inner: *mut bindings::mongoc_uri_t
}
impl Uri {
/// Parses a string containing a MongoDB style URI connection string.
///
/// Returns None if the uri is not in the correct format, there is no
/// further information available if this is not the case.
///
/// See: http://api.mongodb.org/c/current/mongoc_uri_new.html
pub fn new<T: Into<Vec<u8>>>(uri_string: T) -> Option<Uri> {
let uri_cstring = CString::new(uri_string).unwrap();
let uri = unsafe { bindings::mongoc_uri_new(uri_cstring.as_ptr()) };
if uri.is_null() {
None
} else {
Some(Uri { inner: uri })
}
}
pub unsafe fn inner(&self) -> *const bindings::mongoc_uri_t {
assert!(!self.inner.is_null());
self.inner
}
pub fn as_str<'a>(&'a self) -> Cow<'a, str> {
assert!(!self.inner.is_null());
unsafe {
let cstr = CStr::from_ptr(
bindings::mongoc_uri_get_string(self.inner)
);
String::from_utf8_lossy(cstr.to_bytes())
}
}
pub fn get_database<'a>(&'a self) -> Option<Cow<'a, str>> {
assert!(!self.inner.is_null());
unsafe {
let ptr = bindings::mongoc_uri_get_database(self.inner);
if ptr.is_null() {
None
} else {
let cstr = CStr::from_ptr(ptr);
Some(String::from_utf8_lossy(cstr.to_bytes()))
}
}
}
// TODO add various methods that are available on uri
}
impl PartialEq for Uri {
fn eq(&self, other: &Uri) -> bool {
self.as_str() == other.as_str()
}
}
impl fmt::Debug for Uri {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
impl Clone for Uri {
fn clone(&self) -> Uri {
Uri::new(self.as_str().into_owned()).unwrap()
}
}
impl Drop for Uri {
fn drop(&mut self) {
assert!(!self.inner.is_null());
unsafe {
bindings::mongoc_uri_destroy(self.inner);
}
}
}

@ -1,16 +1,44 @@
//! Abstraction on top of the MongoDB connection write concern.
use mongoc::bindings; use mongoc::bindings;
/// Possible write concern levels, only default is supported at the moment.
pub enum WriteConcernLevel {
/// By default, writes block awaiting acknowledgment from MongoDB. Acknowledged write concern allows clients to catch network, duplicate key, and other errors.
Default,
// We'd like to support the following write concerns too at some point, pull request welcome:
// With this write concern, MongoDB does not acknowledge the receipt of write operation. Unacknowledged is similar to errors ignored; however, mongoc attempts to receive and handle network errors when possible.
// WriteUnacknowledged,
// Block until a write has been propagated to a majority of the nodes in the replica set.
// Majority,
// Block until a write has been propagated to at least n nodes in the replica set.
// AtLeastNumberOfNodes(u32),
// Block until the node receiving the write has committed the journal.
// Journal
}
/// This tells the driver what level of acknowledgment to await from the server.
/// The default, `Default`, is right for the great majority of applications.
pub struct WriteConcern { pub struct WriteConcern {
inner: *mut bindings::mongoc_write_concern_t inner: *mut bindings::mongoc_write_concern_t
} }
impl WriteConcern { impl WriteConcern {
pub fn new() -> WriteConcern { /// Get the default write concern
pub fn default() -> WriteConcern {
Self::new(WriteConcernLevel::Default)
}
/// Create a new write concern
pub fn new(_: WriteConcernLevel) -> WriteConcern {
let inner = unsafe { bindings::mongoc_write_concern_new() }; let inner = unsafe { bindings::mongoc_write_concern_new() };
assert!(!inner.is_null()); assert!(!inner.is_null());
WriteConcern { inner: inner } WriteConcern { inner: inner }
} }
#[doc(hidden)]
pub fn inner(&self) -> *const bindings::mongoc_write_concern_t { pub fn inner(&self) -> *const bindings::mongoc_write_concern_t {
assert!(!self.inner.is_null()); assert!(!self.inner.is_null());
self.inner self.inner

@ -1,7 +1,6 @@
use chrono::*; use chrono::*;
use mongo_driver::uri::Uri; use mongo_driver::client::{ClientPool,Uri};
use mongo_driver::client::ClientPool;
use bson::oid::ObjectId; use bson::oid::ObjectId;
use bson::spec::BinarySubtype; use bson::spec::BinarySubtype;

@ -2,8 +2,7 @@ use std::env;
use bson; use bson;
use mongo_driver::uri::Uri; use mongo_driver::client::{ClientPool,Uri};
use mongo_driver::client::ClientPool;
#[test] #[test]
fn test_execute_error() { fn test_execute_error() {

@ -3,8 +3,7 @@ use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use std::thread; use std::thread;
use mongo_driver::uri::Uri; use mongo_driver::client::{ClientPool,SslOptions,Uri};
use mongo_driver::client::{ClientPool,SslOptions};
#[test] #[test]
fn test_new_pool_pop_client_and_borrow_collection() { fn test_new_pool_pop_client_and_borrow_collection() {

@ -2,8 +2,7 @@ use bson;
use mongo_driver::CommandAndFindOptions; use mongo_driver::CommandAndFindOptions;
use mongo_driver::collection::{CountOptions,FindAndModifyOperation}; use mongo_driver::collection::{CountOptions,FindAndModifyOperation};
use mongo_driver::uri::Uri; use mongo_driver::client::{ClientPool,Uri};
use mongo_driver::client::ClientPool;
use mongo_driver::flags; use mongo_driver::flags;
#[test] #[test]

@ -4,8 +4,7 @@ use std::time::Duration;
use bson; use bson;
use mongo_driver::uri::Uri; use mongo_driver::client::{ClientPool,Uri};
use mongo_driver::client::ClientPool;
use mongo_driver::Result; use mongo_driver::Result;
#[test] #[test]

@ -1,5 +1,4 @@
use mongo_driver::uri::Uri; use mongo_driver::client::{ClientPool,Uri};
use mongo_driver::client::ClientPool;
#[test] #[test]
fn test_command() { fn test_command() {

@ -1,4 +1,4 @@
use mongo_driver::uri::Uri; use mongo_driver::client::Uri;
#[test] #[test]
fn test_new_uri() { fn test_new_uri() {

@ -1,7 +1,7 @@
use mongo_driver::write_concern::WriteConcern; use mongo_driver::write_concern::WriteConcern;
#[test] #[test]
fn test_write_concern() { fn test_default_write_concern() {
let write_concern = WriteConcern::new(); let write_concern = WriteConcern::default();
assert!(!write_concern.inner().is_null()); assert!(!write_concern.inner().is_null());
} }

Loading…
Cancel
Save