mirror of
				https://github.com/isar/rusqlite.git
				synced 2025-10-31 13:58:55 +08:00 
			
		
		
		
	Merge pull request #200 from jgallagher/make-close-retryable
Make Connection::close() return the connection on failure.
This commit is contained in:
		| @@ -1,3 +1,8 @@ | |||||||
|  | # Version UPCOMING (TBD) | ||||||
|  |  | ||||||
|  | * BREAKING CHANGE: `Connection::close()` now returns a `Result<(), (Connection, Error)>` instead | ||||||
|  |   of a `Result<(), Error>` so callers get the still-open connection back on failure. | ||||||
|  |  | ||||||
| # Version 0.8.0 (2016-12-31) | # Version 0.8.0 (2016-12-31) | ||||||
|  |  | ||||||
| * BREAKING CHANGE: The `FromSql` trait has been redesigned. It now requires a single, safe | * BREAKING CHANGE: The `FromSql` trait has been redesigned. It now requires a single, safe | ||||||
|   | |||||||
							
								
								
									
										48
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								src/lib.rs
									
									
									
									
									
								
							| @@ -398,15 +398,19 @@ impl Connection { | |||||||
|     /// Close the SQLite connection. |     /// Close the SQLite connection. | ||||||
|     /// |     /// | ||||||
|     /// This is functionally equivalent to the `Drop` implementation for `Connection` except |     /// This is functionally equivalent to the `Drop` implementation for `Connection` except | ||||||
|     /// that it returns any error encountered to the caller. |     /// that on failure, it returns an error and the connection itself (presumably so closing | ||||||
|  |     /// can be attempted again). | ||||||
|     /// |     /// | ||||||
|     /// # Failure |     /// # Failure | ||||||
|     /// |     /// | ||||||
|     /// Will return `Err` if the underlying SQLite call fails. |     /// Will return `Err` if the underlying SQLite call fails. | ||||||
|     pub fn close(self) -> Result<()> { |     pub fn close(self) -> std::result::Result<(), (Connection, Error)> { | ||||||
|         self.flush_prepared_statement_cache(); |         self.flush_prepared_statement_cache(); | ||||||
|         let mut db = self.db.borrow_mut(); |         { | ||||||
|         db.close() |             let mut db = self.db.borrow_mut(); | ||||||
|  |             db.close() | ||||||
|  |         } | ||||||
|  |         .map_err(move |err| (self, err)) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Enable loading of SQLite extensions. Strongly consider using `LoadExtensionGuard` |     /// Enable loading of SQLite extensions. Strongly consider using `LoadExtensionGuard` | ||||||
| @@ -1242,6 +1246,42 @@ mod test { | |||||||
|         assert!(db.close().is_ok()); |         assert!(db.close().is_ok()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn test_close_retry() { | ||||||
|  |         let db = checked_memory_handle(); | ||||||
|  |  | ||||||
|  |         // force the DB to be busy by preparing a statement; this must be done at the FFI | ||||||
|  |         // level to allow us to call .close() without dropping the prepared statement first. | ||||||
|  |         let raw_stmt = { | ||||||
|  |             use std::mem; | ||||||
|  |             use std::ptr; | ||||||
|  |             use libc::c_int; | ||||||
|  |             use super::str_to_cstring; | ||||||
|  |  | ||||||
|  |             let raw_db = db.db.borrow_mut().db; | ||||||
|  |             let sql = "SELECT 1"; | ||||||
|  |             let mut raw_stmt: *mut ffi::sqlite3_stmt = unsafe { mem::uninitialized() }; | ||||||
|  |             let rc = unsafe { | ||||||
|  |                 ffi::sqlite3_prepare_v2(raw_db, | ||||||
|  |                                         str_to_cstring(sql).unwrap().as_ptr(), | ||||||
|  |                                         (sql.len() + 1) as c_int, | ||||||
|  |                                         &mut raw_stmt, | ||||||
|  |                                         ptr::null_mut()) | ||||||
|  |             }; | ||||||
|  |             assert_eq!(rc, ffi::SQLITE_OK); | ||||||
|  |             raw_stmt | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         let result = db.close(); | ||||||
|  |         assert!(result.is_err()); | ||||||
|  |  | ||||||
|  |         // finalize the open statement so a second close will succeed | ||||||
|  |         assert_eq!(ffi::SQLITE_OK, unsafe { ffi::sqlite3_finalize(raw_stmt) }); | ||||||
|  |  | ||||||
|  |         let (db, _) = result.unwrap_err(); | ||||||
|  |         db.close().unwrap(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_open_with_flags() { |     fn test_open_with_flags() { | ||||||
|         for bad_flags in &[OpenFlags::empty(), |         for bad_flags in &[OpenFlags::empty(), | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user