From 82a56b1b58b32f0f95c3b16ad1cba255d9308430 Mon Sep 17 00:00:00 2001 From: Piotr Sarna Date: Tue, 29 Nov 2022 15:52:30 +0100 Subject: [PATCH] Introduce Connection::from_handle_owned It behaves almost the same as Connection::from_handle, but it promises to close the inner connection when the returned connection is closed or dropped. The rationale for having this function is that some users of Connection::from_handle obtain the handle simply by calling ffi::sqlite3_open_v2 or other similar function manually, and would still like for its resources to be released once the connection is dropped. The use-case behind this commit is from https://github.com/libsql/libsql/, where a new libsql_open call is introduced to pass other parameters (like virtual WAL interface) to the connection. --- src/lib.rs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index da07327..6166b2c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -930,6 +930,28 @@ impl Connection { }) } + /// Create a `Connection` from a raw owned handle. + /// + /// The returned connection will attempt to close the inner connection + /// when dropped/closed. This function should only be called on connections + /// owned by the caller. + /// + /// # Safety + /// + /// This function is unsafe because improper use may impact the Connection. + /// In particular, it should only be called on connections created + /// and owned by the caller, e.g. as a result of calling ffi::sqlite3_open(). + #[inline] + pub unsafe fn from_handle_owned(db: *mut ffi::sqlite3) -> Result { + let db_path = db_filename(db); + let db = InnerConnection::new(db, true); + Ok(Connection { + db: RefCell::new(db), + cache: StatementCache::with_capacity(STATEMENT_CACHE_DEFAULT_CAPACITY), + path: db_path, + }) + } + /// Get access to a handle that can be used to interrupt long running /// queries from another thread. #[inline] @@ -1793,6 +1815,16 @@ mod test { Ok(()) } + #[test] + fn test_from_handle_owned() -> Result<()> { + let mut handle: *mut ffi::sqlite3 = std::ptr::null_mut(); + let r = unsafe { ffi::sqlite3_open(":memory:\0".as_ptr() as *const i8, &mut handle) }; + assert_eq!(r, ffi::SQLITE_OK); + let db = unsafe { Connection::from_handle_owned(handle) }?; + db.execute_batch("PRAGMA VACUUM")?; + Ok(()) + } + mod query_and_then_tests { use super::*;