From cd5b78050532534e220386a90e2a22eb65092bcf Mon Sep 17 00:00:00 2001 From: gwenn Date: Sun, 25 Feb 2024 14:26:47 +0100 Subject: [PATCH] Remove obsolete codes and comments Minimal SQLite version supported by rusqlite is 3.14 --- README.md | 9 ++--- src/inner_connection.rs | 78 +++++++---------------------------------- src/lib.rs | 34 ++---------------- src/limits.rs | 14 +++----- 4 files changed, 22 insertions(+), 113 deletions(-) diff --git a/README.md b/README.md index ebb1ead..be71d28 100644 --- a/README.md +++ b/README.md @@ -94,17 +94,14 @@ features](https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-s allows loading dynamic library-based SQLite extensions. * `loadable_extension` to program [loadable extension](https://sqlite.org/loadext.html) in Rust. * [`backup`](https://docs.rs/rusqlite/~0/rusqlite/backup/index.html) - allows use of SQLite's online backup API. Note: This feature requires SQLite 3.6.11 or later. + allows use of SQLite's online backup API. * [`functions`](https://docs.rs/rusqlite/~0/rusqlite/functions/index.html) allows you to load Rust closures into SQLite connections for use in queries. - Note: This feature requires SQLite 3.7.3 or later. * `window` for [window function](https://www.sqlite.org/windowfunctions.html) support (`fun(...) OVER ...`). (Implies `functions`.) * [`trace`](https://docs.rs/rusqlite/~0/rusqlite/trace/index.html) - allows hooks into SQLite's tracing and profiling APIs. Note: This feature - requires SQLite 3.6.23 or later. + allows hooks into SQLite's tracing and profiling APIs. * [`blob`](https://docs.rs/rusqlite/~0/rusqlite/blob/index.html) - gives `std::io::{Read, Write, Seek}` access to SQL BLOBs. Note: This feature - requires SQLite 3.7.4 or later. + gives `std::io::{Read, Write, Seek}` access to SQL BLOBs. * [`limits`](https://docs.rs/rusqlite/~0/rusqlite/struct.Connection.html#method.limit) allows you to set and retrieve SQLite's per connection limits. * `chrono` implements [`FromSql`](https://docs.rs/rusqlite/~0/rusqlite/types/trait.FromSql.html) diff --git a/src/inner_connection.rs b/src/inner_connection.rs index b7c930f..23c9c4a 100644 --- a/src/inner_connection.rs +++ b/src/inner_connection.rs @@ -4,7 +4,6 @@ use std::os::raw::{c_char, c_int}; use std::path::Path; use std::ptr; use std::str; -use std::sync::atomic::AtomicBool; use std::sync::{Arc, Mutex}; use super::ffi; @@ -13,7 +12,6 @@ use super::{Connection, InterruptHandle, OpenFlags, PrepFlags, Result}; use crate::error::{error_from_handle, error_from_sqlite_code, error_with_offset, Error}; use crate::raw_statement::RawStatement; use crate::statement::Statement; -use crate::version::version_number; pub struct InnerConnection { pub db: *mut ffi::sqlite3, @@ -67,21 +65,6 @@ impl InnerConnection { ) -> Result { ensure_safe_sqlite_threading_mode()?; - // Replicate the check for sane open flags from SQLite, because the check in - // SQLite itself wasn't added until version 3.7.3. - debug_assert_eq!(1 << OpenFlags::SQLITE_OPEN_READ_ONLY.bits(), 0x02); - debug_assert_eq!(1 << OpenFlags::SQLITE_OPEN_READ_WRITE.bits(), 0x04); - debug_assert_eq!( - 1 << (OpenFlags::SQLITE_OPEN_READ_WRITE | OpenFlags::SQLITE_OPEN_CREATE).bits(), - 0x40 - ); - if (1 << (flags.bits() & 0x7)) & 0x46 == 0 { - return Err(Error::SqliteFailure( - ffi::Error::new(ffi::SQLITE_MISUSE), - None, - )); - } - let z_vfs = match vfs { Some(c_vfs) => c_vfs.as_ptr(), None => ptr::null(), @@ -390,11 +373,6 @@ impl Drop for InnerConnection { } } -#[cfg(not(any(target_arch = "wasm32", feature = "loadable_extension")))] -static SQLITE_INIT: std::sync::Once = std::sync::Once::new(); - -pub static BYPASS_SQLITE_INIT: AtomicBool = AtomicBool::new(false); - // threading mode checks are not necessary (and do not work) on target // platforms that do not have threading (such as webassembly) #[cfg(target_arch = "wasm32")] @@ -412,51 +390,21 @@ fn ensure_safe_sqlite_threading_mode() -> Result<()> { // Now we know SQLite is _capable_ of being in Multi-thread of Serialized mode, // but it's possible someone configured it to be in Single-thread mode // before calling into us. That would mean we're exposing an unsafe API via - // a safe one (in Rust terminology), which is no good. We have two options - // to protect against this, depending on the version of SQLite we're linked - // with: + // a safe one (in Rust terminology). // - // 1. If we're on 3.7.0 or later, we can ask SQLite for a mutex and check for - // the magic value 8. This isn't documented, but it's what SQLite - // returns for its mutex allocation function in Single-thread mode. - // 2. If we're prior to SQLite 3.7.0, AFAIK there's no way to check the - // threading mode. The check we perform for >= 3.7.0 will segfault. - // Instead, we insist on being able to call sqlite3_config and - // sqlite3_initialize ourself, ensuring we know the threading - // mode. This will fail if someone else has already initialized SQLite - // even if they initialized it safely. That's not ideal either, which is - // why we expose bypass_sqlite_initialization above. - if version_number() >= 3_007_000 { - const SQLITE_SINGLETHREADED_MUTEX_MAGIC: usize = 8; - let is_singlethreaded = unsafe { - let mutex_ptr = ffi::sqlite3_mutex_alloc(0); - let is_singlethreaded = mutex_ptr as usize == SQLITE_SINGLETHREADED_MUTEX_MAGIC; - ffi::sqlite3_mutex_free(mutex_ptr); - is_singlethreaded - }; - if is_singlethreaded { - Err(Error::SqliteSingleThreadedMode) - } else { - Ok(()) - } + // We can ask SQLite for a mutex and check for + // the magic value 8. This isn't documented, but it's what SQLite + // returns for its mutex allocation function in Single-thread mode. + const SQLITE_SINGLETHREADED_MUTEX_MAGIC: usize = 8; + let is_singlethreaded = unsafe { + let mutex_ptr = ffi::sqlite3_mutex_alloc(0); + let is_singlethreaded = mutex_ptr as usize == SQLITE_SINGLETHREADED_MUTEX_MAGIC; + ffi::sqlite3_mutex_free(mutex_ptr); + is_singlethreaded + }; + if is_singlethreaded { + Err(Error::SqliteSingleThreadedMode) } else { - #[cfg(not(feature = "loadable_extension"))] - SQLITE_INIT.call_once(|| { - use std::sync::atomic::Ordering; - if BYPASS_SQLITE_INIT.load(Ordering::Relaxed) { - return; - } - - unsafe { - assert!(ffi::sqlite3_config(ffi::SQLITE_CONFIG_MULTITHREAD) == ffi::SQLITE_OK && ffi::sqlite3_initialize() == ffi::SQLITE_OK, - "Could not ensure safe initialization of SQLite.\n\ - To fix this, either:\n\ - * Upgrade SQLite to at least version 3.7.0\n\ - * Ensure that SQLite has been initialized in Multi-thread or Serialized mode and call\n\ - rusqlite::bypass_sqlite_initialization() prior to your first connection attempt." - ); - } - }); Ok(()) } } diff --git a/src/lib.rs b/src/lib.rs index 03a3432..d5a8f0d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,11 +65,10 @@ use std::os::raw::{c_char, c_int}; use std::path::Path; use std::result; use std::str; -use std::sync::atomic::Ordering; use std::sync::{Arc, Mutex}; use crate::cache::StatementCache; -use crate::inner_connection::{InnerConnection, BYPASS_SQLITE_INIT}; +use crate::inner_connection::InnerConnection; use crate::raw_statement::RawStatement; use crate::types::ValueRef; @@ -1196,29 +1195,6 @@ bitflags::bitflags! { } } -/// rusqlite's check for a safe SQLite threading mode requires SQLite 3.7.0 or -/// later. If you are running against a SQLite older than that, rusqlite -/// attempts to ensure safety by performing configuration and initialization of -/// SQLite itself the first time you -/// attempt to open a connection. By default, rusqlite panics if that -/// initialization fails, since that could mean SQLite has been initialized in -/// single-thread mode. -/// -/// If you are encountering that panic _and_ can ensure that SQLite has been -/// initialized in either multi-thread or serialized mode, call this function -/// prior to attempting to open a connection and rusqlite's initialization -/// process will by skipped. -/// -/// # Safety -/// -/// This function is unsafe because if you call it and SQLite has actually been -/// configured to run in single-thread mode, -/// you may encounter memory errors or data corruption or any number of terrible -/// things that should not be possible when you're using Rust. -pub unsafe fn bypass_sqlite_initialization() { - BYPASS_SQLITE_INIT.store(true, Ordering::Relaxed); -} - /// Allows interrupting a long-running computation. pub struct InterruptHandle { db_lock: Arc>, @@ -1756,12 +1732,6 @@ mod test { #[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. - fn check_extended_code(extended_code: c_int) { - assert_eq!(extended_code, ffi::SQLITE_CONSTRAINT_NOTNULL); - } - let db = Connection::open_in_memory()?; db.execute_batch("CREATE TABLE foo(x NOT NULL)")?; @@ -1770,7 +1740,7 @@ mod test { match result.unwrap_err() { Error::SqliteFailure(err, _) => { assert_eq!(err.code, ErrorCode::ConstraintViolation); - check_extended_code(err.extended_code); + assert_eq!(err.extended_code, ffi::SQLITE_CONSTRAINT_NOTNULL); } err => panic!("Unexpected error {err}"), } diff --git a/src/limits.rs b/src/limits.rs index 16ef556..ef3f82d 100644 --- a/src/limits.rs +++ b/src/limits.rs @@ -148,17 +148,11 @@ mod test { db.set_limit(Limit::SQLITE_LIMIT_VARIABLE_NUMBER, 99); assert_eq!(99, db.limit(Limit::SQLITE_LIMIT_VARIABLE_NUMBER)); - // SQLITE_LIMIT_TRIGGER_DEPTH was added in SQLite 3.6.18. - if crate::version_number() >= 3_006_018 { - db.set_limit(Limit::SQLITE_LIMIT_TRIGGER_DEPTH, 32); - assert_eq!(32, db.limit(Limit::SQLITE_LIMIT_TRIGGER_DEPTH)); - } + db.set_limit(Limit::SQLITE_LIMIT_TRIGGER_DEPTH, 32); + assert_eq!(32, db.limit(Limit::SQLITE_LIMIT_TRIGGER_DEPTH)); - // SQLITE_LIMIT_WORKER_THREADS was added in SQLite 3.8.7. - if crate::version_number() >= 3_008_007 { - db.set_limit(Limit::SQLITE_LIMIT_WORKER_THREADS, 2); - assert_eq!(2, db.limit(Limit::SQLITE_LIMIT_WORKER_THREADS)); - } + db.set_limit(Limit::SQLITE_LIMIT_WORKER_THREADS, 2); + assert_eq!(2, db.limit(Limit::SQLITE_LIMIT_WORKER_THREADS)); Ok(()) } }