From 5c265040475c230160517a1c447a2d0da02554de Mon Sep 17 00:00:00 2001 From: WindSoilder Date: Tue, 12 Oct 2021 15:18:58 +0800 Subject: [PATCH 1/9] add default_database api --- src/client/mod.rs | 11 ++++++++++ src/client/options/mod.rs | 45 ++++++++++++++++++++++++++++++++++++++- src/sync/client/mod.rs | 7 ++++++ src/sync/test.rs | 17 +++++++++++++++ 4 files changed, 79 insertions(+), 1 deletion(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index acded10d0..4c9315808 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -168,6 +168,17 @@ impl Client { Database::new(self.clone(), name, Some(options)) } + /// Gets a handle to default datbaase specified by MongoDB connection URI. + /// + /// If connection URI specified no default database, None will be returned. + pub fn default_database(&self) -> Option { + self.inner + .options + .default_database + .as_ref() + .map(|db_name| Database::new(self.clone(), db_name, None)) + } + async fn list_databases_common( &self, filter: impl Into>, diff --git a/src/client/options/mod.rs b/src/client/options/mod.rs index 59f7d2e32..6a6be1674 100644 --- a/src/client/options/mod.rs +++ b/src/client/options/mod.rs @@ -517,6 +517,12 @@ pub struct ClientOptions { #[builder(default)] pub server_selection_timeout: Option, + /// Default database for this client. + /// + /// By detault, no default database is specified. + #[builder(default)] + pub default_database: Option, + #[builder(default, setter(skip))] pub(crate) socket_timeout: Option, @@ -702,6 +708,7 @@ struct ClientOptionsParser { pub zlib_compression: Option, pub direct_connection: Option, pub credential: Option, + pub default_database: Option, max_staleness: Option, tls_insecure: Option, auth_mechanism: Option, @@ -931,6 +938,7 @@ impl From for ClientOptions { retry_writes: parser.retry_writes, socket_timeout: parser.socket_timeout, direct_connection: parser.direct_connection, + default_database: parser.default_database, driver_info: None, credential: parser.credential, cmap_event_handler: None, @@ -1468,7 +1476,7 @@ impl ClientOptionsParser { credential.source = options .auth_source .clone() - .or(db) + .or(db.clone()) .or_else(|| Some("admin".into())); } else if authentication_requested { return Err(ErrorKind::InvalidArgument { @@ -1481,6 +1489,9 @@ impl ClientOptionsParser { } }; + // set default database. + options.default_database = db.clone(); + if options.tls.is_none() && options.srv { options.tls = Some(Tls::Enabled(Default::default())); } @@ -2359,6 +2370,38 @@ mod tests { } ); } + + #[cfg_attr(feature = "tokio-runtime", tokio::test)] + #[cfg_attr(feature = "async-std-runtime", async_std::test)] + async fn with_default_database() { + let uri = "mongodb://localhost/abc"; + + assert_eq!( + ClientOptions::parse(uri).await.unwrap(), + ClientOptions { + hosts: vec![host_without_port("localhost")], + original_uri: Some(uri.into()), + default_database: Some("abc".to_string()), + ..Default::default() + } + ); + } + + #[cfg_attr(feature = "tokio-runtime", tokio::test)] + #[cfg_attr(feature = "async-std-runtime", async_std::test)] + async fn with_no_default_database() { + let uri = "mongodb://localhost/"; + + assert_eq!( + ClientOptions::parse(uri).await.unwrap(), + ClientOptions { + hosts: vec![host_without_port("localhost")], + original_uri: Some(uri.into()), + default_database: None, + ..Default::default() + } + ); + } } /// Contains the options that can be used to create a new diff --git a/src/sync/client/mod.rs b/src/sync/client/mod.rs index 6841d0396..32b975369 100644 --- a/src/sync/client/mod.rs +++ b/src/sync/client/mod.rs @@ -119,6 +119,13 @@ impl Client { Database::new(self.async_client.database_with_options(name, options)) } + /// Gets a handle to default datbaase specified by MongoDB connection URI. + /// + /// If connection URI specified no default database, None will be returned. + pub fn default_database(&self) -> Option { + self.async_client.default_database().map(Database::new) + } + /// Gets information about each database present in the cluster the Client is connected to. pub fn list_databases( &self, diff --git a/src/sync/test.rs b/src/sync/test.rs index 3236044d9..5265cdf16 100644 --- a/src/sync/test.rs +++ b/src/sync/test.rs @@ -75,6 +75,23 @@ fn client() { assert!(db_names.contains(&function_name!().to_string())); } +#[test] +#[function_name::named] +fn default_database() { + // here we just test default database name matched, the database interactive logic + // is tested in `database`. + let _guard: RwLockReadGuard<()> = RUNTIME.block_on(async { LOCK.run_concurrently().await }); + + let options = CLIENT_OPTIONS.clone(); + let client = Client::with_options(options).expect("client creation should succeed"); + let default_db = client.default_database(); + assert!(default_db.is_none()); + + let client = Client::with_uri_str("mongodb://localhost:27017/abcd").expect("client creation should succeed"); + let default_db = client.default_database().expect("shoulld have a default database."); + assert_eq!(default_db.name(), "abcd"); +} + #[test] #[function_name::named] fn database() { From 6c5b48ebb9c670dbea8092dd60ae7f0f9ce4da1c Mon Sep 17 00:00:00 2001 From: WindSoilder Date: Tue, 12 Oct 2021 15:29:23 +0800 Subject: [PATCH 2/9] update tests --- src/sync/test.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/sync/test.rs b/src/sync/test.rs index 5265cdf16..fa1c8dad4 100644 --- a/src/sync/test.rs +++ b/src/sync/test.rs @@ -87,6 +87,14 @@ fn default_database() { let default_db = client.default_database(); assert!(default_db.is_none()); + // create client througth options. + let mut options = CLIENT_OPTIONS.clone(); + options.default_database = Some("abcd".to_string()); + let client = Client::with_options(options).expect("client creation should succeed"); + let default_db = client.default_database().expect("shoulld have a default database."); + assert_eq!(default_db.name(), "abcd"); + + // creeate client directly through uri_str. let client = Client::with_uri_str("mongodb://localhost:27017/abcd").expect("client creation should succeed"); let default_db = client.default_database().expect("shoulld have a default database."); assert_eq!(default_db.name(), "abcd"); From 7f71616de26ef2d70c50846c4d56bed4e516fd50 Mon Sep 17 00:00:00 2001 From: WindSoilder Date: Tue, 12 Oct 2021 15:45:03 +0800 Subject: [PATCH 3/9] avoid clone --- src/client/options/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/options/mod.rs b/src/client/options/mod.rs index 6a6be1674..28a25fe97 100644 --- a/src/client/options/mod.rs +++ b/src/client/options/mod.rs @@ -1490,7 +1490,7 @@ impl ClientOptionsParser { }; // set default database. - options.default_database = db.clone(); + options.default_database = db; if options.tls.is_none() && options.srv { options.tls = Some(Tls::Enabled(Default::default())); From b76add54481317859af28794526b305084b95e8c Mon Sep 17 00:00:00 2001 From: WindSoilder Date: Wed, 20 Oct 2021 06:55:57 +0800 Subject: [PATCH 4/9] improve comment, move test code --- src/client/mod.rs | 5 +++-- src/client/options/mod.rs | 34 ++-------------------------------- src/client/options/test.rs | 32 ++++++++++++++++++++++++++++++++ src/sync/client/mod.rs | 5 +++-- 4 files changed, 40 insertions(+), 36 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index 4c9315808..3884084e2 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -168,9 +168,10 @@ impl Client { Database::new(self.clone(), name, Some(options)) } - /// Gets a handle to default datbaase specified by MongoDB connection URI. + /// Gets a handle to the default database specified in the `ClientOptions` or MongoDB connection string + /// used to construct this `Client`. /// - /// If connection URI specified no default database, None will be returned. + /// If no default database was specified, `None` will be returned. pub fn default_database(&self) -> Option { self.inner .options diff --git a/src/client/options/mod.rs b/src/client/options/mod.rs index 28a25fe97..32f64425b 100644 --- a/src/client/options/mod.rs +++ b/src/client/options/mod.rs @@ -977,6 +977,8 @@ impl ClientOptions { /// /// The format of a MongoDB connection string is described [here](https://docs.mongodb.com/manual/reference/connection-string/#connection-string-formats). /// + /// Note that [default_database](ClientOptions::default_database) will be set from `/defaultauthdb` in connection string. + /// /// The following options are supported in the options query string: /// /// * `appName`: maps to the `app_name` field @@ -2370,38 +2372,6 @@ mod tests { } ); } - - #[cfg_attr(feature = "tokio-runtime", tokio::test)] - #[cfg_attr(feature = "async-std-runtime", async_std::test)] - async fn with_default_database() { - let uri = "mongodb://localhost/abc"; - - assert_eq!( - ClientOptions::parse(uri).await.unwrap(), - ClientOptions { - hosts: vec![host_without_port("localhost")], - original_uri: Some(uri.into()), - default_database: Some("abc".to_string()), - ..Default::default() - } - ); - } - - #[cfg_attr(feature = "tokio-runtime", tokio::test)] - #[cfg_attr(feature = "async-std-runtime", async_std::test)] - async fn with_no_default_database() { - let uri = "mongodb://localhost/"; - - assert_eq!( - ClientOptions::parse(uri).await.unwrap(), - ClientOptions { - hosts: vec![host_without_port("localhost")], - original_uri: Some(uri.into()), - default_database: None, - ..Default::default() - } - ); - } } /// Contains the options that can be used to create a new diff --git a/src/client/options/test.rs b/src/client/options/test.rs index 3266b66ff..87d4fa230 100644 --- a/src/client/options/test.rs +++ b/src/client/options/test.rs @@ -232,3 +232,35 @@ async fn parse_unknown_options() { .await; parse_uri("maxstalenessms", Some("maxstalenessseconds")).await; } + +#[cfg_attr(feature = "tokio-runtime", tokio::test)] +#[cfg_attr(feature = "async-std-runtime", async_std::test)] +async fn parse_with_default_database() { + let uri = "mongodb://localhost/abc"; + + assert_eq!( + ClientOptions::parse(uri).await.unwrap(), + ClientOptions { + hosts: vec![ServerAddress::Tcp { host: "localhost".to_string(), port: None }], + original_uri: Some(uri.into()), + default_database: Some("abc".to_string()), + ..Default::default() + } + ); +} + +#[cfg_attr(feature = "tokio-runtime", tokio::test)] +#[cfg_attr(feature = "async-std-runtime", async_std::test)] +async fn parse_with_no_default_database() { + let uri = "mongodb://localhost/"; + + assert_eq!( + ClientOptions::parse(uri).await.unwrap(), + ClientOptions { + hosts: vec![ServerAddress::Tcp { host: "localhost".to_string(), port: None }], + original_uri: Some(uri.into()), + default_database: None, + ..Default::default() + } + ); +} diff --git a/src/sync/client/mod.rs b/src/sync/client/mod.rs index 32b975369..e906b0717 100644 --- a/src/sync/client/mod.rs +++ b/src/sync/client/mod.rs @@ -119,9 +119,10 @@ impl Client { Database::new(self.async_client.database_with_options(name, options)) } - /// Gets a handle to default datbaase specified by MongoDB connection URI. + /// Gets a handle to the default database specified in the `ClientOptions` or MongoDB connection string + /// used to construct this `Client`. /// - /// If connection URI specified no default database, None will be returned. + /// If no default database was specified, `None` will be returned. pub fn default_database(&self) -> Option { self.async_client.default_database().map(Database::new) } From e8eb097fc94d0261a9c904a1384502b46f381c07 Mon Sep 17 00:00:00 2001 From: WindSoilder Date: Wed, 20 Oct 2021 06:57:18 +0800 Subject: [PATCH 5/9] fmt --- src/client/options/test.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/client/options/test.rs b/src/client/options/test.rs index 87d4fa230..c00809ac3 100644 --- a/src/client/options/test.rs +++ b/src/client/options/test.rs @@ -241,7 +241,10 @@ async fn parse_with_default_database() { assert_eq!( ClientOptions::parse(uri).await.unwrap(), ClientOptions { - hosts: vec![ServerAddress::Tcp { host: "localhost".to_string(), port: None }], + hosts: vec![ServerAddress::Tcp { + host: "localhost".to_string(), + port: None + }], original_uri: Some(uri.into()), default_database: Some("abc".to_string()), ..Default::default() @@ -257,7 +260,10 @@ async fn parse_with_no_default_database() { assert_eq!( ClientOptions::parse(uri).await.unwrap(), ClientOptions { - hosts: vec![ServerAddress::Tcp { host: "localhost".to_string(), port: None }], + hosts: vec![ServerAddress::Tcp { + host: "localhost".to_string(), + port: None + }], original_uri: Some(uri.into()), default_database: None, ..Default::default() From c93a6e8116f1ff16e198d9d8e0656ffba5248803 Mon Sep 17 00:00:00 2001 From: WindSoilder Date: Sat, 23 Oct 2021 15:29:15 +0800 Subject: [PATCH 6/9] use self.database rather than Database::new --- src/client/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index 3884084e2..0d2566908 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -177,7 +177,7 @@ impl Client { .options .default_database .as_ref() - .map(|db_name| Database::new(self.clone(), db_name, None)) + .map(|db_name| self.database(db_name)) } async fn list_databases_common( From a3b28ac1a21178e7c87ac5df88c332995e715951 Mon Sep 17 00:00:00 2001 From: WindSoilder Date: Thu, 28 Oct 2021 08:43:39 +0800 Subject: [PATCH 7/9] fix typo --- src/client/options/mod.rs | 2 +- src/sync/test.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/options/mod.rs b/src/client/options/mod.rs index 32f64425b..5403dec85 100644 --- a/src/client/options/mod.rs +++ b/src/client/options/mod.rs @@ -519,7 +519,7 @@ pub struct ClientOptions { /// Default database for this client. /// - /// By detault, no default database is specified. + /// By default, no default database is specified. #[builder(default)] pub default_database: Option, diff --git a/src/sync/test.rs b/src/sync/test.rs index fa1c8dad4..bc895e5d0 100644 --- a/src/sync/test.rs +++ b/src/sync/test.rs @@ -94,7 +94,7 @@ fn default_database() { let default_db = client.default_database().expect("shoulld have a default database."); assert_eq!(default_db.name(), "abcd"); - // creeate client directly through uri_str. + // create client directly through uri_str. let client = Client::with_uri_str("mongodb://localhost:27017/abcd").expect("client creation should succeed"); let default_db = client.default_database().expect("shoulld have a default database."); assert_eq!(default_db.name(), "abcd"); From f32d3f12d103649fca5253b5172855dc95301004 Mon Sep 17 00:00:00 2001 From: WindSoilder Date: Thu, 28 Oct 2021 11:16:26 +0800 Subject: [PATCH 8/9] fmt code --- src/client/mod.rs | 4 ++-- src/client/options/mod.rs | 3 ++- src/sync/client/mod.rs | 4 ++-- src/sync/test.rs | 11 ++++++++--- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index 0d2566908..8c1a39bc5 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -168,8 +168,8 @@ impl Client { Database::new(self.clone(), name, Some(options)) } - /// Gets a handle to the default database specified in the `ClientOptions` or MongoDB connection string - /// used to construct this `Client`. + /// Gets a handle to the default database specified in the `ClientOptions` or MongoDB connection + /// string used to construct this `Client`. /// /// If no default database was specified, `None` will be returned. pub fn default_database(&self) -> Option { diff --git a/src/client/options/mod.rs b/src/client/options/mod.rs index 5403dec85..b0f8cba57 100644 --- a/src/client/options/mod.rs +++ b/src/client/options/mod.rs @@ -977,7 +977,8 @@ impl ClientOptions { /// /// The format of a MongoDB connection string is described [here](https://docs.mongodb.com/manual/reference/connection-string/#connection-string-formats). /// - /// Note that [default_database](ClientOptions::default_database) will be set from `/defaultauthdb` in connection string. + /// Note that [default_database](ClientOptions::default_database) will be set from + /// `/defaultauthdb` in connection string. /// /// The following options are supported in the options query string: /// diff --git a/src/sync/client/mod.rs b/src/sync/client/mod.rs index e906b0717..6c3c37f7e 100644 --- a/src/sync/client/mod.rs +++ b/src/sync/client/mod.rs @@ -119,8 +119,8 @@ impl Client { Database::new(self.async_client.database_with_options(name, options)) } - /// Gets a handle to the default database specified in the `ClientOptions` or MongoDB connection string - /// used to construct this `Client`. + /// Gets a handle to the default database specified in the `ClientOptions` or MongoDB connection + /// string used to construct this `Client`. /// /// If no default database was specified, `None` will be returned. pub fn default_database(&self) -> Option { diff --git a/src/sync/test.rs b/src/sync/test.rs index bc895e5d0..10a9242ea 100644 --- a/src/sync/test.rs +++ b/src/sync/test.rs @@ -91,12 +91,17 @@ fn default_database() { let mut options = CLIENT_OPTIONS.clone(); options.default_database = Some("abcd".to_string()); let client = Client::with_options(options).expect("client creation should succeed"); - let default_db = client.default_database().expect("shoulld have a default database."); + let default_db = client + .default_database() + .expect("shoulld have a default database."); assert_eq!(default_db.name(), "abcd"); // create client directly through uri_str. - let client = Client::with_uri_str("mongodb://localhost:27017/abcd").expect("client creation should succeed"); - let default_db = client.default_database().expect("shoulld have a default database."); + let client = Client::with_uri_str("mongodb://localhost:27017/abcd") + .expect("client creation should succeed"); + let default_db = client + .default_database() + .expect("shoulld have a default database."); assert_eq!(default_db.name(), "abcd"); } From 03bad63840576783fb6609b1dcafa198e9581594 Mon Sep 17 00:00:00 2001 From: WindSoilder Date: Thu, 28 Oct 2021 16:30:57 +0800 Subject: [PATCH 9/9] fix typo --- src/sync/test.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sync/test.rs b/src/sync/test.rs index 10a9242ea..6881b6889 100644 --- a/src/sync/test.rs +++ b/src/sync/test.rs @@ -93,7 +93,7 @@ fn default_database() { let client = Client::with_options(options).expect("client creation should succeed"); let default_db = client .default_database() - .expect("shoulld have a default database."); + .expect("should have a default database."); assert_eq!(default_db.name(), "abcd"); // create client directly through uri_str. @@ -101,7 +101,7 @@ fn default_database() { .expect("client creation should succeed"); let default_db = client .default_database() - .expect("shoulld have a default database."); + .expect("should have a default database."); assert_eq!(default_db.name(), "abcd"); }