diff --git a/src/error.rs b/src/error.rs index 69aaf2e..a9d557c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -145,6 +145,11 @@ pub enum Error { #[cfg(feature = "loadable_extension")] #[cfg_attr(docsrs, doc(cfg(feature = "loadable_extension")))] InitError(ffi::InitError), + /// Error when the schema of a particular database is requested, but the index + /// is out of range. + #[cfg(feature = "modern_sqlite")] // 3.39.0 + #[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))] + InvalidDatabaseIndex(usize), } impl PartialEq for Error { @@ -206,6 +211,8 @@ impl PartialEq for Error { ) => e1 == e2 && m1 == m2 && s1 == s2 && o1 == o2, #[cfg(feature = "loadable_extension")] (Error::InitError(e1), Error::InitError(e2)) => e1 == e2, + #[cfg(feature = "modern_sqlite")] + (Error::InvalidDatabaseIndex(i1), Error::InvalidDatabaseIndex(i2)) => i1 == i2, (..) => false, } } @@ -327,6 +334,8 @@ impl fmt::Display for Error { } => write!(f, "{msg} in {sql} at offset {offset}"), #[cfg(feature = "loadable_extension")] Error::InitError(ref err) => err.fmt(f), + #[cfg(feature = "modern_sqlite")] + Error::InvalidDatabaseIndex(i) => write!(f, "Invalid database index: {i}"), } } } @@ -378,6 +387,8 @@ impl error::Error for Error { Error::SqlInputError { ref error, .. } => Some(error), #[cfg(feature = "loadable_extension")] Error::InitError(ref err) => Some(err), + #[cfg(feature = "modern_sqlite")] + Error::InvalidDatabaseIndex(_) => None, } } } diff --git a/src/lib.rs b/src/lib.rs index b682145..d069169 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1037,8 +1037,28 @@ impl Connection { self.db.borrow().db_readonly(db_name) } + /// Return the schema name for a database connection + /// + /// ## Failure + /// + /// Return an `Error::InvalidDatabaseIndex` if `index` is out of range. + #[cfg(feature = "modern_sqlite")] // 3.39.0 + #[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))] + pub fn db_name(&self, index: usize) -> Result<&str> { + unsafe { + let db = self.handle(); + let name = ffi::sqlite3_db_name(db, index as c_int); + if name.is_null() { + Err(Error::InvalidDatabaseIndex(index)) + } else { + Ok(CStr::from_ptr(name).to_str()?) + } + } + } + /// Determine whether or not an interrupt is currently in effect #[cfg(feature = "modern_sqlite")] // 3.41.0 + #[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))] pub fn is_interrupted(&self) -> bool { self.db.borrow().is_interrupted() } @@ -2212,6 +2232,18 @@ mod test { Ok(()) } + #[test] + #[cfg(feature = "modern_sqlite")] + fn test_db_name() -> Result<()> { + let db = Connection::open_in_memory()?; + assert_eq!(db.db_name(0), Ok("main")); + assert_eq!(db.db_name(1), Ok("temp")); + assert!(db.db_name(2).is_err()); + db.execute_batch("ATTACH DATABASE ':memory:' AS xyz;")?; + assert_eq!(db.db_name(2), Ok("xyz")); + Ok(()) + } + #[test] #[cfg(feature = "modern_sqlite")] fn test_is_interrupted() -> Result<()> {