Skip to content

Commit 578954b

Browse files
authored
RUST-1048 Add method for retrieving the URI's default database from Client (#488)
1 parent cdd7583 commit 578954b

File tree

5 files changed

+103
-1
lines changed

5 files changed

+103
-1
lines changed

src/client/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,18 @@ impl Client {
168168
Database::new(self.clone(), name, Some(options))
169169
}
170170

171+
/// Gets a handle to the default database specified in the `ClientOptions` or MongoDB connection
172+
/// string used to construct this `Client`.
173+
///
174+
/// If no default database was specified, `None` will be returned.
175+
pub fn default_database(&self) -> Option<Database> {
176+
self.inner
177+
.options
178+
.default_database
179+
.as_ref()
180+
.map(|db_name| self.database(db_name))
181+
}
182+
171183
async fn list_databases_common(
172184
&self,
173185
filter: impl Into<Option<Document>>,

src/client/options/mod.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,12 @@ pub struct ClientOptions {
517517
#[builder(default)]
518518
pub server_selection_timeout: Option<Duration>,
519519

520+
/// Default database for this client.
521+
///
522+
/// By default, no default database is specified.
523+
#[builder(default)]
524+
pub default_database: Option<String>,
525+
520526
#[builder(default, setter(skip))]
521527
pub(crate) socket_timeout: Option<Duration>,
522528

@@ -702,6 +708,7 @@ struct ClientOptionsParser {
702708
pub zlib_compression: Option<i32>,
703709
pub direct_connection: Option<bool>,
704710
pub credential: Option<Credential>,
711+
pub default_database: Option<String>,
705712
max_staleness: Option<Duration>,
706713
tls_insecure: Option<bool>,
707714
auth_mechanism: Option<AuthMechanism>,
@@ -931,6 +938,7 @@ impl From<ClientOptionsParser> for ClientOptions {
931938
retry_writes: parser.retry_writes,
932939
socket_timeout: parser.socket_timeout,
933940
direct_connection: parser.direct_connection,
941+
default_database: parser.default_database,
934942
driver_info: None,
935943
credential: parser.credential,
936944
cmap_event_handler: None,
@@ -969,6 +977,9 @@ impl ClientOptions {
969977
///
970978
/// The format of a MongoDB connection string is described [here](https://docs.mongodb.com/manual/reference/connection-string/#connection-string-formats).
971979
///
980+
/// Note that [default_database](ClientOptions::default_database) will be set from
981+
/// `/defaultauthdb` in connection string.
982+
///
972983
/// The following options are supported in the options query string:
973984
///
974985
/// * `appName`: maps to the `app_name` field
@@ -1468,7 +1479,7 @@ impl ClientOptionsParser {
14681479
credential.source = options
14691480
.auth_source
14701481
.clone()
1471-
.or(db)
1482+
.or(db.clone())
14721483
.or_else(|| Some("admin".into()));
14731484
} else if authentication_requested {
14741485
return Err(ErrorKind::InvalidArgument {
@@ -1481,6 +1492,9 @@ impl ClientOptionsParser {
14811492
}
14821493
};
14831494

1495+
// set default database.
1496+
options.default_database = db;
1497+
14841498
if options.tls.is_none() && options.srv {
14851499
options.tls = Some(Tls::Enabled(Default::default()));
14861500
}

src/client/options/test.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,3 +232,41 @@ async fn parse_unknown_options() {
232232
.await;
233233
parse_uri("maxstalenessms", Some("maxstalenessseconds")).await;
234234
}
235+
236+
#[cfg_attr(feature = "tokio-runtime", tokio::test)]
237+
#[cfg_attr(feature = "async-std-runtime", async_std::test)]
238+
async fn parse_with_default_database() {
239+
let uri = "mongodb://localhost/abc";
240+
241+
assert_eq!(
242+
ClientOptions::parse(uri).await.unwrap(),
243+
ClientOptions {
244+
hosts: vec![ServerAddress::Tcp {
245+
host: "localhost".to_string(),
246+
port: None
247+
}],
248+
original_uri: Some(uri.into()),
249+
default_database: Some("abc".to_string()),
250+
..Default::default()
251+
}
252+
);
253+
}
254+
255+
#[cfg_attr(feature = "tokio-runtime", tokio::test)]
256+
#[cfg_attr(feature = "async-std-runtime", async_std::test)]
257+
async fn parse_with_no_default_database() {
258+
let uri = "mongodb://localhost/";
259+
260+
assert_eq!(
261+
ClientOptions::parse(uri).await.unwrap(),
262+
ClientOptions {
263+
hosts: vec![ServerAddress::Tcp {
264+
host: "localhost".to_string(),
265+
port: None
266+
}],
267+
original_uri: Some(uri.into()),
268+
default_database: None,
269+
..Default::default()
270+
}
271+
);
272+
}

src/sync/client/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,14 @@ impl Client {
119119
Database::new(self.async_client.database_with_options(name, options))
120120
}
121121

122+
/// Gets a handle to the default database specified in the `ClientOptions` or MongoDB connection
123+
/// string used to construct this `Client`.
124+
///
125+
/// If no default database was specified, `None` will be returned.
126+
pub fn default_database(&self) -> Option<Database> {
127+
self.async_client.default_database().map(Database::new)
128+
}
129+
122130
/// Gets information about each database present in the cluster the Client is connected to.
123131
pub fn list_databases(
124132
&self,

src/sync/test.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,36 @@ fn client() {
7575
assert!(db_names.contains(&function_name!().to_string()));
7676
}
7777

78+
#[test]
79+
#[function_name::named]
80+
fn default_database() {
81+
// here we just test default database name matched, the database interactive logic
82+
// is tested in `database`.
83+
let _guard: RwLockReadGuard<()> = RUNTIME.block_on(async { LOCK.run_concurrently().await });
84+
85+
let options = CLIENT_OPTIONS.clone();
86+
let client = Client::with_options(options).expect("client creation should succeed");
87+
let default_db = client.default_database();
88+
assert!(default_db.is_none());
89+
90+
// create client througth options.
91+
let mut options = CLIENT_OPTIONS.clone();
92+
options.default_database = Some("abcd".to_string());
93+
let client = Client::with_options(options).expect("client creation should succeed");
94+
let default_db = client
95+
.default_database()
96+
.expect("should have a default database.");
97+
assert_eq!(default_db.name(), "abcd");
98+
99+
// create client directly through uri_str.
100+
let client = Client::with_uri_str("mongodb://localhost:27017/abcd")
101+
.expect("client creation should succeed");
102+
let default_db = client
103+
.default_database()
104+
.expect("should have a default database.");
105+
assert_eq!(default_db.name(), "abcd");
106+
}
107+
78108
#[test]
79109
#[function_name::named]
80110
fn database() {

0 commit comments

Comments
 (0)