mirror of
				https://github.com/isar/rusqlite.git
				synced 2025-10-31 22:08:55 +08:00 
			
		
		
		
	Introduce Connection::from_handle
This commit is contained in:
		
							
								
								
									
										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::*; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user