Skip to content

Commit 6e5e263

Browse files
committed
feat(odbc): add dbms_name method to retrieve database management system name
1 parent 3b79516 commit 6e5e263

File tree

4 files changed

+62
-1
lines changed

4 files changed

+62
-1
lines changed

sqlx-core/src/any/connection/mod.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,34 @@ impl AnyConnection {
8787
pub fn private_get_mut(&mut self) -> &mut AnyConnectionKind {
8888
&mut self.0
8989
}
90+
91+
/// Returns the runtime DBMS name for this connection.
92+
///
93+
/// For most built-in drivers this returns a well-known constant string:
94+
/// - Postgres -> "PostgreSQL"
95+
/// - MySQL -> "MySQL"
96+
/// - SQLite -> "SQLite"
97+
/// - MSSQL -> "Microsoft SQL Server"
98+
///
99+
/// For ODBC, this queries the driver at runtime via `SQL_DBMS_NAME`.
100+
pub async fn dbms_name(&mut self) -> Result<String, Error> {
101+
match &mut self.0 {
102+
#[cfg(feature = "postgres")]
103+
AnyConnectionKind::Postgres(_) => Ok("PostgreSQL".to_string()),
104+
105+
#[cfg(feature = "mysql")]
106+
AnyConnectionKind::MySql(_) => Ok("MySQL".to_string()),
107+
108+
#[cfg(feature = "sqlite")]
109+
AnyConnectionKind::Sqlite(_) => Ok("SQLite".to_string()),
110+
111+
#[cfg(feature = "mssql")]
112+
AnyConnectionKind::Mssql(_) => Ok("Microsoft SQL Server".to_string()),
113+
114+
#[cfg(feature = "odbc")]
115+
AnyConnectionKind::Odbc(conn) => conn.dbms_name().await,
116+
}
117+
}
90118
}
91119

92120
macro_rules! delegate_to {

sqlx-core/src/odbc/connection/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,17 @@ impl OdbcConnection {
2828
log_settings: LogSettings::default(),
2929
})
3030
}
31+
32+
/// Returns the name of the actual Database Management System (DBMS) this
33+
/// connection is talking to as reported by the ODBC driver.
34+
///
35+
/// This calls the underlying ODBC API `SQL_DBMS_NAME` via
36+
/// `odbc_api::Connection::database_management_system_name`.
37+
///
38+
/// See: https://docs.rs/odbc-api/19.0.1/odbc_api/struct.Connection.html#method.database_management_system_name
39+
pub async fn dbms_name(&mut self) -> Result<String, Error> {
40+
self.worker.get_dbms_name().await
41+
}
3142
}
3243

3344
impl Connection for OdbcConnection {

sqlx-core/src/odbc/connection/worker.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ enum Command {
5353
sql: Box<str>,
5454
tx: PrepareSender,
5555
},
56+
GetDbmsName {
57+
tx: oneshot::Sender<Result<String, Error>>,
58+
},
5659
}
5760

5861
impl Drop for ConnectionWorker {
@@ -156,6 +159,11 @@ impl ConnectionWorker {
156159
)
157160
.await?
158161
}
162+
163+
pub(crate) async fn get_dbms_name(&mut self) -> Result<String, Error> {
164+
let (tx, rx) = oneshot::channel();
165+
send_command_and_await(&self.command_tx, Command::GetDbmsName { tx }, rx).await?
166+
}
159167
}
160168

161169
// Worker thread implementation
@@ -254,6 +262,7 @@ fn process_command(cmd: Command, conn: &OdbcConnection) -> Option<oneshot::Sende
254262
Command::Shutdown { tx } => return Some(tx),
255263
Command::Execute { sql, args, tx } => handle_execute(conn, sql, args, tx),
256264
Command::Prepare { sql, tx } => handle_prepare(conn, sql, tx),
265+
Command::GetDbmsName { tx } => handle_get_dbms_name(conn, tx),
257266
}
258267
None
259268
}
@@ -309,6 +318,13 @@ fn handle_prepare(conn: &OdbcConnection, sql: Box<str>, tx: PrepareSender) {
309318
send_result(tx, result);
310319
}
311320

321+
fn handle_get_dbms_name(conn: &OdbcConnection, tx: oneshot::Sender<Result<String, Error>>) {
322+
let result = conn
323+
.database_management_system_name()
324+
.map_err(|e| Error::Protocol(format!("Failed to get DBMS name: {}", e)));
325+
send_result(tx, result);
326+
}
327+
312328
// Helper functions
313329
fn execute_simple(conn: &OdbcConnection, sql: &str) -> Result<(), Error> {
314330
match conn.execute(sql, (), None) {

tests/any/odbc.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ async fn it_connects_via_any_odbc() -> anyhow::Result<()> {
2525
// Simple ping test
2626
conn.ping().await?;
2727

28+
// DBMS name can be retrieved at runtime
29+
let dbms = conn.dbms_name().await?;
30+
assert!(!dbms.is_empty());
31+
2832
// Close the connection
2933
conn.close().await?;
3034

@@ -338,7 +342,9 @@ async fn it_matches_any_kind_odbc() -> anyhow::Result<()> {
338342
// Check that the connection kind is ODBC
339343
assert_eq!(conn.kind(), AnyKind::Odbc);
340344

341-
conn.close().await?;
345+
// Ensure dbms_name works on owned connection too by dropping after fetch
346+
let _ = conn;
347+
342348
Ok(())
343349
}
344350

0 commit comments

Comments
 (0)