mirror of
				https://github.com/isar/rusqlite.git
				synced 2025-10-31 13:58:55 +08:00 
			
		
		
		
	Fix callbacks lifetime
This commit is contained in:
		| @@ -179,9 +179,11 @@ mod build_bundled { | |||||||
|  |  | ||||||
|             if cfg!(feature = "bundled-sqlcipher-vendored-openssl") { |             if cfg!(feature = "bundled-sqlcipher-vendored-openssl") { | ||||||
|                 cfg.include(std::env::var("DEP_OPENSSL_INCLUDE").unwrap()); |                 cfg.include(std::env::var("DEP_OPENSSL_INCLUDE").unwrap()); | ||||||
|                 // cargo will resolve downstream to the static lib in openssl-sys |                 // cargo will resolve downstream to the static lib in | ||||||
|  |                 // openssl-sys | ||||||
|             } else if is_windows { |             } else if is_windows { | ||||||
|                 // Windows without `-vendored-openssl` takes this to link against a prebuilt OpenSSL lib |                 // Windows without `-vendored-openssl` takes this to link against a prebuilt | ||||||
|  |                 // OpenSSL lib | ||||||
|                 cfg.include(inc_dir.to_string_lossy().as_ref()); |                 cfg.include(inc_dir.to_string_lossy().as_ref()); | ||||||
|                 let lib = lib_dir.join("libcrypto.lib"); |                 let lib = lib_dir.join("libcrypto.lib"); | ||||||
|                 cfg.flag(lib.to_string_lossy().as_ref()); |                 cfg.flag(lib.to_string_lossy().as_ref()); | ||||||
|   | |||||||
| @@ -16,9 +16,9 @@ unsafe extern "C" fn free_boxed_value<T>(p: *mut c_void) { | |||||||
| impl Connection { | impl Connection { | ||||||
|     /// Add or modify a collation. |     /// Add or modify a collation. | ||||||
|     #[inline] |     #[inline] | ||||||
|     pub fn create_collation<'c, C>(&'c self, collation_name: &str, x_compare: C) -> Result<()> |     pub fn create_collation<C>(&self, collation_name: &str, x_compare: C) -> Result<()> | ||||||
|     where |     where | ||||||
|         C: Fn(&str, &str) -> Ordering + Send + UnwindSafe + 'c, |         C: Fn(&str, &str) -> Ordering + Send + UnwindSafe + 'static, | ||||||
|     { |     { | ||||||
|         self.db |         self.db | ||||||
|             .borrow_mut() |             .borrow_mut() | ||||||
| @@ -42,9 +42,9 @@ impl Connection { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl InnerConnection { | impl InnerConnection { | ||||||
|     fn create_collation<'c, C>(&'c mut self, collation_name: &str, x_compare: C) -> Result<()> |     fn create_collation<C>(&mut self, collation_name: &str, x_compare: C) -> Result<()> | ||||||
|     where |     where | ||||||
|         C: Fn(&str, &str) -> Ordering + Send + UnwindSafe + 'c, |         C: Fn(&str, &str) -> Ordering + Send + UnwindSafe + 'static, | ||||||
|     { |     { | ||||||
|         unsafe extern "C" fn call_boxed_closure<C>( |         unsafe extern "C" fn call_boxed_closure<C>( | ||||||
|             arg1: *mut c_void, |             arg1: *mut c_void, | ||||||
|   | |||||||
| @@ -380,15 +380,15 @@ impl Connection { | |||||||
|     /// |     /// | ||||||
|     /// Will return Err if the function could not be attached to the connection. |     /// Will return Err if the function could not be attached to the connection. | ||||||
|     #[inline] |     #[inline] | ||||||
|     pub fn create_scalar_function<'c, F, T>( |     pub fn create_scalar_function<F, T>( | ||||||
|         &'c self, |         &self, | ||||||
|         fn_name: &str, |         fn_name: &str, | ||||||
|         n_arg: c_int, |         n_arg: c_int, | ||||||
|         flags: FunctionFlags, |         flags: FunctionFlags, | ||||||
|         x_func: F, |         x_func: F, | ||||||
|     ) -> Result<()> |     ) -> Result<()> | ||||||
|     where |     where | ||||||
|         F: FnMut(&Context<'_>) -> Result<T> + Send + UnwindSafe + 'c, |         F: FnMut(&Context<'_>) -> Result<T> + Send + UnwindSafe + 'static, | ||||||
|         T: ToSql, |         T: ToSql, | ||||||
|     { |     { | ||||||
|         self.db |         self.db | ||||||
| @@ -462,15 +462,15 @@ impl Connection { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl InnerConnection { | impl InnerConnection { | ||||||
|     fn create_scalar_function<'c, F, T>( |     fn create_scalar_function<F, T>( | ||||||
|         &'c mut self, |         &mut self, | ||||||
|         fn_name: &str, |         fn_name: &str, | ||||||
|         n_arg: c_int, |         n_arg: c_int, | ||||||
|         flags: FunctionFlags, |         flags: FunctionFlags, | ||||||
|         x_func: F, |         x_func: F, | ||||||
|     ) -> Result<()> |     ) -> Result<()> | ||||||
|     where |     where | ||||||
|         F: FnMut(&Context<'_>) -> Result<T> + Send + UnwindSafe + 'c, |         F: FnMut(&Context<'_>) -> Result<T> + Send + UnwindSafe + 'static, | ||||||
|         T: ToSql, |         T: ToSql, | ||||||
|     { |     { | ||||||
|         unsafe extern "C" fn call_boxed_closure<F, T>( |         unsafe extern "C" fn call_boxed_closure<F, T>( | ||||||
|   | |||||||
							
								
								
									
										42
									
								
								src/hooks.rs
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								src/hooks.rs
									
									
									
									
									
								
							| @@ -345,9 +345,9 @@ impl Connection { | |||||||
|     /// |     /// | ||||||
|     /// The callback returns `true` to rollback. |     /// The callback returns `true` to rollback. | ||||||
|     #[inline] |     #[inline] | ||||||
|     pub fn commit_hook<'c, F>(&'c self, hook: Option<F>) |     pub fn commit_hook<F>(&self, hook: Option<F>) | ||||||
|     where |     where | ||||||
|         F: FnMut() -> bool + Send + 'c, |         F: FnMut() -> bool + Send + 'static, | ||||||
|     { |     { | ||||||
|         self.db.borrow_mut().commit_hook(hook); |         self.db.borrow_mut().commit_hook(hook); | ||||||
|     } |     } | ||||||
| @@ -357,9 +357,9 @@ impl Connection { | |||||||
|     /// |     /// | ||||||
|     /// The callback returns `true` to rollback. |     /// The callback returns `true` to rollback. | ||||||
|     #[inline] |     #[inline] | ||||||
|     pub fn rollback_hook<'c, F>(&'c self, hook: Option<F>) |     pub fn rollback_hook<F>(&self, hook: Option<F>) | ||||||
|     where |     where | ||||||
|         F: FnMut() + Send + 'c, |         F: FnMut() + Send + 'static, | ||||||
|     { |     { | ||||||
|         self.db.borrow_mut().rollback_hook(hook); |         self.db.borrow_mut().rollback_hook(hook); | ||||||
|     } |     } | ||||||
| @@ -375,9 +375,9 @@ impl Connection { | |||||||
|     /// - the name of the table that is updated, |     /// - the name of the table that is updated, | ||||||
|     /// - the ROWID of the row that is updated. |     /// - the ROWID of the row that is updated. | ||||||
|     #[inline] |     #[inline] | ||||||
|     pub fn update_hook<'c, F>(&'c self, hook: Option<F>) |     pub fn update_hook<F>(&self, hook: Option<F>) | ||||||
|     where |     where | ||||||
|         F: FnMut(Action, &str, &str, i64) + Send + 'c, |         F: FnMut(Action, &str, &str, i64) + Send + 'static, | ||||||
|     { |     { | ||||||
|         self.db.borrow_mut().update_hook(hook); |         self.db.borrow_mut().update_hook(hook); | ||||||
|     } |     } | ||||||
| @@ -418,9 +418,9 @@ impl InnerConnection { | |||||||
|         self.authorizer(None::<fn(AuthContext<'_>) -> Authorization>); |         self.authorizer(None::<fn(AuthContext<'_>) -> Authorization>); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn commit_hook<'c, F>(&'c mut self, hook: Option<F>) |     fn commit_hook<F>(&mut self, hook: Option<F>) | ||||||
|     where |     where | ||||||
|         F: FnMut() -> bool + Send + 'c, |         F: FnMut() -> bool + Send + 'static, | ||||||
|     { |     { | ||||||
|         unsafe extern "C" fn call_boxed_closure<F>(p_arg: *mut c_void) -> c_int |         unsafe extern "C" fn call_boxed_closure<F>(p_arg: *mut c_void) -> c_int | ||||||
|         where |         where | ||||||
| @@ -467,9 +467,9 @@ impl InnerConnection { | |||||||
|         self.free_commit_hook = free_commit_hook; |         self.free_commit_hook = free_commit_hook; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn rollback_hook<'c, F>(&'c mut self, hook: Option<F>) |     fn rollback_hook<F>(&mut self, hook: Option<F>) | ||||||
|     where |     where | ||||||
|         F: FnMut() + Send + 'c, |         F: FnMut() + Send + 'static, | ||||||
|     { |     { | ||||||
|         unsafe extern "C" fn call_boxed_closure<F>(p_arg: *mut c_void) |         unsafe extern "C" fn call_boxed_closure<F>(p_arg: *mut c_void) | ||||||
|         where |         where | ||||||
| @@ -508,9 +508,9 @@ impl InnerConnection { | |||||||
|         self.free_rollback_hook = free_rollback_hook; |         self.free_rollback_hook = free_rollback_hook; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn update_hook<'c, F>(&'c mut self, hook: Option<F>) |     fn update_hook<F>(&mut self, hook: Option<F>) | ||||||
|     where |     where | ||||||
|         F: FnMut(Action, &str, &str, i64) + Send + 'c, |         F: FnMut(Action, &str, &str, i64) + Send + 'static, | ||||||
|     { |     { | ||||||
|         unsafe extern "C" fn call_boxed_closure<F>( |         unsafe extern "C" fn call_boxed_closure<F>( | ||||||
|             p_arg: *mut c_void, |             p_arg: *mut c_void, | ||||||
| @@ -698,13 +698,13 @@ mod test { | |||||||
|     fn test_commit_hook() -> Result<()> { |     fn test_commit_hook() -> Result<()> { | ||||||
|         let db = Connection::open_in_memory()?; |         let db = Connection::open_in_memory()?; | ||||||
|  |  | ||||||
|         let mut called = false; |         static CALLED: AtomicBool = AtomicBool::new(false); | ||||||
|         db.commit_hook(Some(|| { |         db.commit_hook(Some(|| { | ||||||
|             called = true; |             CALLED.store(true, Ordering::Relaxed); | ||||||
|             false |             false | ||||||
|         })); |         })); | ||||||
|         db.execute_batch("BEGIN; CREATE TABLE foo (t TEXT); COMMIT;")?; |         db.execute_batch("BEGIN; CREATE TABLE foo (t TEXT); COMMIT;")?; | ||||||
|         assert!(called); |         assert!(CALLED.load(Ordering::Relaxed)); | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -726,12 +726,12 @@ mod test { | |||||||
|     fn test_rollback_hook() -> Result<()> { |     fn test_rollback_hook() -> Result<()> { | ||||||
|         let db = Connection::open_in_memory()?; |         let db = Connection::open_in_memory()?; | ||||||
|  |  | ||||||
|         let mut called = false; |         static CALLED: AtomicBool = AtomicBool::new(false); | ||||||
|         db.rollback_hook(Some(|| { |         db.rollback_hook(Some(|| { | ||||||
|             called = true; |             CALLED.store(true, Ordering::Relaxed); | ||||||
|         })); |         })); | ||||||
|         db.execute_batch("BEGIN; CREATE TABLE foo (t TEXT); ROLLBACK;")?; |         db.execute_batch("BEGIN; CREATE TABLE foo (t TEXT); ROLLBACK;")?; | ||||||
|         assert!(called); |         assert!(CALLED.load(Ordering::Relaxed)); | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -739,17 +739,17 @@ mod test { | |||||||
|     fn test_update_hook() -> Result<()> { |     fn test_update_hook() -> Result<()> { | ||||||
|         let db = Connection::open_in_memory()?; |         let db = Connection::open_in_memory()?; | ||||||
|  |  | ||||||
|         let mut called = false; |         static CALLED: AtomicBool = AtomicBool::new(false); | ||||||
|         db.update_hook(Some(|action, db: &str, tbl: &str, row_id| { |         db.update_hook(Some(|action, db: &str, tbl: &str, row_id| { | ||||||
|             assert_eq!(Action::SQLITE_INSERT, action); |             assert_eq!(Action::SQLITE_INSERT, action); | ||||||
|             assert_eq!("main", db); |             assert_eq!("main", db); | ||||||
|             assert_eq!("foo", tbl); |             assert_eq!("foo", tbl); | ||||||
|             assert_eq!(1, row_id); |             assert_eq!(1, row_id); | ||||||
|             called = true; |             CALLED.store(true, Ordering::Relaxed); | ||||||
|         })); |         })); | ||||||
|         db.execute_batch("CREATE TABLE foo (t TEXT)")?; |         db.execute_batch("CREATE TABLE foo (t TEXT)")?; | ||||||
|         db.execute_batch("INSERT INTO foo VALUES ('lisa')")?; |         db.execute_batch("INSERT INTO foo VALUES ('lisa')")?; | ||||||
|         assert!(called); |         assert!(CALLED.load(Ordering::Relaxed)); | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/lib.rs
									
									
									
									
									
								
							| @@ -159,9 +159,11 @@ pub const NO_PARAMS: &[&dyn ToSql] = &[]; | |||||||
| /// } | /// } | ||||||
| /// | /// | ||||||
| /// fn add_person(conn: &Connection, person: &Person) -> Result<()> { | /// fn add_person(conn: &Connection, person: &Person) -> Result<()> { | ||||||
| ///     conn.execute("INSERT INTO person (name, age_in_years, data) | ///     conn.execute( | ||||||
|  | ///         "INSERT INTO person (name, age_in_years, data) | ||||||
| ///                   VALUES (?1, ?2, ?3)", | ///                   VALUES (?1, ?2, ?3)", | ||||||
| ///                  params![person.name, person.age_in_years, person.data])?; | ///         params![person.name, person.age_in_years, person.data], | ||||||
|  | ///     )?; | ||||||
| ///     Ok(()) | ///     Ok(()) | ||||||
| /// } | /// } | ||||||
| /// ``` | /// ``` | ||||||
| @@ -197,7 +199,7 @@ macro_rules! params { | |||||||
| ///             ":name": person.name, | ///             ":name": person.name, | ||||||
| ///             ":age": person.age_in_years, | ///             ":age": person.age_in_years, | ||||||
| ///             ":data": person.data, | ///             ":data": person.data, | ||||||
| ///         } | ///         }, | ||||||
| ///     )?; | ///     )?; | ||||||
| ///     Ok(()) | ///     Ok(()) | ||||||
| /// } | /// } | ||||||
| @@ -462,7 +464,8 @@ impl Connection { | |||||||
|     /// ```rust,no_run |     /// ```rust,no_run | ||||||
|     /// # use rusqlite::{Connection, Result}; |     /// # use rusqlite::{Connection, Result}; | ||||||
|     /// fn create_tables(conn: &Connection) -> Result<()> { |     /// fn create_tables(conn: &Connection) -> Result<()> { | ||||||
|     ///     conn.execute_batch("BEGIN; |     ///     conn.execute_batch( | ||||||
|  |     ///         "BEGIN; | ||||||
|     ///          CREATE TABLE foo(x INTEGER); |     ///          CREATE TABLE foo(x INTEGER); | ||||||
|     ///          CREATE TABLE bar(y TEXT); |     ///          CREATE TABLE bar(y TEXT); | ||||||
|     ///          COMMIT;", |     ///          COMMIT;", | ||||||
| @@ -515,7 +518,10 @@ impl Connection { | |||||||
|     /// ```rust,no_run |     /// ```rust,no_run | ||||||
|     /// # use rusqlite::{params, Connection}; |     /// # use rusqlite::{params, Connection}; | ||||||
|     /// fn update_rows(conn: &Connection) { |     /// fn update_rows(conn: &Connection) { | ||||||
|     ///     match conn.execute("UPDATE foo SET bar = 'baz' WHERE qux = ?1 AND quux = ?2", params![1i32, 1.5f64]) { |     ///     match conn.execute( | ||||||
|  |     ///         "UPDATE foo SET bar = 'baz' WHERE qux = ?1 AND quux = ?2", | ||||||
|  |     ///         params![1i32, 1.5f64], | ||||||
|  |     ///     ) { | ||||||
|     ///         Ok(updated) => println!("{} rows were updated", updated), |     ///         Ok(updated) => println!("{} rows were updated", updated), | ||||||
|     ///         Err(err) => println!("update failed: {}", err), |     ///         Err(err) => println!("update failed: {}", err), | ||||||
|     ///     } |     ///     } | ||||||
|   | |||||||
| @@ -251,7 +251,7 @@ impl_for_array_ref!( | |||||||
| /// ## Basic usage | /// ## Basic usage | ||||||
| /// | /// | ||||||
| /// ```rust,no_run | /// ```rust,no_run | ||||||
| /// use rusqlite::{Connection, Result, params_from_iter}; | /// use rusqlite::{params_from_iter, Connection, Result}; | ||||||
| /// use std::collections::BTreeSet; | /// use std::collections::BTreeSet; | ||||||
| /// | /// | ||||||
| /// fn query(conn: &Connection, ids: &BTreeSet<String>) -> Result<()> { | /// fn query(conn: &Connection, ids: &BTreeSet<String>) -> Result<()> { | ||||||
|   | |||||||
| @@ -346,13 +346,12 @@ impl Statement<'_> { | |||||||
|     /// |     /// | ||||||
|     /// fn name_to_person(name: String) -> Result<Person> { |     /// fn name_to_person(name: String) -> Result<Person> { | ||||||
|     ///     // ... check for valid name |     ///     // ... check for valid name | ||||||
|     ///     Ok(Person { name: name }) |     ///     Ok(Person { name }) | ||||||
|     /// } |     /// } | ||||||
|     /// |     /// | ||||||
|     /// fn get_names(conn: &Connection) -> Result<Vec<Person>> { |     /// fn get_names(conn: &Connection) -> Result<Vec<Person>> { | ||||||
|     ///     let mut stmt = conn.prepare("SELECT name FROM people WHERE id = :id")?; |     ///     let mut stmt = conn.prepare("SELECT name FROM people WHERE id = :id")?; | ||||||
|     ///     let rows = |     ///     let rows = stmt.query_and_then(&[(":id", "one")], |row| name_to_person(row.get(0)?))?; | ||||||
|     ///         stmt.query_and_then(&[(":id", "one")], |row| name_to_person(row.get(0)?))?; |  | ||||||
|     /// |     /// | ||||||
|     ///     let mut persons = Vec::new(); |     ///     let mut persons = Vec::new(); | ||||||
|     ///     for person_result in rows { |     ///     for person_result in rows { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user