Add command on collection and database

pull/3/head
Thijs Cadier 9 years ago
parent 82852b98ce
commit d2e0fbc109

@ -7,6 +7,7 @@ use mongo_c_driver_wrapper::bindings;
use bson::{Bson,Document}; use bson::{Bson,Document};
use super::Result; use super::Result;
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::bulk_operation::BulkOperation;
@ -62,28 +63,6 @@ impl CountOptions {
} }
} }
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 struct InsertOptions {
pub insert_flags: Flags<InsertFlag>, pub insert_flags: Flags<InsertFlag>,
pub write_concern: WriteConcern pub write_concern: WriteConcern
@ -138,6 +117,47 @@ impl<'a> Collection<'a> {
} }
} }
/// Execute a command on the collection
///
/// See: http://api.mongodb.org/c/current/mongoc_collection_command.html
pub fn command(
&'a self,
command: Document,
options: Option<&CommandAndFindOptions>
) -> Result<Cursor<'a>> {
assert!(!self.inner.is_null());
let default_options = CommandAndFindOptions::default();
let options = options.unwrap_or(&default_options);
let inner = unsafe {
bindings::mongoc_collection_command(
self.inner,
options.query_flags.flags(),
options.skip,
options.limit,
options.batch_size,
try!(Bsonc::from_document(&command)).inner(),
match options.fields {
Some(ref f) => {
try!(Bsonc::from_document(f)).inner()
},
None => ptr::null()
},
match options.read_prefs {
Some(ref prefs) => prefs.inner(),
None => ptr::null()
}
)
};
if inner.is_null() {
return Err(InvalidParamsError.into())
}
Ok(Cursor::new(cursor::CreatedBy::Collection(self), inner))
}
pub fn count( pub fn count(
&self, &self,
query: &Document, query: &Document,
@ -214,11 +234,11 @@ impl<'a> Collection<'a> {
pub fn find( pub fn find(
&'a self, &'a self,
query: &Document, query: &Document,
options: Option<&FindOptions> options: Option<&CommandAndFindOptions>
) -> Result<Cursor<'a>> { ) -> Result<Cursor<'a>> {
assert!(!self.inner.is_null()); assert!(!self.inner.is_null());
let default_options = FindOptions::default(); let default_options = CommandAndFindOptions::default();
let options = options.unwrap_or(&default_options); let options = options.unwrap_or(&default_options);
let inner = unsafe { let inner = unsafe {
@ -355,7 +375,7 @@ impl<'a> Collection<'a> {
pub fn tail( pub fn tail(
&'a self, &'a self,
query: Document, query: Document,
find_options: Option<FindOptions>, find_options: Option<CommandAndFindOptions>,
tail_options: Option<TailOptions> tail_options: Option<TailOptions>
) -> TailingCursor<'a> { ) -> TailingCursor<'a> {
let mut query_with_options = Document::new(); let mut query_with_options = Document::new();
@ -368,7 +388,7 @@ impl<'a> Collection<'a> {
TailingCursor::new( TailingCursor::new(
self, self,
query_with_options, query_with_options,
find_options.unwrap_or(FindOptions::default()), find_options.unwrap_or(CommandAndFindOptions::default()),
tail_options.unwrap_or(TailOptions::default()) tail_options.unwrap_or(TailOptions::default())
) )
} }
@ -390,6 +410,20 @@ mod tests {
use super::super::client::ClientPool; use super::super::client::ClientPool;
use super::super::flags; use super::super::flags;
#[test]
fn test_command() {
let uri = Uri::new("mongodb://localhost:27017/");
let pool = ClientPool::new(uri);
let client = pool.pop();
let collection = client.get_collection("rust_driver_test", "items");
let mut command = bson::Document::new();
command.insert("ping".to_string(), bson::Bson::I32(1));
let result = collection.command(command, None).unwrap().next().unwrap().unwrap();
assert!(result.contains_key("ok"));
}
#[test] #[test]
fn test_mutation_and_finding() { fn test_mutation_and_finding() {
let uri = Uri::new("mongodb://localhost:27017/"); let uri = Uri::new("mongodb://localhost:27017/");
@ -454,7 +488,7 @@ mod tests {
{ {
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 options = super::super::CommandAndFindOptions {
query_flags: flags::Flags::new(), query_flags: flags::Flags::new(),
skip: 0, skip: 0,
limit: 0, limit: 0,

@ -8,14 +8,17 @@ use bson::{Bson,Document,oid};
use super::BsoncError; use super::BsoncError;
use super::bsonc; use super::bsonc;
use super::client::Client; use super::client::Client;
use super::database::Database;
use super::flags::QueryFlag; use super::flags::QueryFlag;
use super::collection::{Collection,FindOptions,TailOptions}; use super::collection::{Collection,TailOptions};
use super::CommandAndFindOptions;
use super::Result; use super::Result;
pub enum CreatedBy<'a> { pub enum CreatedBy<'a> {
Collection(&'a Collection<'a>), Client(&'a Client<'a>),
Client(&'a Client<'a>) Database(&'a Database<'a>),
Collection(&'a Collection<'a>)
} }
pub struct Cursor<'a> { pub struct Cursor<'a> {
@ -134,7 +137,7 @@ impl<'a> Drop for Cursor<'a> {
pub struct TailingCursor<'a> { pub struct TailingCursor<'a> {
collection: &'a Collection<'a>, collection: &'a Collection<'a>,
query: Document, query: Document,
find_options: FindOptions, find_options: CommandAndFindOptions,
tail_options: TailOptions, tail_options: TailOptions,
cursor: Option<Cursor<'a>>, cursor: Option<Cursor<'a>>,
last_seen_id: Option<oid::ObjectId>, last_seen_id: Option<oid::ObjectId>,
@ -145,7 +148,7 @@ impl<'a> TailingCursor<'a> {
pub fn new( pub fn new(
collection: &'a Collection<'a>, collection: &'a Collection<'a>,
query: Document, query: Document,
find_options: FindOptions, find_options: CommandAndFindOptions,
tail_options: TailOptions tail_options: TailOptions
) -> TailingCursor<'a> { ) -> TailingCursor<'a> {
// Add flags to make query tailable // Add flags to make query tailable

@ -6,10 +6,15 @@ use mongo_c_driver_wrapper::bindings;
use bson::Document; use bson::Document;
use super::Result; use super::Result;
use super::CommandAndFindOptions;
use super::{BsoncError,InvalidParamsError};
use super::bsonc::Bsonc; use super::bsonc::Bsonc;
use super::client::Client; use super::client::Client;
use super::collection::{Collection,CreatedBy}; use super::collection;
use error::BsoncError; use super::collection::Collection;
use super::cursor;
use super::cursor::Cursor;
use flags::FlagsValue;
pub struct Database<'a> { pub struct Database<'a> {
_client: &'a Client<'a>, _client: &'a Client<'a>,
@ -28,6 +33,47 @@ impl<'a> Database<'a> {
} }
} }
/// Execute a command on the database
///
/// See: http://api.mongodb.org/c/current/mongoc_database_command.html
pub fn command(
&'a self,
command: Document,
options: Option<&CommandAndFindOptions>
) -> Result<Cursor<'a>> {
assert!(!self.inner.is_null());
let default_options = CommandAndFindOptions::default();
let options = options.unwrap_or(&default_options);
let inner = unsafe {
bindings::mongoc_database_command(
self.inner,
options.query_flags.flags(),
options.skip,
options.limit,
options.batch_size,
try!(Bsonc::from_document(&command)).inner(),
match options.fields {
Some(ref f) => {
try!(Bsonc::from_document(f)).inner()
},
None => ptr::null()
},
match options.read_prefs {
Some(ref prefs) => prefs.inner(),
None => ptr::null()
}
)
};
if inner.is_null() {
return Err(InvalidParamsError.into())
}
Ok(Cursor::new(cursor::CreatedBy::Database(self), inner))
}
pub fn create_collection<S: Into<Vec<u8>>>( pub fn create_collection<S: Into<Vec<u8>>>(
&self, &self,
name: S, name: S,
@ -50,7 +96,7 @@ impl<'a> Database<'a> {
}; };
if error.is_empty() { if error.is_empty() {
Ok(Collection::new(CreatedBy::Database(self), coll)) Ok(Collection::new(collection::CreatedBy::Database(self), coll))
} else { } else {
Err(error.into()) Err(error.into())
} }
@ -65,7 +111,7 @@ impl<'a> Database<'a> {
collection_cstring.as_ptr() collection_cstring.as_ptr()
) )
}; };
Collection::new(CreatedBy::Database(self), coll) Collection::new(collection::CreatedBy::Database(self), coll)
} }
pub fn get_name(&self) -> Cow<str> { pub fn get_name(&self) -> Cow<str> {
@ -87,9 +133,24 @@ impl<'a> Drop for Database<'a> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use bson;
use super::super::uri::Uri; use super::super::uri::Uri;
use super::super::client::ClientPool; use super::super::client::ClientPool;
#[test]
fn test_command() {
let uri = Uri::new("mongodb://localhost:27017/");
let pool = ClientPool::new(uri);
let client = pool.pop();
let database = client.get_database("rust_test");
let mut command = bson::Document::new();
command.insert("ping".to_string(), bson::Bson::I32(1));
let result = database.command(command, None).unwrap().next().unwrap().unwrap();
assert!(result.contains_key("ok"));
}
#[test] #[test]
fn test_get_collection_and_name() { fn test_get_collection_and_name() {
let uri = Uri::new("mongodb://localhost:27017/"); let uri = Uri::new("mongodb://localhost:27017/");

@ -33,6 +33,28 @@ fn init() {
}); });
} }
pub struct CommandAndFindOptions {
pub query_flags: flags::Flags<flags::QueryFlag>,
pub skip: u32,
pub limit: u32,
pub batch_size: u32,
pub fields: Option<bson::Document>,
pub read_prefs: Option<read_prefs::ReadPrefs>
}
impl CommandAndFindOptions {
pub fn default() -> CommandAndFindOptions {
CommandAndFindOptions {
query_flags: flags::Flags::new(),
skip: 0,
limit: 0,
batch_size: 0,
fields: None,
read_prefs: None
}
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#[test] #[test]

Loading…
Cancel
Save