Merge remote-tracking branch 'upstream/master' into sub_type

# Conflicts:
#	src/functions.rs
This commit is contained in:
gwenn
2022-10-30 09:01:28 +01:00
54 changed files with 25196 additions and 28094 deletions

View File

@@ -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();
}
{

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);

View File

@@ -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(())
}

View File

@@ -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(())
}

View File

@@ -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 {

View File

@@ -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);
}

View File

@@ -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(())
}
}

View File

@@ -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,
);
}

View File

@@ -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:
///

View File

@@ -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 {

View File

@@ -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)) }
}

View File

@@ -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(())
}

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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...

View File

@@ -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();
}
}

View File

@@ -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()
);

View File

@@ -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)?);

View File

@@ -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))?;

View File

@@ -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(())
}
}

View File

@@ -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(

View File

@@ -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;

View File

@@ -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();
}
}

View File

@@ -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();

View File

@@ -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() {

View File

@@ -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}"));
}
}

View File

@@ -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)]

View File

@@ -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

View File

@@ -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={}): {}",