mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-23 00:39:20 +08:00
Introduce Connection::from_handle
This commit is contained in:
parent
f6a4feecea
commit
0042f2514f
47
src/lib.rs
47
src/lib.rs
@ -191,9 +191,6 @@ pub enum DatabaseName<'a> {
|
|||||||
Attached(&'a str),
|
Attached(&'a str),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Currently DatabaseName is only used by the backup and blob mods, so hide
|
|
||||||
// this (private) impl to avoid dead code warnings.
|
|
||||||
#[cfg(any(feature = "backup", feature = "blob"))]
|
|
||||||
impl<'a> DatabaseName<'a> {
|
impl<'a> DatabaseName<'a> {
|
||||||
fn to_cstring(&self) -> Result<CString> {
|
fn to_cstring(&self) -> Result<CString> {
|
||||||
use self::DatabaseName::{Attached, Main, Temp};
|
use self::DatabaseName::{Attached, Main, Temp};
|
||||||
@ -591,6 +588,26 @@ impl Connection {
|
|||||||
self.db.borrow().db()
|
self.db.borrow().db()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a `Connection` from a raw handle.
|
||||||
|
///
|
||||||
|
/// The underlying SQLite database connection handle will not be closed when
|
||||||
|
/// the returned connection is dropped/closed.
|
||||||
|
pub unsafe fn from_handle(db: *mut ffi::sqlite3) -> Result<Connection> {
|
||||||
|
let db_name = DatabaseName::Main.to_cstring()?;
|
||||||
|
let db_filename = ffi::sqlite3_db_filename(db, db_name.as_ptr());
|
||||||
|
let db_path = if db_filename.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
CStr::from_ptr(db_filename).to_str().ok().map(PathBuf::from)
|
||||||
|
};
|
||||||
|
let db = InnerConnection::new(db, false);
|
||||||
|
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.
|
||||||
pub fn get_interrupt_handle(&self) -> InterruptHandle {
|
pub fn get_interrupt_handle(&self) -> InterruptHandle {
|
||||||
@ -641,6 +658,7 @@ struct InnerConnection {
|
|||||||
free_rollback_hook: Option<fn(*mut ::std::os::raw::c_void)>,
|
free_rollback_hook: Option<fn(*mut ::std::os::raw::c_void)>,
|
||||||
#[cfg(feature = "hooks")]
|
#[cfg(feature = "hooks")]
|
||||||
free_update_hook: Option<fn(*mut ::std::os::raw::c_void)>,
|
free_update_hook: Option<fn(*mut ::std::os::raw::c_void)>,
|
||||||
|
owned: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
@ -815,21 +833,23 @@ To fix this, either:
|
|||||||
|
|
||||||
impl InnerConnection {
|
impl InnerConnection {
|
||||||
#[cfg(not(feature = "hooks"))]
|
#[cfg(not(feature = "hooks"))]
|
||||||
fn new(db: *mut ffi::sqlite3) -> InnerConnection {
|
fn new(db: *mut ffi::sqlite3, owned: bool) -> InnerConnection {
|
||||||
InnerConnection {
|
InnerConnection {
|
||||||
db,
|
db,
|
||||||
interrupt_lock: Arc::new(Mutex::new(db)),
|
interrupt_lock: Arc::new(Mutex::new(db)),
|
||||||
|
owned,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "hooks")]
|
#[cfg(feature = "hooks")]
|
||||||
fn new(db: *mut ffi::sqlite3) -> InnerConnection {
|
fn new(db: *mut ffi::sqlite3, owned: bool) -> InnerConnection {
|
||||||
InnerConnection {
|
InnerConnection {
|
||||||
db,
|
db,
|
||||||
interrupt_lock: Arc::new(Mutex::new(db)),
|
interrupt_lock: Arc::new(Mutex::new(db)),
|
||||||
free_commit_hook: None,
|
free_commit_hook: None,
|
||||||
free_rollback_hook: None,
|
free_rollback_hook: None,
|
||||||
free_update_hook: None,
|
free_update_hook: None,
|
||||||
|
owned,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -877,7 +897,7 @@ impl InnerConnection {
|
|||||||
// attempt to turn on extended results code; don't fail if we can't.
|
// attempt to turn on extended results code; don't fail if we can't.
|
||||||
ffi::sqlite3_extended_result_codes(db, 1);
|
ffi::sqlite3_extended_result_codes(db, 1);
|
||||||
|
|
||||||
Ok(InnerConnection::new(db))
|
Ok(InnerConnection::new(db, true))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -907,6 +927,10 @@ impl InnerConnection {
|
|||||||
!shared_handle.is_null(),
|
!shared_handle.is_null(),
|
||||||
"Bug: Somehow interrupt_lock was cleared before the DB was closed"
|
"Bug: Somehow interrupt_lock was cleared before the DB was closed"
|
||||||
);
|
);
|
||||||
|
if !self.owned {
|
||||||
|
self.db = ptr::null_mut();
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
let r = ffi::sqlite3_close(self.db);
|
let r = ffi::sqlite3_close(self.db);
|
||||||
// Need to use _raw because _guard has a reference out, and
|
// Need to use _raw because _guard has a reference out, and
|
||||||
@ -1615,6 +1639,17 @@ mod test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_handle() {
|
||||||
|
let db = checked_memory_handle();
|
||||||
|
let handle = unsafe { db.handle() };
|
||||||
|
{
|
||||||
|
let db = unsafe { Connection::from_handle(handle) }.unwrap();
|
||||||
|
db.execute_batch("PRAGMA VACUUM").unwrap();
|
||||||
|
}
|
||||||
|
db.close().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
mod query_and_then_tests {
|
mod query_and_then_tests {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
Loading…
Reference in New Issue
Block a user