mirror of
				https://github.com/isar/rusqlite.git
				synced 2025-10-31 05:48:56 +08:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/master' into sub_type
# Conflicts: # src/functions.rs
This commit is contained in:
		| @@ -235,7 +235,7 @@ impl Connection { | ||||
|                 table.as_ptr(), | ||||
|                 column.as_ptr(), | ||||
|                 row_id, | ||||
|                 if read_only { 0 } else { 1 }, | ||||
|                 !read_only as std::os::raw::c_int, | ||||
|                 &mut blob, | ||||
|             ) | ||||
|         }; | ||||
| @@ -473,14 +473,14 @@ mod test { | ||||
|         assert_eq!(&bytes, b"Clob5"); | ||||
|  | ||||
|         // should not be able to seek negative or past end | ||||
|         assert!(blob.seek(SeekFrom::Current(-20)).is_err()); | ||||
|         assert!(blob.seek(SeekFrom::End(0)).is_ok()); | ||||
|         assert!(blob.seek(SeekFrom::Current(1)).is_err()); | ||||
|         blob.seek(SeekFrom::Current(-20)).unwrap_err(); | ||||
|         blob.seek(SeekFrom::End(0)).unwrap(); | ||||
|         blob.seek(SeekFrom::Current(1)).unwrap_err(); | ||||
|  | ||||
|         // write_all should detect when we return Ok(0) because there is no space left, | ||||
|         // and return a write error | ||||
|         blob.reopen(rowid)?; | ||||
|         assert!(blob.write_all(b"0123456789x").is_err()); | ||||
|         blob.write_all(b"0123456789x").unwrap_err(); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
| @@ -519,7 +519,7 @@ mod test { | ||||
|             // trying to write too much and then flush should fail | ||||
|             assert_eq!(8, writer.write(b"01234567").unwrap()); | ||||
|             assert_eq!(8, writer.write(b"01234567").unwrap()); | ||||
|             assert!(writer.flush().is_err()); | ||||
|             writer.flush().unwrap_err(); | ||||
|         } | ||||
|  | ||||
|         { | ||||
| @@ -536,7 +536,7 @@ mod test { | ||||
|  | ||||
|             // trying to write_all too much should fail | ||||
|             writer.write_all(b"aaaaaaaaaabbbbb").unwrap(); | ||||
|             assert!(writer.flush().is_err()); | ||||
|             writer.flush().unwrap_err(); | ||||
|         } | ||||
|  | ||||
|         { | ||||
|   | ||||
| @@ -214,7 +214,7 @@ mod test { | ||||
|         let mut s = [0u8; 10]; | ||||
|         blob.read_at_exact(&mut s, 0).unwrap(); | ||||
|         assert_eq!(&s, &one2ten, "write should go through"); | ||||
|         assert!(blob.read_at_exact(&mut s, 1).is_err()); | ||||
|         blob.read_at_exact(&mut s, 1).unwrap_err(); | ||||
|  | ||||
|         blob.read_at_exact(&mut s, 0).unwrap(); | ||||
|         assert_eq!(&s, &one2ten, "should be unchanged"); | ||||
| @@ -225,13 +225,13 @@ mod test { | ||||
|  | ||||
|         blob.read_at_exact(&mut fives, 5).unwrap(); | ||||
|         assert_eq!(&fives, &[6u8, 7, 8, 9, 10]); | ||||
|         assert!(blob.read_at_exact(&mut fives, 7).is_err()); | ||||
|         assert!(blob.read_at_exact(&mut fives, 12).is_err()); | ||||
|         assert!(blob.read_at_exact(&mut fives, 10).is_err()); | ||||
|         assert!(blob.read_at_exact(&mut fives, i32::MAX as usize).is_err()); | ||||
|         assert!(blob | ||||
|             .read_at_exact(&mut fives, i32::MAX as usize + 1) | ||||
|             .is_err()); | ||||
|         blob.read_at_exact(&mut fives, 7).unwrap_err(); | ||||
|         blob.read_at_exact(&mut fives, 12).unwrap_err(); | ||||
|         blob.read_at_exact(&mut fives, 10).unwrap_err(); | ||||
|         blob.read_at_exact(&mut fives, i32::MAX as usize) | ||||
|             .unwrap_err(); | ||||
|         blob.read_at_exact(&mut fives, i32::MAX as usize + 1) | ||||
|             .unwrap_err(); | ||||
|  | ||||
|         // zero length writes are fine if in bounds | ||||
|         blob.read_at_exact(&mut [], 10).unwrap(); | ||||
| @@ -242,13 +242,11 @@ mod test { | ||||
|         blob.read_at_exact(&mut s, 0).unwrap(); | ||||
|         assert_eq!(&s, &[1u8, 2, 3, 4, 5, 16, 17, 18, 19, 20]); | ||||
|  | ||||
|         assert!(blob.write_at(&[100, 99, 98, 97, 96], 6).is_err()); | ||||
|         assert!(blob | ||||
|             .write_at(&[100, 99, 98, 97, 96], i32::MAX as usize) | ||||
|             .is_err()); | ||||
|         assert!(blob | ||||
|             .write_at(&[100, 99, 98, 97, 96], i32::MAX as usize + 1) | ||||
|             .is_err()); | ||||
|         blob.write_at(&[100, 99, 98, 97, 96], 6).unwrap_err(); | ||||
|         blob.write_at(&[100, 99, 98, 97, 96], i32::MAX as usize) | ||||
|             .unwrap_err(); | ||||
|         blob.write_at(&[100, 99, 98, 97, 96], i32::MAX as usize + 1) | ||||
|             .unwrap_err(); | ||||
|  | ||||
|         blob.read_at_exact(&mut s, 0).unwrap(); | ||||
|         assert_eq!(&s, &[1u8, 2, 3, 4, 5, 16, 17, 18, 19, 20]); | ||||
| @@ -265,7 +263,7 @@ mod test { | ||||
|             blob.raw_read_at_exact(&mut empty, 0).unwrap().as_ptr(), | ||||
|             empty.as_ptr().cast(), | ||||
|         )); | ||||
|         assert!(blob.raw_read_at_exact(&mut s2, 5).is_err()); | ||||
|         blob.raw_read_at_exact(&mut s2, 5).unwrap_err(); | ||||
|  | ||||
|         let end_pos = blob.seek(std::io::SeekFrom::Current(0)).unwrap(); | ||||
|         assert_eq!(end_pos, 1); | ||||
|   | ||||
| @@ -58,11 +58,7 @@ impl Connection { | ||||
|     pub fn busy_handler(&self, callback: Option<fn(i32) -> bool>) -> Result<()> { | ||||
|         unsafe extern "C" fn busy_handler_callback(p_arg: *mut c_void, count: c_int) -> c_int { | ||||
|             let handler_fn: fn(i32) -> bool = mem::transmute(p_arg); | ||||
|             if let Ok(true) = catch_unwind(|| handler_fn(count)) { | ||||
|                 1 | ||||
|             } else { | ||||
|                 0 | ||||
|             } | ||||
|             c_int::from(catch_unwind(|| handler_fn(count)).unwrap_or_default()) | ||||
|         } | ||||
|         let c = self.db.borrow_mut(); | ||||
|         let r = match callback { | ||||
|   | ||||
| @@ -33,7 +33,7 @@ impl Statement<'_> { | ||||
|     /// calling this method. | ||||
|     pub fn column_names(&self) -> Vec<&str> { | ||||
|         let n = self.column_count(); | ||||
|         let mut cols = Vec::with_capacity(n as usize); | ||||
|         let mut cols = Vec::with_capacity(n); | ||||
|         for i in 0..n { | ||||
|             let s = self.column_name_unwrap(i); | ||||
|             cols.push(s); | ||||
| @@ -95,6 +95,7 @@ impl Statement<'_> { | ||||
|     pub fn column_name(&self, col: usize) -> Result<&str> { | ||||
|         self.stmt | ||||
|             .column_name(col) | ||||
|             // clippy::or_fun_call (nightly) vs clippy::unnecessary-lazy-evaluations (stable) | ||||
|             .ok_or(Error::InvalidColumnIndex(col)) | ||||
|             .map(|slice| { | ||||
|                 str::from_utf8(slice.to_bytes()).expect("Invalid UTF-8 sequence in column name") | ||||
| @@ -137,7 +138,7 @@ impl Statement<'_> { | ||||
|     #[cfg_attr(docsrs, doc(cfg(feature = "column_decltype")))] | ||||
|     pub fn columns(&self) -> Vec<Column> { | ||||
|         let n = self.column_count(); | ||||
|         let mut cols = Vec::with_capacity(n as usize); | ||||
|         let mut cols = Vec::with_capacity(n); | ||||
|         for i in 0..n { | ||||
|             let name = self.column_name_unwrap(i); | ||||
|             let slice = self.stmt.column_decltype(i); | ||||
|   | ||||
| @@ -16,12 +16,12 @@ pub enum DbConfig { | ||||
|     //SQLITE_DBCONFIG_MAINDBNAME = 1000, /* const char* */ | ||||
|     //SQLITE_DBCONFIG_LOOKASIDE = 1001,  /* void* int int */ | ||||
|     /// Enable or disable the enforcement of foreign key constraints. | ||||
|     SQLITE_DBCONFIG_ENABLE_FKEY = 1002, | ||||
|     SQLITE_DBCONFIG_ENABLE_FKEY = ffi::SQLITE_DBCONFIG_ENABLE_FKEY, | ||||
|     /// Enable or disable triggers. | ||||
|     SQLITE_DBCONFIG_ENABLE_TRIGGER = 1003, | ||||
|     SQLITE_DBCONFIG_ENABLE_TRIGGER = ffi::SQLITE_DBCONFIG_ENABLE_TRIGGER, | ||||
|     /// Enable or disable the fts3_tokenizer() function which is part of the | ||||
|     /// FTS3 full-text search engine extension. | ||||
|     SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER = 1004, // 3.12.0 | ||||
|     SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER = ffi::SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, // 3.12.0 | ||||
|     //SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION = 1005, | ||||
|     /// In WAL mode, enable or disable the checkpoint operation before closing | ||||
|     /// the connection. | ||||
| @@ -115,7 +115,7 @@ impl Connection { | ||||
|             check(ffi::sqlite3_db_config( | ||||
|                 c.db(), | ||||
|                 config as c_int, | ||||
|                 if new_val { 1 } else { 0 }, | ||||
|                 new_val as c_int, | ||||
|                 &mut val, | ||||
|             ))?; | ||||
|             Ok(val != 0) | ||||
|   | ||||
| @@ -43,7 +43,7 @@ pub(super) unsafe fn set_result(ctx: *mut sqlite3_context, result: &ToSqlOutput< | ||||
|         ValueRef::Real(r) => ffi::sqlite3_result_double(ctx, r), | ||||
|         ValueRef::Text(s) => { | ||||
|             let length = s.len(); | ||||
|             if length > c_int::max_value() as usize { | ||||
|             if length > c_int::MAX as usize { | ||||
|                 ffi::sqlite3_result_error_toobig(ctx); | ||||
|             } else { | ||||
|                 let (c_str, len, destructor) = match str_for_sqlite(s) { | ||||
| @@ -57,7 +57,7 @@ pub(super) unsafe fn set_result(ctx: *mut sqlite3_context, result: &ToSqlOutput< | ||||
|         } | ||||
|         ValueRef::Blob(b) => { | ||||
|             let length = b.len(); | ||||
|             if length > c_int::max_value() as usize { | ||||
|             if length > c_int::MAX as usize { | ||||
|                 ffi::sqlite3_result_error_toobig(ctx); | ||||
|             } else if length == 0 { | ||||
|                 ffi::sqlite3_result_zeroblob(ctx, 0); | ||||
|   | ||||
							
								
								
									
										36
									
								
								src/error.rs
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								src/error.rs
									
									
									
									
									
								
							| @@ -34,7 +34,7 @@ pub enum Error { | ||||
|  | ||||
|     /// Error converting a string to a C-compatible string because it contained | ||||
|     /// an embedded nul. | ||||
|     NulError(::std::ffi::NulError), | ||||
|     NulError(std::ffi::NulError), | ||||
|  | ||||
|     /// Error when using SQL named parameters and passing a parameter name not | ||||
|     /// present in the SQL. | ||||
| @@ -212,14 +212,14 @@ impl From<str::Utf8Error> for Error { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<::std::ffi::NulError> for Error { | ||||
| impl From<std::ffi::NulError> for Error { | ||||
|     #[cold] | ||||
|     fn from(err: ::std::ffi::NulError) -> Error { | ||||
|     fn from(err: std::ffi::NulError) -> Error { | ||||
|         Error::NulError(err) | ||||
|     } | ||||
| } | ||||
|  | ||||
| const UNKNOWN_COLUMN: usize = std::usize::MAX; | ||||
| const UNKNOWN_COLUMN: usize = usize::MAX; | ||||
|  | ||||
| /// The conversion isn't precise, but it's convenient to have it | ||||
| /// to allow use of `get_raw(…).as_…()?` in callbacks that take `Error`. | ||||
| @@ -245,7 +245,7 @@ impl fmt::Display for Error { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||
|         match *self { | ||||
|             Error::SqliteFailure(ref err, None) => err.fmt(f), | ||||
|             Error::SqliteFailure(_, Some(ref s)) => write!(f, "{}", s), | ||||
|             Error::SqliteFailure(_, Some(ref s)) => write!(f, "{s}"), | ||||
|             Error::SqliteSingleThreadedMode => write!( | ||||
|                 f, | ||||
|                 "SQLite was compiled or configured for single-threaded use only" | ||||
| @@ -263,21 +263,21 @@ impl fmt::Display for Error { | ||||
|             } | ||||
|             Error::IntegralValueOutOfRange(col, val) => { | ||||
|                 if col != UNKNOWN_COLUMN { | ||||
|                     write!(f, "Integer {} out of range at index {}", val, col) | ||||
|                     write!(f, "Integer {val} out of range at index {col}") | ||||
|                 } else { | ||||
|                     write!(f, "Integer {} out of range", val) | ||||
|                     write!(f, "Integer {val} out of range") | ||||
|                 } | ||||
|             } | ||||
|             Error::Utf8Error(ref err) => err.fmt(f), | ||||
|             Error::NulError(ref err) => err.fmt(f), | ||||
|             Error::InvalidParameterName(ref name) => write!(f, "Invalid parameter name: {}", name), | ||||
|             Error::InvalidParameterName(ref name) => write!(f, "Invalid parameter name: {name}"), | ||||
|             Error::InvalidPath(ref p) => write!(f, "Invalid path: {}", p.to_string_lossy()), | ||||
|             Error::ExecuteReturnedResults => { | ||||
|                 write!(f, "Execute returned results - did you mean to call query?") | ||||
|             } | ||||
|             Error::QueryReturnedNoRows => write!(f, "Query returned no rows"), | ||||
|             Error::InvalidColumnIndex(i) => write!(f, "Invalid column index: {}", i), | ||||
|             Error::InvalidColumnName(ref name) => write!(f, "Invalid column name: {}", name), | ||||
|             Error::InvalidColumnIndex(i) => write!(f, "Invalid column index: {i}"), | ||||
|             Error::InvalidColumnName(ref name) => write!(f, "Invalid column name: {name}"), | ||||
|             Error::InvalidColumnType(i, ref name, ref t) => write!( | ||||
|                 f, | ||||
|                 "Invalid column type {} at index: {}, name: {}", | ||||
| @@ -288,22 +288,22 @@ impl fmt::Display for Error { | ||||
|                 "Wrong number of parameters passed to query. Got {}, needed {}", | ||||
|                 i1, n1 | ||||
|             ), | ||||
|             Error::StatementChangedRows(i) => write!(f, "Query changed {} rows", i), | ||||
|             Error::StatementChangedRows(i) => write!(f, "Query changed {i} rows"), | ||||
|  | ||||
|             #[cfg(feature = "functions")] | ||||
|             Error::InvalidFunctionParameterType(i, ref t) => { | ||||
|                 write!(f, "Invalid function parameter type {} at index {}", t, i) | ||||
|                 write!(f, "Invalid function parameter type {t} at index {i}") | ||||
|             } | ||||
|             #[cfg(feature = "vtab")] | ||||
|             Error::InvalidFilterParameterType(i, ref t) => { | ||||
|                 write!(f, "Invalid filter parameter type {} at index {}", t, i) | ||||
|                 write!(f, "Invalid filter parameter type {t} at index {i}") | ||||
|             } | ||||
|             #[cfg(feature = "functions")] | ||||
|             Error::UserFunctionError(ref err) => err.fmt(f), | ||||
|             Error::ToSqlConversionFailure(ref err) => err.fmt(f), | ||||
|             Error::InvalidQuery => write!(f, "Query is not read-only"), | ||||
|             #[cfg(feature = "vtab")] | ||||
|             Error::ModuleError(ref desc) => write!(f, "{}", desc), | ||||
|             Error::ModuleError(ref desc) => write!(f, "{desc}"), | ||||
|             #[cfg(feature = "functions")] | ||||
|             Error::UnwindingPanic => write!(f, "unwinding panic"), | ||||
|             #[cfg(feature = "functions")] | ||||
| @@ -317,7 +317,7 @@ impl fmt::Display for Error { | ||||
|                 offset, | ||||
|                 ref sql, | ||||
|                 .. | ||||
|             } => write!(f, "{} in {} at offset {}", msg, sql, offset), | ||||
|             } => write!(f, "{msg} in {sql} at offset {offset}"), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -408,13 +408,13 @@ pub unsafe fn error_from_handle(db: *mut ffi::sqlite3, code: c_int) -> Error { | ||||
| } | ||||
|  | ||||
| #[cold] | ||||
| #[cfg(not(all(feature = "modern_sqlite", not(feature = "bundled-sqlcipher"))))] // SQLite >= 3.38.0 | ||||
| #[cfg(not(feature = "modern_sqlite"))] // SQLite >= 3.38.0 | ||||
| pub unsafe fn error_with_offset(db: *mut ffi::sqlite3, code: c_int, _sql: &str) -> Error { | ||||
|     error_from_handle(db, code) | ||||
| } | ||||
|  | ||||
| #[cold] | ||||
| #[cfg(all(feature = "modern_sqlite", not(feature = "bundled-sqlcipher")))] // SQLite >= 3.38.0 | ||||
| #[cfg(feature = "modern_sqlite")] // SQLite >= 3.38.0 | ||||
| pub unsafe fn error_with_offset(db: *mut ffi::sqlite3, code: c_int, sql: &str) -> Error { | ||||
|     if db.is_null() { | ||||
|         error_from_sqlite_code(code, None) | ||||
| @@ -438,7 +438,7 @@ pub unsafe fn error_with_offset(db: *mut ffi::sqlite3, code: c_int, sql: &str) - | ||||
|  | ||||
| pub fn check(code: c_int) -> Result<()> { | ||||
|     if code != crate::ffi::SQLITE_OK { | ||||
|         Err(crate::error::error_from_sqlite_code(code, None)) | ||||
|         Err(error_from_sqlite_code(code, None)) | ||||
|     } else { | ||||
|         Ok(()) | ||||
|     } | ||||
|   | ||||
| @@ -75,14 +75,9 @@ unsafe fn report_error(ctx: *mut sqlite3_context, err: &Error) { | ||||
|     // an explicit feature check for that, and this doesn't really warrant one. | ||||
|     // We'll use the extended code if we're on the bundled version (since it's | ||||
|     // at least 3.17.0) and the normal constraint error code if not. | ||||
|     #[cfg(feature = "modern_sqlite")] | ||||
|     fn constraint_error_code() -> i32 { | ||||
|         ffi::SQLITE_CONSTRAINT_FUNCTION | ||||
|     } | ||||
|     #[cfg(not(feature = "modern_sqlite"))] | ||||
|     fn constraint_error_code() -> i32 { | ||||
|         ffi::SQLITE_CONSTRAINT | ||||
|     } | ||||
|  | ||||
|     if let Error::SqliteFailure(ref err, ref s) = *err { | ||||
|         ffi::sqlite3_result_error_code(ctx, err.extended_code); | ||||
| @@ -168,8 +163,6 @@ impl Context<'_> { | ||||
|     /// | ||||
|     /// Will panic if `idx` is greater than or equal to | ||||
|     /// [`self.len()`](Context::len). | ||||
|     #[cfg(feature = "modern_sqlite")] // 3.9.0 | ||||
|     #[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))] | ||||
|     pub fn get_subtype(&self, idx: usize) -> std::os::raw::c_uint { | ||||
|         let arg = self.args[idx]; | ||||
|         unsafe { ffi::sqlite3_value_subtype(arg) } | ||||
| @@ -639,7 +632,7 @@ unsafe extern "C" fn call_boxed_step<A, D, T>( | ||||
|     D: Aggregate<A, T>, | ||||
|     T: ToSql, | ||||
| { | ||||
|     let pac = if let Some(pac) = aggregate_context(ctx, ::std::mem::size_of::<*mut A>()) { | ||||
|     let pac = if let Some(pac) = aggregate_context(ctx, std::mem::size_of::<*mut A>()) { | ||||
|         pac | ||||
|     } else { | ||||
|         ffi::sqlite3_result_error_nomem(ctx); | ||||
| @@ -686,7 +679,7 @@ unsafe extern "C" fn call_boxed_inverse<A, W, T>( | ||||
|     W: WindowAggregate<A, T>, | ||||
|     T: ToSql, | ||||
| { | ||||
|     let pac = if let Some(pac) = aggregate_context(ctx, ::std::mem::size_of::<*mut A>()) { | ||||
|     let pac = if let Some(pac) = aggregate_context(ctx, std::mem::size_of::<*mut A>()) { | ||||
|         pac | ||||
|     } else { | ||||
|         ffi::sqlite3_result_error_nomem(ctx); | ||||
| @@ -821,7 +814,6 @@ where | ||||
| #[cfg(test)] | ||||
| mod test { | ||||
|     use regex::Regex; | ||||
|     use std::f64::EPSILON; | ||||
|     use std::os::raw::c_double; | ||||
|  | ||||
|     #[cfg(feature = "window")] | ||||
| @@ -846,7 +838,7 @@ mod test { | ||||
|         )?; | ||||
|         let result: Result<f64> = db.query_row("SELECT half(6)", [], |r| r.get(0)); | ||||
|  | ||||
|         assert!((3f64 - result?).abs() < EPSILON); | ||||
|         assert!((3f64 - result?).abs() < f64::EPSILON); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
| @@ -860,11 +852,11 @@ mod test { | ||||
|             half, | ||||
|         )?; | ||||
|         let result: Result<f64> = db.query_row("SELECT half(6)", [], |r| r.get(0)); | ||||
|         assert!((3f64 - result?).abs() < EPSILON); | ||||
|         assert!((3f64 - result?).abs() < f64::EPSILON); | ||||
|  | ||||
|         db.remove_function("half", 1)?; | ||||
|         let result: Result<f64> = db.query_row("SELECT half(6)", [], |r| r.get(0)); | ||||
|         assert!(result.is_err()); | ||||
|         result.unwrap_err(); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|   | ||||
							
								
								
									
										26
									
								
								src/hooks.rs
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								src/hooks.rs
									
									
									
									
									
								
							| @@ -10,7 +10,7 @@ use crate::ffi; | ||||
| use crate::{Connection, InnerConnection}; | ||||
|  | ||||
| /// Action Codes | ||||
| #[derive(Clone, Copy, Debug, PartialEq)] | ||||
| #[derive(Clone, Copy, Debug, Eq, PartialEq)] | ||||
| #[repr(i32)] | ||||
| #[non_exhaustive] | ||||
| #[allow(clippy::upper_case_acronyms)] | ||||
| @@ -37,10 +37,10 @@ impl From<i32> for Action { | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// The context recieved by an authorizer hook. | ||||
| /// The context received by an authorizer hook. | ||||
| /// | ||||
| /// See <https://sqlite.org/c3ref/set_authorizer.html> for more info. | ||||
| #[derive(Clone, Copy, Debug, PartialEq)] | ||||
| #[derive(Clone, Copy, Debug, Eq, PartialEq)] | ||||
| pub struct AuthContext<'c> { | ||||
|     /// The action to be authorized. | ||||
|     pub action: AuthAction<'c>, | ||||
| @@ -57,7 +57,7 @@ pub struct AuthContext<'c> { | ||||
| /// preparation. | ||||
| /// | ||||
| /// See <https://sqlite.org/c3ref/c_alter_table.html> for more info. | ||||
| #[derive(Clone, Copy, Debug, PartialEq)] | ||||
| #[derive(Clone, Copy, Debug, Eq, PartialEq)] | ||||
| #[non_exhaustive] | ||||
| #[allow(missing_docs)] | ||||
| pub enum AuthAction<'c> { | ||||
| @@ -181,7 +181,6 @@ pub enum AuthAction<'c> { | ||||
|         operation: TransactionOperation, | ||||
|         savepoint_name: &'c str, | ||||
|     }, | ||||
|     #[cfg(feature = "modern_sqlite")] | ||||
|     Recursive, | ||||
| } | ||||
|  | ||||
| @@ -285,7 +284,6 @@ impl<'c> AuthAction<'c> { | ||||
|                 operation: TransactionOperation::from_str(operation_str), | ||||
|                 savepoint_name, | ||||
|             }, | ||||
|             #[cfg(feature = "modern_sqlite")] // 3.8.3 | ||||
|             (ffi::SQLITE_RECURSIVE, ..) => Self::Recursive, | ||||
|             (code, arg1, arg2) => Self::Unknown { code, arg1, arg2 }, | ||||
|         } | ||||
| @@ -296,7 +294,7 @@ pub(crate) type BoxedAuthorizer = | ||||
|     Box<dyn for<'c> FnMut(AuthContext<'c>) -> Authorization + Send + 'static>; | ||||
|  | ||||
| /// A transaction operation. | ||||
| #[derive(Clone, Copy, Debug, PartialEq)] | ||||
| #[derive(Clone, Copy, Debug, Eq, PartialEq)] | ||||
| #[non_exhaustive] | ||||
| #[allow(missing_docs)] | ||||
| pub enum TransactionOperation { | ||||
| @@ -318,7 +316,7 @@ impl TransactionOperation { | ||||
| } | ||||
|  | ||||
| /// [`authorizer`](Connection::authorizer) return code | ||||
| #[derive(Clone, Copy, Debug, PartialEq)] | ||||
| #[derive(Clone, Copy, Debug, Eq, PartialEq)] | ||||
| #[non_exhaustive] | ||||
| pub enum Authorization { | ||||
|     /// Authorize the action. | ||||
| @@ -428,11 +426,7 @@ impl InnerConnection { | ||||
|                 let boxed_hook: *mut F = p_arg.cast::<F>(); | ||||
|                 (*boxed_hook)() | ||||
|             }); | ||||
|             if let Ok(true) = r { | ||||
|                 1 | ||||
|             } else { | ||||
|                 0 | ||||
|             } | ||||
|             c_int::from(r.unwrap_or_default()) | ||||
|         } | ||||
|  | ||||
|         // unlike `sqlite3_create_function_v2`, we cannot specify a `xDestroy` with | ||||
| @@ -570,11 +564,7 @@ impl InnerConnection { | ||||
|                 let boxed_handler: *mut F = p_arg.cast::<F>(); | ||||
|                 (*boxed_handler)() | ||||
|             }); | ||||
|             if let Ok(true) = r { | ||||
|                 1 | ||||
|             } else { | ||||
|                 0 | ||||
|             } | ||||
|             c_int::from(r.unwrap_or_default()) | ||||
|         } | ||||
|  | ||||
|         if let Some(handler) = handler { | ||||
|   | ||||
| @@ -25,11 +25,11 @@ pub struct InnerConnection { | ||||
|     // interrupt would only acquire the lock after the query's completion. | ||||
|     interrupt_lock: Arc<Mutex<*mut ffi::sqlite3>>, | ||||
|     #[cfg(feature = "hooks")] | ||||
|     pub free_commit_hook: Option<unsafe fn(*mut ::std::os::raw::c_void)>, | ||||
|     pub free_commit_hook: Option<unsafe fn(*mut std::os::raw::c_void)>, | ||||
|     #[cfg(feature = "hooks")] | ||||
|     pub free_rollback_hook: Option<unsafe fn(*mut ::std::os::raw::c_void)>, | ||||
|     pub free_rollback_hook: Option<unsafe fn(*mut std::os::raw::c_void)>, | ||||
|     #[cfg(feature = "hooks")] | ||||
|     pub free_update_hook: Option<unsafe fn(*mut ::std::os::raw::c_void)>, | ||||
|     pub free_update_hook: Option<unsafe fn(*mut std::os::raw::c_void)>, | ||||
|     #[cfg(feature = "hooks")] | ||||
|     pub progress_handler: Option<Box<dyn FnMut() -> bool + Send>>, | ||||
|     #[cfg(feature = "hooks")] | ||||
| @@ -105,7 +105,7 @@ impl InnerConnection { | ||||
|                     { | ||||
|                         e = Error::SqliteFailure( | ||||
|                             ffi::Error::new(r), | ||||
|                             Some(format!("{}: {}", msg, c_path.to_string_lossy())), | ||||
|                             Some(format!("{msg}: {}", c_path.to_string_lossy())), | ||||
|                         ); | ||||
|                     } | ||||
|                     ffi::sqlite3_close(db); | ||||
| @@ -208,7 +208,7 @@ impl InnerConnection { | ||||
|             Ok(()) | ||||
|         } else { | ||||
|             let message = super::errmsg_to_string(errmsg); | ||||
|             ffi::sqlite3_free(errmsg.cast::<::std::os::raw::c_void>()); | ||||
|             ffi::sqlite3_free(errmsg.cast::<std::os::raw::c_void>()); | ||||
|             Err(error_from_sqlite_code(r, Some(message))) | ||||
|         } | ||||
|     } | ||||
| @@ -295,7 +295,6 @@ impl InnerConnection { | ||||
|         unsafe { ffi::sqlite3_get_autocommit(self.db()) != 0 } | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "modern_sqlite")] // 3.8.6 | ||||
|     pub fn is_busy(&self) -> bool { | ||||
|         let db = self.db(); | ||||
|         unsafe { | ||||
| @@ -310,7 +309,6 @@ impl InnerConnection { | ||||
|         false | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "modern_sqlite")] // 3.10.0 | ||||
|     pub fn cache_flush(&mut self) -> Result<()> { | ||||
|         crate::error::check(unsafe { ffi::sqlite3_db_cacheflush(self.db()) }) | ||||
|     } | ||||
| @@ -319,7 +317,6 @@ impl InnerConnection { | ||||
|     #[inline] | ||||
|     fn remove_hooks(&mut self) {} | ||||
|  | ||||
|     #[cfg(feature = "modern_sqlite")] // 3.7.11 | ||||
|     pub fn db_readonly(&self, db_name: super::DatabaseName<'_>) -> Result<bool> { | ||||
|         let name = db_name.as_cstring()?; | ||||
|         let r = unsafe { ffi::sqlite3_db_readonly(self.db, name.as_ptr()) }; | ||||
| @@ -328,7 +325,7 @@ impl InnerConnection { | ||||
|             1 => Ok(true), | ||||
|             -1 => Err(Error::SqliteFailure( | ||||
|                 ffi::Error::new(ffi::SQLITE_MISUSE), | ||||
|                 Some(format!("{:?} is not the name of a database", db_name)), | ||||
|                 Some(format!("{db_name:?} is not the name of a database")), | ||||
|             )), | ||||
|             _ => Err(error_from_sqlite_code( | ||||
|                 r, | ||||
| @@ -354,7 +351,7 @@ impl InnerConnection { | ||||
|             2 => Ok(super::transaction::TransactionState::Write), | ||||
|             -1 => Err(Error::SqliteFailure( | ||||
|                 ffi::Error::new(ffi::SQLITE_MISUSE), | ||||
|                 Some(format!("{:?} is not the name of a valid schema", db_name)), | ||||
|                 Some(format!("{db_name:?} is not the name of a valid schema")), | ||||
|             )), | ||||
|             _ => Err(error_from_sqlite_code( | ||||
|                 r, | ||||
| @@ -378,7 +375,7 @@ impl Drop for InnerConnection { | ||||
|  | ||||
|         if let Err(e) = self.close() { | ||||
|             if panicking() { | ||||
|                 eprintln!("Error while closing SQLite connection: {:?}", e); | ||||
|                 eprintln!("Error while closing SQLite connection: {e:?}"); | ||||
|             } else { | ||||
|                 panic!("Error while closing SQLite connection: {:?}", e); | ||||
|             } | ||||
| @@ -400,7 +397,7 @@ fn ensure_safe_sqlite_threading_mode() -> Result<()> { | ||||
|  | ||||
| #[cfg(not(any(target_arch = "wasm32")))] | ||||
| fn ensure_safe_sqlite_threading_mode() -> Result<()> { | ||||
|     // Ensure SQLite was compiled in thredsafe mode. | ||||
|     // Ensure SQLite was compiled in threadsafe mode. | ||||
|     if unsafe { ffi::sqlite3_threadsafe() == 0 } { | ||||
|         return Err(Error::SqliteSingleThreadedMode); | ||||
|     } | ||||
|   | ||||
							
								
								
									
										67
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								src/lib.rs
									
									
									
									
									
								
							| @@ -57,7 +57,6 @@ | ||||
| pub use libsqlite3_sys as ffi; | ||||
|  | ||||
| use std::cell::RefCell; | ||||
| use std::convert; | ||||
| use std::default::Default; | ||||
| use std::ffi::{CStr, CString}; | ||||
| use std::fmt; | ||||
| @@ -272,7 +271,7 @@ fn str_for_sqlite(s: &[u8]) -> Result<(*const c_char, c_int, ffi::sqlite3_destru | ||||
| // Helper to cast to c_int safely, returning the correct error type if the cast | ||||
| // failed. | ||||
| fn len_as_c_int(len: usize) -> Result<c_int> { | ||||
|     if len >= (c_int::max_value() as usize) { | ||||
|     if len >= (c_int::MAX as usize) { | ||||
|         Err(Error::SqliteFailure( | ||||
|             ffi::Error::new(ffi::SQLITE_TOOBIG), | ||||
|             None, | ||||
| @@ -315,15 +314,9 @@ pub const TEMP_DB: DatabaseName<'static> = DatabaseName::Temp; | ||||
|  | ||||
| // 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", | ||||
|     feature = "session", | ||||
|     feature = "modern_sqlite" | ||||
| ))] | ||||
| impl DatabaseName<'_> { | ||||
|     #[inline] | ||||
|     fn as_cstring(&self) -> Result<util::SmallCString> { | ||||
|     fn as_cstring(&self) -> Result<SmallCString> { | ||||
|         use self::DatabaseName::{Attached, Main, Temp}; | ||||
|         match *self { | ||||
|             Main => str_to_cstring("main"), | ||||
| @@ -724,7 +717,7 @@ impl Connection { | ||||
|     where | ||||
|         P: Params, | ||||
|         F: FnOnce(&Row<'_>) -> Result<T, E>, | ||||
|         E: convert::From<Error>, | ||||
|         E: From<Error>, | ||||
|     { | ||||
|         let mut stmt = self.prepare(sql)?; | ||||
|         stmt.check_no_tail()?; | ||||
| @@ -962,22 +955,16 @@ impl Connection { | ||||
|  | ||||
|     /// Determine if all associated prepared statements have been reset. | ||||
|     #[inline] | ||||
|     #[cfg(feature = "modern_sqlite")] // 3.8.6 | ||||
|     #[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))] | ||||
|     pub fn is_busy(&self) -> bool { | ||||
|         self.db.borrow().is_busy() | ||||
|     } | ||||
|  | ||||
|     /// Flush caches to disk mid-transaction | ||||
|     #[cfg(feature = "modern_sqlite")] // 3.10.0 | ||||
|     #[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))] | ||||
|     pub fn cache_flush(&self) -> Result<()> { | ||||
|         self.db.borrow_mut().cache_flush() | ||||
|     } | ||||
|  | ||||
|     /// Determine if a database is read-only | ||||
|     #[cfg(feature = "modern_sqlite")] // 3.7.11 | ||||
|     #[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))] | ||||
|     pub fn is_readonly(&self, db_name: DatabaseName<'_>) -> Result<bool> { | ||||
|         self.db.borrow().db_readonly(db_name) | ||||
|     } | ||||
| @@ -1071,9 +1058,9 @@ bitflags::bitflags! { | ||||
|         /// The database is created if it does not already exist | ||||
|         const SQLITE_OPEN_CREATE = ffi::SQLITE_OPEN_CREATE; | ||||
|         /// The filename can be interpreted as a URI if this flag is set. | ||||
|         const SQLITE_OPEN_URI = 0x0000_0040; | ||||
|         const SQLITE_OPEN_URI = ffi::SQLITE_OPEN_URI; | ||||
|         /// The database will be opened as an in-memory database. | ||||
|         const SQLITE_OPEN_MEMORY = 0x0000_0080; | ||||
|         const SQLITE_OPEN_MEMORY = ffi::SQLITE_OPEN_MEMORY; | ||||
|         /// The new database connection will not use a per-connection mutex (the | ||||
|         /// connection will use the "multi-thread" threading mode, in SQLite | ||||
|         /// parlance). | ||||
| @@ -1177,7 +1164,6 @@ impl InterruptHandle { | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "modern_sqlite")] // 3.7.10 | ||||
| unsafe fn db_filename(db: *mut ffi::sqlite3) -> Option<PathBuf> { | ||||
|     let db_name = DatabaseName::Main.as_cstring().unwrap(); | ||||
|     let db_filename = ffi::sqlite3_db_filename(db, db_name.as_ptr()); | ||||
| @@ -1187,10 +1173,6 @@ unsafe fn db_filename(db: *mut ffi::sqlite3) -> Option<PathBuf> { | ||||
|         CStr::from_ptr(db_filename).to_str().ok().map(PathBuf::from) | ||||
|     } | ||||
| } | ||||
| #[cfg(not(feature = "modern_sqlite"))] | ||||
| unsafe fn db_filename(_: *mut ffi::sqlite3) -> Option<PathBuf> { | ||||
|     None | ||||
| } | ||||
|  | ||||
| #[cfg(doctest)] | ||||
| doc_comment::doctest!("../README.md"); | ||||
| @@ -1278,7 +1260,7 @@ mod test { | ||||
|         } | ||||
|  | ||||
|         let path_string = path.to_str().unwrap(); | ||||
|         let db = Connection::open(&path_string)?; | ||||
|         let db = Connection::open(path_string)?; | ||||
|         let the_answer: Result<i64> = db.query_row("SELECT x FROM foo", [], |r| r.get(0)); | ||||
|  | ||||
|         assert_eq!(42i64, the_answer?); | ||||
| @@ -1287,17 +1269,16 @@ mod test { | ||||
|  | ||||
|     #[test] | ||||
|     fn test_open() { | ||||
|         assert!(Connection::open_in_memory().is_ok()); | ||||
|         Connection::open_in_memory().unwrap(); | ||||
|  | ||||
|         let db = checked_memory_handle(); | ||||
|         assert!(db.close().is_ok()); | ||||
|         db.close().unwrap(); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_open_failure() { | ||||
|         let filename = "no_such_file.db"; | ||||
|         let result = Connection::open_with_flags(filename, OpenFlags::SQLITE_OPEN_READ_ONLY); | ||||
|         assert!(result.is_err()); | ||||
|         let err = result.unwrap_err(); | ||||
|         if let Error::SqliteFailure(e, Some(msg)) = err { | ||||
|             assert_eq!(ErrorCode::CannotOpen, e.code); | ||||
| @@ -1392,7 +1373,7 @@ mod test { | ||||
|             OpenFlags::SQLITE_OPEN_READ_ONLY | OpenFlags::SQLITE_OPEN_READ_WRITE, | ||||
|             OpenFlags::SQLITE_OPEN_READ_ONLY | OpenFlags::SQLITE_OPEN_CREATE, | ||||
|         ] { | ||||
|             assert!(Connection::open_in_memory_with_flags(*bad_flags).is_err()); | ||||
|             Connection::open_in_memory_with_flags(*bad_flags).unwrap_err(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -1410,7 +1391,7 @@ mod test { | ||||
|  | ||||
|         db.execute_batch("UPDATE foo SET x = 3 WHERE x < 3")?; | ||||
|  | ||||
|         assert!(db.execute_batch("INVALID SQL").is_err()); | ||||
|         db.execute_batch("INVALID SQL").unwrap_err(); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
| @@ -1434,8 +1415,9 @@ mod test { | ||||
|     fn test_execute_select() { | ||||
|         let db = checked_memory_handle(); | ||||
|         let err = db.execute("SELECT 1 WHERE 1 < ?", [1i32]).unwrap_err(); | ||||
|         assert!( | ||||
|             err == Error::ExecuteReturnedResults, | ||||
|         assert_eq!( | ||||
|             err, | ||||
|             Error::ExecuteReturnedResults, | ||||
|             "Unexpected error: {}", | ||||
|             err | ||||
|         ); | ||||
| @@ -1572,7 +1554,7 @@ mod test { | ||||
|  | ||||
|         let bad_query_result = db.query_row("NOT A PROPER QUERY; test123", [], |_| Ok(())); | ||||
|  | ||||
|         assert!(bad_query_result.is_err()); | ||||
|         bad_query_result.unwrap_err(); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
| @@ -1596,7 +1578,7 @@ mod test { | ||||
|  | ||||
|         let bad_query_result: Result<i64> = db.query_row("NOT A PROPER QUERY", [], |r| r.get(0)); | ||||
|         let bad_query_result = bad_query_result.optional(); | ||||
|         assert!(bad_query_result.is_err()); | ||||
|         bad_query_result.unwrap_err(); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
| @@ -1634,7 +1616,7 @@ mod test { | ||||
|         db.execute_batch("CREATE TABLE foo(x INTEGER);")?; | ||||
|  | ||||
|         let err = db.prepare("SELECT * FROM does_not_exist").unwrap_err(); | ||||
|         assert!(format!("{}", err).contains("does_not_exist")); | ||||
|         assert!(format!("{err}").contains("does_not_exist")); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
| @@ -1665,7 +1647,6 @@ mod test { | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     #[cfg(feature = "modern_sqlite")] | ||||
|     fn test_is_busy() -> Result<()> { | ||||
|         let db = Connection::open_in_memory()?; | ||||
|         assert!(!db.is_busy()); | ||||
| @@ -1688,7 +1669,7 @@ mod test { | ||||
|         let query = "SELECT 12345"; | ||||
|         let stmt = db.prepare(query)?; | ||||
|  | ||||
|         assert!(format!("{:?}", stmt).contains(query)); | ||||
|         assert!(format!("{stmt:?}").contains(query)); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
| @@ -1696,18 +1677,14 @@ mod test { | ||||
|     fn test_notnull_constraint_error() -> Result<()> { | ||||
|         // extended error codes for constraints were added in SQLite 3.7.16; if we're | ||||
|         // running on our bundled version, we know the extended error code exists. | ||||
|         #[cfg(feature = "modern_sqlite")] | ||||
|         fn check_extended_code(extended_code: c_int) { | ||||
|             assert_eq!(extended_code, ffi::SQLITE_CONSTRAINT_NOTNULL); | ||||
|         } | ||||
|         #[cfg(not(feature = "modern_sqlite"))] | ||||
|         fn check_extended_code(_extended_code: c_int) {} | ||||
|  | ||||
|         let db = Connection::open_in_memory()?; | ||||
|         db.execute_batch("CREATE TABLE foo(x NOT NULL)")?; | ||||
|  | ||||
|         let result = db.execute("INSERT INTO foo (x) VALUES (NULL)", []); | ||||
|         assert!(result.is_err()); | ||||
|  | ||||
|         match result.unwrap_err() { | ||||
|             Error::SqliteFailure(err, _) => { | ||||
| @@ -1726,7 +1703,7 @@ mod test { | ||||
|         let minor = (n % 1_000_000) / 1_000; | ||||
|         let patch = n % 1_000; | ||||
|  | ||||
|         assert!(version().contains(&format!("{}.{}.{}", major, minor, patch))); | ||||
|         assert!(version().contains(&format!("{major}.{minor}.{patch}"))); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
| @@ -1739,7 +1716,7 @@ mod test { | ||||
|         db.create_scalar_function( | ||||
|             "interrupt", | ||||
|             0, | ||||
|             crate::functions::FunctionFlags::default(), | ||||
|             functions::FunctionFlags::default(), | ||||
|             move |_| { | ||||
|                 interrupt_handle.interrupt(); | ||||
|                 Ok((0, None)) | ||||
| @@ -1833,7 +1810,7 @@ mod test { | ||||
|             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { | ||||
|                 match *self { | ||||
|                     CustomError::SomeError => write!(f, "my custom error"), | ||||
|                     CustomError::Sqlite(ref se) => write!(f, "my custom error: {}", se), | ||||
|                     CustomError::Sqlite(ref se) => write!(f, "my custom error: {se}"), | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -2111,17 +2088,15 @@ mod test { | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     #[cfg(feature = "modern_sqlite")] | ||||
|     fn test_cache_flush() -> Result<()> { | ||||
|         let db = Connection::open_in_memory()?; | ||||
|         db.cache_flush() | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     #[cfg(feature = "modern_sqlite")] | ||||
|     pub fn db_readonly() -> Result<()> { | ||||
|         let db = Connection::open_in_memory()?; | ||||
|         assert!(!db.is_readonly(super::MAIN_DB)?); | ||||
|         assert!(!db.is_readonly(MAIN_DB)?); | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -39,10 +39,10 @@ pub enum Limit { | ||||
|     /// The maximum index number of any parameter in an SQL statement. | ||||
|     SQLITE_LIMIT_VARIABLE_NUMBER = ffi::SQLITE_LIMIT_VARIABLE_NUMBER, | ||||
|     /// The maximum depth of recursion for triggers. | ||||
|     SQLITE_LIMIT_TRIGGER_DEPTH = 10, | ||||
|     SQLITE_LIMIT_TRIGGER_DEPTH = ffi::SQLITE_LIMIT_TRIGGER_DEPTH, | ||||
|     /// The maximum number of auxiliary worker threads that a single prepared | ||||
|     /// statement may start. | ||||
|     SQLITE_LIMIT_WORKER_THREADS = 11, | ||||
|     SQLITE_LIMIT_WORKER_THREADS = ffi::SQLITE_LIMIT_WORKER_THREADS, | ||||
| } | ||||
|  | ||||
| impl Connection { | ||||
| @@ -71,55 +71,49 @@ mod test { | ||||
|  | ||||
|     #[test] | ||||
|     fn test_limit_values() { | ||||
|         assert_eq!( | ||||
|             Limit::SQLITE_LIMIT_LENGTH as i32, | ||||
|             ffi::SQLITE_LIMIT_LENGTH as i32, | ||||
|         ); | ||||
|         assert_eq!(Limit::SQLITE_LIMIT_LENGTH as i32, ffi::SQLITE_LIMIT_LENGTH,); | ||||
|         assert_eq!( | ||||
|             Limit::SQLITE_LIMIT_SQL_LENGTH as i32, | ||||
|             ffi::SQLITE_LIMIT_SQL_LENGTH as i32, | ||||
|         ); | ||||
|         assert_eq!( | ||||
|             Limit::SQLITE_LIMIT_COLUMN as i32, | ||||
|             ffi::SQLITE_LIMIT_COLUMN as i32, | ||||
|             ffi::SQLITE_LIMIT_SQL_LENGTH, | ||||
|         ); | ||||
|         assert_eq!(Limit::SQLITE_LIMIT_COLUMN as i32, ffi::SQLITE_LIMIT_COLUMN,); | ||||
|         assert_eq!( | ||||
|             Limit::SQLITE_LIMIT_EXPR_DEPTH as i32, | ||||
|             ffi::SQLITE_LIMIT_EXPR_DEPTH as i32, | ||||
|             ffi::SQLITE_LIMIT_EXPR_DEPTH, | ||||
|         ); | ||||
|         assert_eq!( | ||||
|             Limit::SQLITE_LIMIT_COMPOUND_SELECT as i32, | ||||
|             ffi::SQLITE_LIMIT_COMPOUND_SELECT as i32, | ||||
|             ffi::SQLITE_LIMIT_COMPOUND_SELECT, | ||||
|         ); | ||||
|         assert_eq!( | ||||
|             Limit::SQLITE_LIMIT_VDBE_OP as i32, | ||||
|             ffi::SQLITE_LIMIT_VDBE_OP as i32, | ||||
|             ffi::SQLITE_LIMIT_VDBE_OP, | ||||
|         ); | ||||
|         assert_eq!( | ||||
|             Limit::SQLITE_LIMIT_FUNCTION_ARG as i32, | ||||
|             ffi::SQLITE_LIMIT_FUNCTION_ARG as i32, | ||||
|             ffi::SQLITE_LIMIT_FUNCTION_ARG, | ||||
|         ); | ||||
|         assert_eq!( | ||||
|             Limit::SQLITE_LIMIT_ATTACHED as i32, | ||||
|             ffi::SQLITE_LIMIT_ATTACHED as i32, | ||||
|             ffi::SQLITE_LIMIT_ATTACHED, | ||||
|         ); | ||||
|         assert_eq!( | ||||
|             Limit::SQLITE_LIMIT_LIKE_PATTERN_LENGTH as i32, | ||||
|             ffi::SQLITE_LIMIT_LIKE_PATTERN_LENGTH as i32, | ||||
|             ffi::SQLITE_LIMIT_LIKE_PATTERN_LENGTH, | ||||
|         ); | ||||
|         assert_eq!( | ||||
|             Limit::SQLITE_LIMIT_VARIABLE_NUMBER as i32, | ||||
|             ffi::SQLITE_LIMIT_VARIABLE_NUMBER as i32, | ||||
|             ffi::SQLITE_LIMIT_VARIABLE_NUMBER, | ||||
|         ); | ||||
|         #[cfg(feature = "bundled")] | ||||
|         assert_eq!( | ||||
|             Limit::SQLITE_LIMIT_TRIGGER_DEPTH as i32, | ||||
|             ffi::SQLITE_LIMIT_TRIGGER_DEPTH as i32, | ||||
|             ffi::SQLITE_LIMIT_TRIGGER_DEPTH, | ||||
|         ); | ||||
|         #[cfg(feature = "bundled")] | ||||
|         assert_eq!( | ||||
|             Limit::SQLITE_LIMIT_WORKER_THREADS as i32, | ||||
|             ffi::SQLITE_LIMIT_WORKER_THREADS as i32, | ||||
|             ffi::SQLITE_LIMIT_WORKER_THREADS, | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -41,7 +41,7 @@ use sealed::Sealed; | ||||
| /// - Using the [`rusqlite::params!`](crate::params!) macro, e.g. | ||||
| ///   `thing.query(rusqlite::params![1, "foo", bar])`. This is mostly useful for | ||||
| ///   heterogeneous lists where the number of parameters greater than 16, or | ||||
| ///   homogenous lists of paramters where the number of parameters exceeds 32. | ||||
| ///   homogenous lists of parameters where the number of parameters exceeds 32. | ||||
| /// | ||||
| /// - For small homogeneous lists of parameters, they can either be passed as: | ||||
| /// | ||||
|   | ||||
| @@ -37,7 +37,7 @@ impl Sql { | ||||
|         } else { | ||||
|             Err(Error::SqliteFailure( | ||||
|                 ffi::Error::new(ffi::SQLITE_MISUSE), | ||||
|                 Some(format!("Invalid keyword \"{}\"", keyword)), | ||||
|                 Some(format!("Invalid keyword \"{keyword}\"")), | ||||
|             )) | ||||
|         } | ||||
|     } | ||||
| @@ -67,14 +67,14 @@ impl Sql { | ||||
|             ToSqlOutput::ZeroBlob(_) => { | ||||
|                 return Err(Error::SqliteFailure( | ||||
|                     ffi::Error::new(ffi::SQLITE_MISUSE), | ||||
|                     Some(format!("Unsupported value \"{:?}\"", value)), | ||||
|                     Some(format!("Unsupported value \"{value:?}\"")), | ||||
|                 )); | ||||
|             } | ||||
|             #[cfg(feature = "array")] | ||||
|             ToSqlOutput::Array(_) => { | ||||
|                 return Err(Error::SqliteFailure( | ||||
|                     ffi::Error::new(ffi::SQLITE_MISUSE), | ||||
|                     Some(format!("Unsupported value \"{:?}\"", value)), | ||||
|                     Some(format!("Unsupported value \"{value:?}\"")), | ||||
|                 )); | ||||
|             } | ||||
|         }; | ||||
| @@ -92,7 +92,7 @@ impl Sql { | ||||
|             _ => { | ||||
|                 return Err(Error::SqliteFailure( | ||||
|                     ffi::Error::new(ffi::SQLITE_MISUSE), | ||||
|                     Some(format!("Unsupported value \"{:?}\"", value)), | ||||
|                     Some(format!("Unsupported value \"{value:?}\"")), | ||||
|                 )); | ||||
|             } | ||||
|         }; | ||||
| @@ -369,7 +369,7 @@ mod test { | ||||
|     fn pragma() -> Result<()> { | ||||
|         let db = Connection::open_in_memory()?; | ||||
|         let mut columns = Vec::new(); | ||||
|         db.pragma(None, "table_info", &"sqlite_master", |row| { | ||||
|         db.pragma(None, "table_info", "sqlite_master", |row| { | ||||
|             let column: String = row.get(1)?; | ||||
|             columns.push(column); | ||||
|             Ok(()) | ||||
| @@ -412,8 +412,8 @@ mod test { | ||||
|             journal_mode, | ||||
|         ); | ||||
|         // Sanity checks to ensure the move to a generic `ToSql` wasn't breaking | ||||
|         let mode = db | ||||
|             .pragma_update_and_check(None, "journal_mode", &"OFF", |row| row.get::<_, String>(0))?; | ||||
|         let mode = | ||||
|             db.pragma_update_and_check(None, "journal_mode", "OFF", |row| row.get::<_, String>(0))?; | ||||
|         assert!(mode == "off" || mode == "memory", "mode: {:?}", mode); | ||||
|  | ||||
|         let param: &dyn crate::ToSql = &"OFF"; | ||||
| @@ -448,7 +448,7 @@ mod test { | ||||
|     #[test] | ||||
|     fn locking_mode() -> Result<()> { | ||||
|         let db = Connection::open_in_memory()?; | ||||
|         let r = db.pragma_update(None, "locking_mode", &"exclusive"); | ||||
|         let r = db.pragma_update(None, "locking_mode", "exclusive"); | ||||
|         if cfg!(feature = "extra_check") { | ||||
|             r.unwrap_err(); | ||||
|         } else { | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| use super::ffi; | ||||
| use super::StatementStatus; | ||||
| use crate::util::ParamIndexCache; | ||||
| #[cfg(feature = "modern_sqlite")] | ||||
| use crate::util::SqliteMallocString; | ||||
| use std::ffi::CStr; | ||||
| use std::os::raw::c_int; | ||||
| @@ -110,7 +109,7 @@ impl RawStatement { | ||||
|     #[cfg(feature = "unlock_notify")] | ||||
|     pub fn step(&self) -> c_int { | ||||
|         use crate::unlock_notify; | ||||
|         let mut db = core::ptr::null_mut::<ffi::sqlite3>(); | ||||
|         let mut db = ptr::null_mut::<ffi::sqlite3>(); | ||||
|         loop { | ||||
|             unsafe { | ||||
|                 let mut rc = ffi::sqlite3_step(self.ptr); | ||||
| @@ -196,14 +195,13 @@ impl RawStatement { | ||||
|     } | ||||
|  | ||||
|     // does not work for PRAGMA | ||||
|     #[cfg(feature = "extra_check")] | ||||
|     #[inline] | ||||
|     #[cfg(all(feature = "extra_check", feature = "modern_sqlite"))] // 3.7.4 | ||||
|     pub fn readonly(&self) -> bool { | ||||
|         unsafe { ffi::sqlite3_stmt_readonly(self.ptr) != 0 } | ||||
|     } | ||||
|  | ||||
|     #[inline] | ||||
|     #[cfg(feature = "modern_sqlite")] // 3.14.0 | ||||
|     pub(crate) fn expanded_sql(&self) -> Option<SqliteMallocString> { | ||||
|         unsafe { SqliteMallocString::from_raw(ffi::sqlite3_expanded_sql(self.ptr)) } | ||||
|     } | ||||
|   | ||||
| @@ -171,7 +171,7 @@ pub struct AndThenRows<'stmt, F> { | ||||
|  | ||||
| impl<T, E, F> Iterator for AndThenRows<'_, F> | ||||
| where | ||||
|     E: convert::From<Error>, | ||||
|     E: From<Error>, | ||||
|     F: FnMut(&Row<'_>) -> Result<T, E>, | ||||
| { | ||||
|     type Item = Result<T, E>; | ||||
| @@ -391,7 +391,7 @@ impl RowIndex for usize { | ||||
| impl RowIndex for &'_ str { | ||||
|     #[inline] | ||||
|     fn idx(&self, stmt: &Statement<'_>) -> Result<usize> { | ||||
|         stmt.column_index(*self) | ||||
|         stmt.column_index(self) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -448,7 +448,7 @@ mod tests { | ||||
|         let val = conn.query_row("SELECT a FROM test", [], |row| <(u32,)>::try_from(row))?; | ||||
|         assert_eq!(val, (42,)); | ||||
|         let fail = conn.query_row("SELECT a FROM test", [], |row| <(u32, u32)>::try_from(row)); | ||||
|         assert!(fail.is_err()); | ||||
|         fail.unwrap_err(); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
| @@ -466,7 +466,7 @@ mod tests { | ||||
|         let fail = conn.query_row("SELECT a, b FROM test", [], |row| { | ||||
|             <(u32, u32, u32)>::try_from(row) | ||||
|         }); | ||||
|         assert!(fail.is_err()); | ||||
|         fail.unwrap_err(); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -19,12 +19,14 @@ use crate::{errmsg_to_string, str_to_cstring, Connection, DatabaseName, Result}; | ||||
|  | ||||
| // https://sqlite.org/session.html | ||||
|  | ||||
| type Filter = Option<Box<dyn Fn(&str) -> bool>>; | ||||
|  | ||||
| /// An instance of this object is a session that can be | ||||
| /// used to record changes to a database. | ||||
| pub struct Session<'conn> { | ||||
|     phantom: PhantomData<&'conn Connection>, | ||||
|     s: *mut ffi::sqlite3_session, | ||||
|     filter: Option<Box<dyn Fn(&str) -> bool>>, | ||||
|     filter: Filter, | ||||
| } | ||||
|  | ||||
| impl Session<'_> { | ||||
| @@ -168,7 +170,7 @@ impl Session<'_> { | ||||
|             if r != ffi::SQLITE_OK { | ||||
|                 let errmsg: *mut c_char = errmsg; | ||||
|                 let message = errmsg_to_string(&*errmsg); | ||||
|                 ffi::sqlite3_free(errmsg as *mut ::std::os::raw::c_void); | ||||
|                 ffi::sqlite3_free(errmsg as *mut c_void); | ||||
|                 return Err(error_from_sqlite_code(r, Some(message))); | ||||
|             } | ||||
|         } | ||||
| @@ -656,7 +658,7 @@ impl Connection { | ||||
| /// See [here](https://sqlite.org/session.html#SQLITE_CHANGESET_CONFLICT) for details. | ||||
| #[allow(missing_docs)] | ||||
| #[repr(i32)] | ||||
| #[derive(Debug, PartialEq)] | ||||
| #[derive(Debug, PartialEq, Eq)] | ||||
| #[non_exhaustive] | ||||
| #[allow(clippy::upper_case_acronyms)] | ||||
| pub enum ConflictType { | ||||
| @@ -684,7 +686,7 @@ impl From<i32> for ConflictType { | ||||
| /// See [here](https://sqlite.org/session.html#SQLITE_CHANGESET_ABORT) for details. | ||||
| #[allow(missing_docs)] | ||||
| #[repr(i32)] | ||||
| #[derive(Debug, PartialEq)] | ||||
| #[derive(Debug, PartialEq, Eq)] | ||||
| #[non_exhaustive] | ||||
| #[allow(clippy::upper_case_acronyms)] | ||||
| pub enum ConflictAction { | ||||
|   | ||||
| @@ -3,7 +3,7 @@ use std::os::raw::{c_int, c_void}; | ||||
| #[cfg(feature = "array")] | ||||
| use std::rc::Rc; | ||||
| use std::slice::from_raw_parts; | ||||
| use std::{convert, fmt, mem, ptr, str}; | ||||
| use std::{fmt, mem, ptr, str}; | ||||
|  | ||||
| use super::ffi; | ||||
| use super::{len_as_c_int, str_for_sqlite}; | ||||
| @@ -202,7 +202,7 @@ impl Statement<'_> { | ||||
|     /// } | ||||
|     /// ``` | ||||
|     /// | ||||
|     /// Or, equivalently (but without the [`params!`] macro). | ||||
|     /// Or, equivalently (but without the [`crate::params!`] macro). | ||||
|     /// | ||||
|     /// ```rust,no_run | ||||
|     /// # use rusqlite::{Connection, Result}; | ||||
| @@ -417,7 +417,7 @@ impl Statement<'_> { | ||||
|     pub fn query_and_then<T, E, P, F>(&mut self, params: P, f: F) -> Result<AndThenRows<'_, F>> | ||||
|     where | ||||
|         P: Params, | ||||
|         E: convert::From<Error>, | ||||
|         E: From<Error>, | ||||
|         F: FnMut(&Row<'_>) -> Result<T, E>, | ||||
|     { | ||||
|         self.query(params).map(|rows| rows.and_then(f)) | ||||
| @@ -447,7 +447,7 @@ impl Statement<'_> { | ||||
|         f: F, | ||||
|     ) -> Result<AndThenRows<'_, F>> | ||||
|     where | ||||
|         E: convert::From<Error>, | ||||
|         E: From<Error>, | ||||
|         F: FnMut(&Row<'_>) -> Result<T, E>, | ||||
|     { | ||||
|         self.query_and_then(params, f) | ||||
| @@ -796,7 +796,7 @@ impl Statement<'_> { | ||||
|         self.conn.decode_result(stmt.finalize()) | ||||
|     } | ||||
|  | ||||
|     #[cfg(all(feature = "modern_sqlite", feature = "extra_check"))] | ||||
|     #[cfg(feature = "extra_check")] | ||||
|     #[inline] | ||||
|     fn check_update(&self) -> Result<()> { | ||||
|         // sqlite3_column_count works for DML but not for DDL (ie ALTER) | ||||
| @@ -806,16 +806,6 @@ impl Statement<'_> { | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     #[cfg(all(not(feature = "modern_sqlite"), feature = "extra_check"))] | ||||
|     #[inline] | ||||
|     fn check_update(&self) -> Result<()> { | ||||
|         // sqlite3_column_count works for DML but not for DDL (ie ALTER) | ||||
|         if self.column_count() > 0 { | ||||
|             return Err(Error::ExecuteReturnedResults); | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "extra_check"))] | ||||
|     #[inline] | ||||
|     #[allow(clippy::unnecessary_wraps)] | ||||
| @@ -825,8 +815,6 @@ impl Statement<'_> { | ||||
|  | ||||
|     /// Returns a string containing the SQL text of prepared statement with | ||||
|     /// bound parameters expanded. | ||||
|     #[cfg(feature = "modern_sqlite")] | ||||
|     #[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))] | ||||
|     pub fn expanded_sql(&self) -> Option<String> { | ||||
|         self.stmt | ||||
|             .expanded_sql() | ||||
| @@ -1407,7 +1395,6 @@ mod test { | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     #[cfg(feature = "modern_sqlite")] | ||||
|     fn test_expanded_sql() -> Result<()> { | ||||
|         let db = Connection::open_in_memory()?; | ||||
|         let stmt = db.prepare("SELECT ?")?; | ||||
| @@ -1422,7 +1409,7 @@ mod test { | ||||
|         // dynamic slice: | ||||
|         db.query_row( | ||||
|             "SELECT ?1, ?2, ?3", | ||||
|             &[&1u8 as &dyn ToSql, &"one", &Some("one")], | ||||
|             [&1u8 as &dyn ToSql, &"one", &Some("one")], | ||||
|             |row| row.get::<_, u8>(0), | ||||
|         )?; | ||||
|         // existing collection: | ||||
| @@ -1474,10 +1461,10 @@ mod test { | ||||
|         let conn = Connection::open_in_memory()?; | ||||
|         let mut stmt = conn.prepare("")?; | ||||
|         assert_eq!(0, stmt.column_count()); | ||||
|         assert!(stmt.parameter_index("test").is_ok()); | ||||
|         assert!(stmt.step().is_err()); | ||||
|         stmt.parameter_index("test").unwrap(); | ||||
|         stmt.step().unwrap_err(); | ||||
|         stmt.reset(); | ||||
|         assert!(stmt.execute([]).is_err()); | ||||
|         stmt.execute([]).unwrap_err(); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
| @@ -1507,12 +1494,12 @@ mod test { | ||||
|     #[test] | ||||
|     fn test_utf16_conversion() -> Result<()> { | ||||
|         let db = Connection::open_in_memory()?; | ||||
|         db.pragma_update(None, "encoding", &"UTF-16le")?; | ||||
|         db.pragma_update(None, "encoding", "UTF-16le")?; | ||||
|         let encoding: String = db.pragma_query_value(None, "encoding", |row| row.get(0))?; | ||||
|         assert_eq!("UTF-16le", encoding); | ||||
|         db.execute_batch("CREATE TABLE foo(x TEXT)")?; | ||||
|         let expected = "テスト"; | ||||
|         db.execute("INSERT INTO foo(x) VALUES (?)", &[&expected])?; | ||||
|         db.execute("INSERT INTO foo(x) VALUES (?)", [&expected])?; | ||||
|         let actual: String = db.query_row("SELECT x FROM foo", [], |row| row.get(0))?; | ||||
|         assert_eq!(expected, actual); | ||||
|         Ok(()) | ||||
| @@ -1537,12 +1524,11 @@ mod test { | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     #[cfg(all(feature = "modern_sqlite", not(feature = "bundled-sqlcipher")))] // SQLite >= 3.38.0 | ||||
|     #[cfg(feature = "modern_sqlite")] // SQLite >= 3.38.0 | ||||
|     fn test_error_offset() -> Result<()> { | ||||
|         use crate::ffi::ErrorCode; | ||||
|         let db = Connection::open_in_memory()?; | ||||
|         let r = db.execute_batch("SELECT CURRENT_TIMESTANP;"); | ||||
|         assert!(r.is_err()); | ||||
|         match r.unwrap_err() { | ||||
|             Error::SqlInputError { error, offset, .. } => { | ||||
|                 assert_eq!(error.code, ErrorCode::Unknown); | ||||
|   | ||||
| @@ -255,7 +255,7 @@ impl Savepoint<'_> { | ||||
|         name: T, | ||||
|     ) -> Result<Savepoint<'_>> { | ||||
|         let name = name.into(); | ||||
|         conn.execute_batch(&format!("SAVEPOINT {}", name)) | ||||
|         conn.execute_batch(&format!("SAVEPOINT {name}")) | ||||
|             .map(|_| Savepoint { | ||||
|                 conn, | ||||
|                 name, | ||||
| @@ -267,7 +267,7 @@ impl Savepoint<'_> { | ||||
|  | ||||
|     #[inline] | ||||
|     fn with_depth(conn: &Connection, depth: u32) -> Result<Savepoint<'_>> { | ||||
|         let name = format!("_rusqlite_sp_{}", depth); | ||||
|         let name = format!("_rusqlite_sp_{depth}"); | ||||
|         Savepoint::with_depth_and_name(conn, depth, name) | ||||
|     } | ||||
|  | ||||
| @@ -559,7 +559,7 @@ mod test { | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
|     fn assert_nested_tx_error(e: crate::Error) { | ||||
|     fn assert_nested_tx_error(e: Error) { | ||||
|         if let Error::SqliteFailure(e, Some(m)) = &e { | ||||
|             assert_eq!(e.extended_code, crate::ffi::SQLITE_ERROR); | ||||
|             // FIXME: Not ideal... | ||||
|   | ||||
| @@ -287,15 +287,15 @@ mod test { | ||||
|     fn test_sqlite_functions() -> Result<()> { | ||||
|         let db = checked_memory_handle()?; | ||||
|         let result: Result<NaiveTime> = db.query_row("SELECT CURRENT_TIME", [], |r| r.get(0)); | ||||
|         assert!(result.is_ok()); | ||||
|         result.unwrap(); | ||||
|         let result: Result<NaiveDate> = db.query_row("SELECT CURRENT_DATE", [], |r| r.get(0)); | ||||
|         assert!(result.is_ok()); | ||||
|         result.unwrap(); | ||||
|         let result: Result<NaiveDateTime> = | ||||
|             db.query_row("SELECT CURRENT_TIMESTAMP", [], |r| r.get(0)); | ||||
|         assert!(result.is_ok()); | ||||
|         result.unwrap(); | ||||
|         let result: Result<DateTime<Utc>> = | ||||
|             db.query_row("SELECT CURRENT_TIMESTAMP", [], |r| r.get(0)); | ||||
|         assert!(result.is_ok()); | ||||
|         result.unwrap(); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
| @@ -303,7 +303,7 @@ mod test { | ||||
|     fn test_naive_date_time_param() -> Result<()> { | ||||
|         let db = checked_memory_handle()?; | ||||
|         let result: Result<bool> = db.query_row("SELECT 1 WHERE ? BETWEEN datetime('now', '-1 minute') AND datetime('now', '+1 minute')", [Utc::now().naive_utc()], |r| r.get(0)); | ||||
|         assert!(result.is_ok()); | ||||
|         result.unwrap(); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
| @@ -311,13 +311,13 @@ mod test { | ||||
|     fn test_date_time_param() -> Result<()> { | ||||
|         let db = checked_memory_handle()?; | ||||
|         let result: Result<bool> = db.query_row("SELECT 1 WHERE ? BETWEEN datetime('now', '-1 minute') AND datetime('now', '+1 minute')", [Utc::now()], |r| r.get(0)); | ||||
|         assert!(result.is_ok()); | ||||
|         result.unwrap(); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_lenient_parse_timezone() { | ||||
|         assert!(DateTime::<Utc>::column_result(ValueRef::Text(b"1970-01-01T00:00:00Z")).is_ok()); | ||||
|         assert!(DateTime::<Utc>::column_result(ValueRef::Text(b"1970-01-01T00:00:00+00")).is_ok()); | ||||
|         DateTime::<Utc>::column_result(ValueRef::Text(b"1970-01-01T00:00:00Z")).unwrap(); | ||||
|         DateTime::<Utc>::column_result(ValueRef::Text(b"1970-01-01T00:00:00+00")).unwrap(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -52,7 +52,7 @@ impl fmt::Display for FromSqlError { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||
|         match *self { | ||||
|             FromSqlError::InvalidType => write!(f, "Invalid type"), | ||||
|             FromSqlError::OutOfRange(i) => write!(f, "Value {} out of range", i), | ||||
|             FromSqlError::OutOfRange(i) => write!(f, "Value {i} out of range"), | ||||
|             FromSqlError::InvalidBlobSize { | ||||
|                 expected_size, | ||||
|                 blob_size, | ||||
| @@ -240,11 +240,11 @@ mod test { | ||||
|  | ||||
|         fn check_ranges<T>(db: &Connection, out_of_range: &[i64], in_range: &[i64]) | ||||
|         where | ||||
|             T: Into<i64> + FromSql + ::std::fmt::Debug, | ||||
|             T: Into<i64> + FromSql + std::fmt::Debug, | ||||
|         { | ||||
|             for n in out_of_range { | ||||
|                 let err = db | ||||
|                     .query_row("SELECT ?", &[n], |r| r.get::<_, T>(0)) | ||||
|                     .query_row("SELECT ?", [n], |r| r.get::<_, T>(0)) | ||||
|                     .unwrap_err(); | ||||
|                 match err { | ||||
|                     Error::IntegralValueOutOfRange(_, value) => assert_eq!(*n, value), | ||||
| @@ -254,7 +254,7 @@ mod test { | ||||
|             for n in in_range { | ||||
|                 assert_eq!( | ||||
|                     *n, | ||||
|                     db.query_row("SELECT ?", &[n], |r| r.get::<_, T>(0)) | ||||
|                     db.query_row("SELECT ?", [n], |r| r.get::<_, T>(0)) | ||||
|                         .unwrap() | ||||
|                         .into() | ||||
|                 ); | ||||
|   | ||||
| @@ -140,7 +140,6 @@ impl fmt::Display for Type { | ||||
| mod test { | ||||
|     use super::Value; | ||||
|     use crate::{params, Connection, Error, Result, Statement}; | ||||
|     use std::f64::EPSILON; | ||||
|     use std::os::raw::{c_double, c_int}; | ||||
|  | ||||
|     fn checked_memory_handle() -> Result<Connection> { | ||||
| @@ -154,7 +153,7 @@ mod test { | ||||
|         let db = checked_memory_handle()?; | ||||
|  | ||||
|         let v1234 = vec![1u8, 2, 3, 4]; | ||||
|         db.execute("INSERT INTO foo(b) VALUES (?)", &[&v1234])?; | ||||
|         db.execute("INSERT INTO foo(b) VALUES (?)", [&v1234])?; | ||||
|  | ||||
|         let v: Vec<u8> = db.query_row("SELECT b FROM foo", [], |r| r.get(0))?; | ||||
|         assert_eq!(v, v1234); | ||||
| @@ -166,7 +165,7 @@ mod test { | ||||
|         let db = checked_memory_handle()?; | ||||
|  | ||||
|         let empty = vec![]; | ||||
|         db.execute("INSERT INTO foo(b) VALUES (?)", &[&empty])?; | ||||
|         db.execute("INSERT INTO foo(b) VALUES (?)", [&empty])?; | ||||
|  | ||||
|         let v: Vec<u8> = db.query_row("SELECT b FROM foo", [], |r| r.get(0))?; | ||||
|         assert_eq!(v, empty); | ||||
| @@ -178,7 +177,7 @@ mod test { | ||||
|         let db = checked_memory_handle()?; | ||||
|  | ||||
|         let s = "hello, world!"; | ||||
|         db.execute("INSERT INTO foo(t) VALUES (?)", &[&s])?; | ||||
|         db.execute("INSERT INTO foo(t) VALUES (?)", [&s])?; | ||||
|  | ||||
|         let from: String = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?; | ||||
|         assert_eq!(from, s); | ||||
| @@ -217,8 +216,8 @@ mod test { | ||||
|         let s = Some("hello, world!"); | ||||
|         let b = Some(vec![1u8, 2, 3, 4]); | ||||
|  | ||||
|         db.execute("INSERT INTO foo(t) VALUES (?)", &[&s])?; | ||||
|         db.execute("INSERT INTO foo(b) VALUES (?)", &[&b])?; | ||||
|         db.execute("INSERT INTO foo(t) VALUES (?)", [&s])?; | ||||
|         db.execute("INSERT INTO foo(b) VALUES (?)", [&b])?; | ||||
|  | ||||
|         let mut stmt = db.prepare("SELECT t, b FROM foo ORDER BY ROWID ASC")?; | ||||
|         let mut rows = stmt.query([])?; | ||||
| @@ -264,7 +263,7 @@ mod test { | ||||
|         assert_eq!(vec![1, 2], row.get::<_, Vec<u8>>(0)?); | ||||
|         assert_eq!("text", row.get::<_, String>(1)?); | ||||
|         assert_eq!(1, row.get::<_, c_int>(2)?); | ||||
|         assert!((1.5 - row.get::<_, c_double>(3)?).abs() < EPSILON); | ||||
|         assert!((1.5 - row.get::<_, c_double>(3)?).abs() < f64::EPSILON); | ||||
|         assert_eq!(row.get::<_, Option<c_int>>(4)?, None); | ||||
|         assert_eq!(row.get::<_, Option<c_double>>(4)?, None); | ||||
|         assert_eq!(row.get::<_, Option<String>>(4)?, None); | ||||
| @@ -355,7 +354,7 @@ mod test { | ||||
|         assert_eq!(Value::Text(String::from("text")), row.get::<_, Value>(1)?); | ||||
|         assert_eq!(Value::Integer(1), row.get::<_, Value>(2)?); | ||||
|         match row.get::<_, Value>(3)? { | ||||
|             Value::Real(val) => assert!((1.5 - val).abs() < EPSILON), | ||||
|             Value::Real(val) => assert!((1.5 - val).abs() < f64::EPSILON), | ||||
|             x => panic!("Invalid Value {:?}", x), | ||||
|         } | ||||
|         assert_eq!(Value::Null, row.get::<_, Value>(4)?); | ||||
|   | ||||
| @@ -41,7 +41,7 @@ mod test { | ||||
|         let data: serde_json::Value = serde_json::from_str(json).unwrap(); | ||||
|         db.execute( | ||||
|             "INSERT INTO foo (t, b) VALUES (?, ?)", | ||||
|             &[&data as &dyn ToSql, &json.as_bytes()], | ||||
|             [&data as &dyn ToSql, &json.as_bytes()], | ||||
|         )?; | ||||
|  | ||||
|         let t: serde_json::Value = db.query_row("SELECT t FROM foo", [], |r| r.get(0))?; | ||||
|   | ||||
| @@ -154,7 +154,7 @@ mod test { | ||||
|         let db = Connection::open_in_memory()?; | ||||
|         let result: Result<OffsetDateTime> = | ||||
|             db.query_row("SELECT CURRENT_TIMESTAMP", [], |r| r.get(0)); | ||||
|         assert!(result.is_ok()); | ||||
|         result.unwrap(); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
| @@ -162,7 +162,7 @@ mod test { | ||||
|     fn test_param() -> Result<()> { | ||||
|         let db = Connection::open_in_memory()?; | ||||
|         let result: Result<bool> = db.query_row("SELECT 1 WHERE ? BETWEEN datetime('now', '-1 minute') AND datetime('now', '+1 minute')", [OffsetDateTime::now_utc()], |r| r.get(0)); | ||||
|         assert!(result.is_ok()); | ||||
|         result.unwrap(); | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -278,7 +278,7 @@ mod test { | ||||
|         let _a: &[&dyn ToSql] = crate::params![a]; | ||||
|         let r = ToSql::to_sql(&a); | ||||
|  | ||||
|         assert!(r.is_ok()); | ||||
|         r.unwrap(); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
| @@ -287,10 +287,10 @@ mod test { | ||||
|         let s = "str"; | ||||
|         let cow: Cow<str> = Cow::Borrowed(s); | ||||
|         let r = cow.to_sql(); | ||||
|         assert!(r.is_ok()); | ||||
|         r.unwrap(); | ||||
|         let cow: Cow<str> = Cow::Owned::<str>(String::from(s)); | ||||
|         let r = cow.to_sql(); | ||||
|         assert!(r.is_ok()); | ||||
|         r.unwrap(); | ||||
|         // Ensure this compiles. | ||||
|         let _p: &[&dyn ToSql] = crate::params![cow]; | ||||
|     } | ||||
| @@ -301,7 +301,7 @@ mod test { | ||||
|         let _s: &[&dyn ToSql] = crate::params![s]; | ||||
|         let r = ToSql::to_sql(&s); | ||||
|  | ||||
|         assert!(r.is_ok()); | ||||
|         r.unwrap(); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
| @@ -310,7 +310,7 @@ mod test { | ||||
|         let _s: &[&dyn ToSql] = crate::params![s]; | ||||
|         let r = s.to_sql(); | ||||
|  | ||||
|         assert!(r.is_ok()); | ||||
|         r.unwrap(); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
| @@ -319,7 +319,7 @@ mod test { | ||||
|         let _s: &[&dyn ToSql] = crate::params![s]; | ||||
|         let r = ToSql::to_sql(&s); | ||||
|  | ||||
|         assert!(r.is_ok()); | ||||
|         r.unwrap(); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
| @@ -331,39 +331,38 @@ mod test { | ||||
|         let s: Rc<Box<str>> = Rc::new(source_str.clone()); | ||||
|         let _s: &[&dyn ToSql] = crate::params![s]; | ||||
|         let r = s.to_sql(); | ||||
|         assert!(r.is_ok()); | ||||
|         r.unwrap(); | ||||
|  | ||||
|         let s: Arc<Box<str>> = Arc::new(source_str.clone()); | ||||
|         let _s: &[&dyn ToSql] = crate::params![s]; | ||||
|         let r = s.to_sql(); | ||||
|         assert!(r.is_ok()); | ||||
|         r.unwrap(); | ||||
|  | ||||
|         let s: Arc<str> = Arc::from(&*source_str); | ||||
|         let _s: &[&dyn ToSql] = crate::params![s]; | ||||
|         let r = s.to_sql(); | ||||
|         assert!(r.is_ok()); | ||||
|         r.unwrap(); | ||||
|  | ||||
|         let s: Arc<dyn ToSql> = Arc::new(source_str.clone()); | ||||
|         let _s: &[&dyn ToSql] = crate::params![s]; | ||||
|         let r = s.to_sql(); | ||||
|         assert!(r.is_ok()); | ||||
|         r.unwrap(); | ||||
|  | ||||
|         let s: Rc<str> = Rc::from(&*source_str); | ||||
|         let _s: &[&dyn ToSql] = crate::params![s]; | ||||
|         let r = s.to_sql(); | ||||
|         assert!(r.is_ok()); | ||||
|         r.unwrap(); | ||||
|  | ||||
|         let s: Rc<dyn ToSql> = Rc::new(source_str); | ||||
|         let _s: &[&dyn ToSql] = crate::params![s]; | ||||
|         let r = s.to_sql(); | ||||
|         assert!(r.is_ok()); | ||||
|         r.unwrap(); | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "i128_blob")] | ||||
|     #[test] | ||||
|     fn test_i128() -> crate::Result<()> { | ||||
|         use crate::Connection; | ||||
|         use std::i128; | ||||
|         let db = Connection::open_in_memory()?; | ||||
|         db.execute_batch("CREATE TABLE foo (i128 BLOB, desc TEXT)")?; | ||||
|         db.execute( | ||||
|   | ||||
| @@ -5,7 +5,5 @@ pub(crate) use param_cache::ParamIndexCache; | ||||
| pub(crate) use small_cstr::SmallCString; | ||||
|  | ||||
| // Doesn't use any modern features or vtab stuff, but is only used by them. | ||||
| #[cfg(any(feature = "modern_sqlite", feature = "vtab"))] | ||||
| mod sqlite_string; | ||||
| #[cfg(any(feature = "modern_sqlite", feature = "vtab"))] | ||||
| pub(crate) use sqlite_string::SqliteMallocString; | ||||
|   | ||||
| @@ -5,7 +5,7 @@ use std::ffi::{CStr, CString, NulError}; | ||||
| /// small enough. Also guarantees it's input is UTF-8 -- used for cases where we | ||||
| /// need to pass a NUL-terminated string to SQLite, and we have a `&str`. | ||||
| #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] | ||||
| pub(crate) struct SmallCString(smallvec::SmallVec<[u8; 16]>); | ||||
| pub(crate) struct SmallCString(SmallVec<[u8; 16]>); | ||||
|  | ||||
| impl SmallCString { | ||||
|     #[inline] | ||||
| @@ -163,8 +163,8 @@ mod test { | ||||
|         assert_eq!(SmallCString::new("").unwrap().0.as_slice(), b"\0"); | ||||
|         assert_eq!(SmallCString::new("").unwrap().as_bytes_without_nul(), b""); | ||||
|  | ||||
|         assert!(SmallCString::new("\0").is_err()); | ||||
|         assert!(SmallCString::new("\0abc").is_err()); | ||||
|         assert!(SmallCString::new("abc\0").is_err()); | ||||
|         SmallCString::new("\0").unwrap_err(); | ||||
|         SmallCString::new("\0abc").unwrap_err(); | ||||
|         SmallCString::new("abc\0").unwrap_err(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,10 +1,7 @@ | ||||
| // This is used when either vtab or modern-sqlite is on. Different methods are | ||||
| // used in each feature. Avoid having to track this for each function. We will | ||||
| // still warn for anything that's not used by either, though. | ||||
| #![cfg_attr( | ||||
|     not(all(feature = "vtab", feature = "modern-sqlite")), | ||||
|     allow(dead_code) | ||||
| )] | ||||
| #![cfg_attr(not(feature = "vtab"), allow(dead_code))] | ||||
| use crate::ffi; | ||||
| use std::marker::PhantomData; | ||||
| use std::os::raw::{c_char, c_int}; | ||||
| @@ -134,7 +131,8 @@ impl SqliteMallocString { | ||||
|                     //   (everything is aligned to 1) | ||||
|                     // - `size` is also never zero, although this function doesn't actually require | ||||
|                     //   it now. | ||||
|                     let layout = Layout::from_size_align_unchecked(s.len().saturating_add(1), 1); | ||||
|                     let len = s.len().saturating_add(1).min(isize::MAX as usize); | ||||
|                     let layout = Layout::from_size_align_unchecked(len, 1); | ||||
|                     // Note: This call does not return. | ||||
|                     handle_alloc_error(layout); | ||||
|                 }); | ||||
| @@ -214,7 +212,7 @@ mod test { | ||||
|         let mut v = vec![]; | ||||
|         for i in 0..1000 { | ||||
|             v.push(SqliteMallocString::from_str(&i.to_string()).into_raw()); | ||||
|             v.push(SqliteMallocString::from_str(&format!("abc {} 😀", i)).into_raw()); | ||||
|             v.push(SqliteMallocString::from_str(&format!("abc {i} 😀")).into_raw()); | ||||
|         } | ||||
|         unsafe { | ||||
|             for (i, s) in v.chunks_mut(2).enumerate() { | ||||
| @@ -226,7 +224,7 @@ mod test { | ||||
|                 ); | ||||
|                 assert_eq!( | ||||
|                     std::ffi::CStr::from_ptr(s1).to_str().unwrap(), | ||||
|                     &format!("abc {} 😀", i) | ||||
|                     &format!("abc {i} 😀") | ||||
|                 ); | ||||
|                 let _ = SqliteMallocString::from_raw(s0).unwrap(); | ||||
|                 let _ = SqliteMallocString::from_raw(s1).unwrap(); | ||||
|   | ||||
| @@ -208,7 +208,7 @@ mod test { | ||||
|         { | ||||
|             let mut stmt = db.prepare("SELECT value from rarray(?);")?; | ||||
|  | ||||
|             let rows = stmt.query_map(&[&ptr], |row| row.get::<_, i64>(0))?; | ||||
|             let rows = stmt.query_map([&ptr], |row| row.get::<_, i64>(0))?; | ||||
|             assert_eq!(2, Rc::strong_count(&ptr)); | ||||
|             let mut count = 0; | ||||
|             for (i, value) in rows.enumerate() { | ||||
|   | ||||
| @@ -11,7 +11,7 @@ | ||||
| //!     // Note: This should be done once (usually when opening the DB). | ||||
| //!     let db = Connection::open_in_memory()?; | ||||
| //!     rusqlite::vtab::csvtab::load_module(&db)?; | ||||
| //!     // Assum3e my_csv.csv | ||||
| //!     // Assume my_csv.csv | ||||
| //!     let schema = " | ||||
| //!         CREATE VIRTUAL TABLE my_csv_data | ||||
| //!         USING csv(filename = 'my_csv.csv') | ||||
| @@ -208,13 +208,13 @@ unsafe impl<'vtab> VTab<'vtab> for CsvTab { | ||||
|                 let mut record = csv::ByteRecord::new(); | ||||
|                 if reader.read_byte_record(&mut record)? { | ||||
|                     for (i, _) in record.iter().enumerate() { | ||||
|                         cols.push(format!("c{}", i)); | ||||
|                         cols.push(format!("c{i}")); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } else if let Some(n_col) = n_col { | ||||
|             for i in 0..n_col { | ||||
|                 cols.push(format!("c{}", i)); | ||||
|                 cols.push(format!("c{i}")); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -187,8 +187,7 @@ pub fn eponymous_only_module<'vtab, T: VTab<'vtab>>() -> &'static Module<'vtab, | ||||
| /// Virtual table configuration options | ||||
| #[repr(i32)] | ||||
| #[non_exhaustive] | ||||
| #[cfg(feature = "modern_sqlite")] // 3.7.7 | ||||
| #[derive(Debug, Clone, Copy, PartialEq)] | ||||
| #[derive(Debug, Clone, Copy, Eq, PartialEq)] | ||||
| pub enum VTabConfig { | ||||
|     /// Equivalent to SQLITE_VTAB_CONSTRAINT_SUPPORT | ||||
|     ConstraintSupport = 1, | ||||
| @@ -203,8 +202,6 @@ pub struct VTabConnection(*mut ffi::sqlite3); | ||||
|  | ||||
| impl VTabConnection { | ||||
|     /// Configure various facets of the virtual table interface | ||||
|     #[cfg(feature = "modern_sqlite")] // 3.7.7 | ||||
|     #[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))] | ||||
|     pub fn config(&mut self, config: VTabConfig) -> Result<()> { | ||||
|         crate::error::check(unsafe { ffi::sqlite3_vtab_config(self.0, config as c_int) }) | ||||
|     } | ||||
| @@ -322,7 +319,7 @@ pub trait UpdateVTab<'vtab>: CreateVTab<'vtab> { | ||||
|  | ||||
| /// Index constraint operator. | ||||
| /// See [Virtual Table Constraint Operator Codes](https://sqlite.org/c3ref/c_index_constraint_eq.html) for details. | ||||
| #[derive(Debug, PartialEq)] | ||||
| #[derive(Debug, Eq, PartialEq)] | ||||
| #[allow(non_snake_case, non_camel_case_types, missing_docs)] | ||||
| #[allow(clippy::upper_case_acronyms)] | ||||
| pub enum IndexConstraintOp { | ||||
| @@ -369,7 +366,6 @@ impl From<u8> for IndexConstraintOp { | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "modern_sqlite")] // 3.9.0 | ||||
| bitflags::bitflags! { | ||||
|     /// Virtual table scan flags | ||||
|     /// See [Function Flags](https://sqlite.org/c3ref/c_index_scan_unique.html) for details. | ||||
| @@ -461,7 +457,7 @@ impl IndexInfo { | ||||
|     #[inline] | ||||
|     pub fn set_order_by_consumed(&mut self, order_by_consumed: bool) { | ||||
|         unsafe { | ||||
|             (*self.0).orderByConsumed = if order_by_consumed { 1 } else { 0 }; | ||||
|             (*self.0).orderByConsumed = order_by_consumed as c_int; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -474,8 +470,6 @@ impl IndexInfo { | ||||
|     } | ||||
|  | ||||
|     /// Estimated number of rows returned. | ||||
|     #[cfg(feature = "modern_sqlite")] // SQLite >= 3.8.2 | ||||
|     #[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))] | ||||
|     #[inline] | ||||
|     pub fn set_estimated_rows(&mut self, estimated_rows: i64) { | ||||
|         unsafe { | ||||
| @@ -484,16 +478,12 @@ impl IndexInfo { | ||||
|     } | ||||
|  | ||||
|     /// Mask of SQLITE_INDEX_SCAN_* flags. | ||||
|     #[cfg(feature = "modern_sqlite")] // SQLite >= 3.9.0 | ||||
|     #[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))] | ||||
|     #[inline] | ||||
|     pub fn set_idx_flags(&mut self, flags: IndexFlags) { | ||||
|         unsafe { (*self.0).idxFlags = flags.bits() }; | ||||
|     } | ||||
|  | ||||
|     /// Mask of columns used by statement | ||||
|     #[cfg(feature = "modern_sqlite")] // SQLite >= 3.10.0 | ||||
|     #[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))] | ||||
|     #[inline] | ||||
|     pub fn col_used(&self) -> u64 { | ||||
|         unsafe { (*self.0).colUsed } | ||||
| @@ -509,7 +499,7 @@ impl IndexInfo { | ||||
|         if collation.is_null() { | ||||
|             return Err(Error::SqliteFailure( | ||||
|                 ffi::Error::new(ffi::SQLITE_MISUSE), | ||||
|                 Some(format!("{} is out of range", constraint_idx)), | ||||
|                 Some(format!("{constraint_idx} is out of range")), | ||||
|             )); | ||||
|         } | ||||
|         Ok(unsafe { CStr::from_ptr(collation) }.to_str()?) | ||||
| @@ -623,7 +613,7 @@ impl IndexConstraintUsage<'_> { | ||||
|     /// if `omit`, do not code a test for this constraint | ||||
|     #[inline] | ||||
|     pub fn set_omit(&mut self, omit: bool) { | ||||
|         self.0.omit = if omit { 1 } else { 0 }; | ||||
|         self.0.omit = omit as std::os::raw::c_uchar; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -934,7 +924,7 @@ pub fn parameter(c_slice: &[u8]) -> Result<(&str, &str)> { | ||||
|             return Ok((param, value)); | ||||
|         } | ||||
|     } | ||||
|     Err(Error::ModuleError(format!("illegal argument: '{}'", arg))) | ||||
|     Err(Error::ModuleError(format!("illegal argument: '{arg}'"))) | ||||
| } | ||||
|  | ||||
| // FIXME copy/paste from function.rs | ||||
| @@ -963,7 +953,7 @@ where | ||||
|         .map(|&cs| CStr::from_ptr(cs).to_bytes()) // FIXME .to_str() -> Result<&str, Utf8Error> | ||||
|         .collect::<Vec<_>>(); | ||||
|     match T::create(&mut conn, aux.as_ref(), &vec[..]) { | ||||
|         Ok((sql, vtab)) => match ::std::ffi::CString::new(sql) { | ||||
|         Ok((sql, vtab)) => match std::ffi::CString::new(sql) { | ||||
|             Ok(c_sql) => { | ||||
|                 let rc = ffi::sqlite3_declare_vtab(db, c_sql.as_ptr()); | ||||
|                 if rc == ffi::SQLITE_OK { | ||||
| @@ -1015,7 +1005,7 @@ where | ||||
|         .map(|&cs| CStr::from_ptr(cs).to_bytes()) // FIXME .to_str() -> Result<&str, Utf8Error> | ||||
|         .collect::<Vec<_>>(); | ||||
|     match T::connect(&mut conn, aux.as_ref(), &vec[..]) { | ||||
|         Ok((sql, vtab)) => match ::std::ffi::CString::new(sql) { | ||||
|         Ok((sql, vtab)) => match std::ffi::CString::new(sql) { | ||||
|             Ok(c_sql) => { | ||||
|                 let rc = ffi::sqlite3_declare_vtab(db, c_sql.as_ptr()); | ||||
|                 if rc == ffi::SQLITE_OK { | ||||
| @@ -1334,7 +1324,7 @@ pub mod csvtab; | ||||
| #[cfg(feature = "series")] | ||||
| #[cfg_attr(docsrs, doc(cfg(feature = "series")))] | ||||
| pub mod series; // SQLite >= 3.9.0 | ||||
| #[cfg(test)] | ||||
| #[cfg(all(test, feature = "modern_sqlite"))] | ||||
| mod vtablog; | ||||
|  | ||||
| #[cfg(test)] | ||||
|   | ||||
| @@ -115,6 +115,7 @@ unsafe impl<'vtab> VTab<'vtab> for SeriesTab { | ||||
|         } | ||||
|         if idx_num.contains(QueryPlanFlags::BOTH) { | ||||
|             // Both start= and stop= boundaries are available. | ||||
|             //#[allow(clippy::bool_to_int_with_if)] | ||||
|             info.set_estimated_cost(f64::from( | ||||
|                 2 - if idx_num.contains(QueryPlanFlags::STEP) { | ||||
|                     1 | ||||
|   | ||||
| @@ -153,7 +153,7 @@ impl<'vtab> CreateVTab<'vtab> for VTabLog { | ||||
|  | ||||
| impl<'vtab> UpdateVTab<'vtab> for VTabLog { | ||||
|     fn delete(&mut self, arg: ValueRef<'_>) -> Result<()> { | ||||
|         println!("VTabLog::delete({}, {:?})", self.i_inst, arg); | ||||
|         println!("VTabLog::delete({}, {arg:?})", self.i_inst); | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
| @@ -163,7 +163,7 @@ impl<'vtab> UpdateVTab<'vtab> for VTabLog { | ||||
|             self.i_inst, | ||||
|             args.iter().collect::<Vec<ValueRef<'_>>>() | ||||
|         ); | ||||
|         Ok(self.n_row as i64) | ||||
|         Ok(self.n_row) | ||||
|     } | ||||
|  | ||||
|     fn update(&mut self, args: &Values<'_>) -> Result<()> { | ||||
| @@ -246,7 +246,7 @@ unsafe impl VTabCursor for VTabLogCursor<'_> { | ||||
|                 self.row_id | ||||
|             ) | ||||
|         } else { | ||||
|             format!("{}{}", i, self.row_id) | ||||
|             format!("{i}{}", self.row_id) | ||||
|         }; | ||||
|         println!( | ||||
|             "VTabLogCursor::column(tab={}, cursor={}, i={}): {}", | ||||
|   | ||||
		Reference in New Issue
	
	Block a user