Keep track of SQL input

This commit is contained in:
gwenn 2022-04-21 15:14:08 +02:00
parent cfcbb56fce
commit 8370970b0b
3 changed files with 22 additions and 10 deletions

View File

@ -136,6 +136,8 @@ pub enum Error {
error: ffi::Error, error: ffi::Error,
/// error message /// error message
msg: String, msg: String,
/// SQL input
sql: String,
/// byte offset of the start of invalid token /// byte offset of the start of invalid token
offset: c_int, offset: c_int,
}, },
@ -187,15 +189,17 @@ impl PartialEq for Error {
( (
Error::SqlInputError { Error::SqlInputError {
error: e1, error: e1,
msg: s1, msg: m1,
sql: s1,
offset: o1, offset: o1,
}, },
Error::SqlInputError { Error::SqlInputError {
error: e2, error: e2,
msg: s2, msg: m2,
sql: s2,
offset: o2, offset: o2,
}, },
) => e1 == e2 && s1 == s2 && o1 == o2, ) => e1 == e2 && m1 == m2 && s1 == s2 && o1 == o2,
(..) => false, (..) => false,
} }
} }
@ -309,8 +313,11 @@ impl fmt::Display for Error {
Error::BlobSizeError => "Blob size is insufficient".fmt(f), Error::BlobSizeError => "Blob size is insufficient".fmt(f),
#[cfg(feature = "modern_sqlite")] #[cfg(feature = "modern_sqlite")]
Error::SqlInputError { Error::SqlInputError {
ref msg, offset, .. ref msg,
} => write!(f, "{} at offset {}", msg, offset), offset,
ref sql,
..
} => write!(f, "{} in {} at offset {}", msg, sql, offset),
} }
} }
} }
@ -402,13 +409,13 @@ pub unsafe fn error_from_handle(db: *mut ffi::sqlite3, code: c_int) -> Error {
#[cold] #[cold]
#[cfg(not(feature = "modern_sqlite"))] #[cfg(not(feature = "modern_sqlite"))]
pub unsafe fn error_with_offset(db: *mut ffi::sqlite3, code: c_int) -> Error { pub unsafe fn error_with_offset(db: *mut ffi::sqlite3, code: c_int, sql: &str) -> Error {
error_from_handle(db, code) error_from_handle(db, code)
} }
#[cold] #[cold]
#[cfg(feature = "modern_sqlite")] // 3.38.0 #[cfg(feature = "modern_sqlite")] // 3.38.0
pub unsafe fn error_with_offset(db: *mut ffi::sqlite3, code: c_int) -> Error { pub unsafe fn error_with_offset(db: *mut ffi::sqlite3, code: c_int, sql: &str) -> Error {
if db.is_null() { if db.is_null() {
error_from_sqlite_code(code, None) error_from_sqlite_code(code, None)
} else { } else {
@ -417,7 +424,12 @@ pub unsafe fn error_with_offset(db: *mut ffi::sqlite3, code: c_int) -> Error {
if ffi::ErrorCode::Unknown == error.code { if ffi::ErrorCode::Unknown == error.code {
let offset = ffi::sqlite3_error_offset(db); let offset = ffi::sqlite3_error_offset(db);
if offset >= 0 { if offset >= 0 {
return Error::SqlInputError { error, msg, offset }; return Error::SqlInputError {
error,
msg,
sql: sql.to_owned(),
offset,
};
} }
} }
Error::SqliteFailure(error, Some(msg)) Error::SqliteFailure(error, Some(msg))

View File

@ -257,7 +257,7 @@ impl InnerConnection {
}; };
// If there is an error, *ppStmt is set to NULL. // If there is an error, *ppStmt is set to NULL.
if r != ffi::SQLITE_OK { if r != ffi::SQLITE_OK {
return Err(unsafe { error_with_offset(self.db, r) }); return Err(unsafe { error_with_offset(self.db, r, sql) });
} }
// If the input text contains no SQL (if the input is an empty string or a // If the input text contains no SQL (if the input is an empty string or a
// comment) then *ppStmt is set to NULL. // comment) then *ppStmt is set to NULL.

View File

@ -1537,7 +1537,7 @@ mod test {
} }
#[test] #[test]
#[cfg(feature = "modern_sqlite")] #[cfg(all(feature = "modern_sqlite", not(feature = "bundled-sqlcipher")))] // SQLite >= 3.38.0
fn test_error_offset() -> Result<()> { fn test_error_offset() -> Result<()> {
use crate::ffi::ErrorCode; use crate::ffi::ErrorCode;
let db = Connection::open_in_memory()?; let db = Connection::open_in_memory()?;