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.
This commit is contained in:
Piotr Sarna 2022-11-29 15:52:30 +01:00
parent 12a6d3c1b1
commit 82a56b1b58

View File

@ -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<Connection> {
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 /// Get access to a handle that can be used to interrupt long running
/// queries from another thread. /// queries from another thread.
#[inline] #[inline]
@ -1793,6 +1815,16 @@ mod test {
Ok(()) 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 { mod query_and_then_tests {
use super::*; use super::*;