Skip to main content

rusqlite/
lib.rs

1//! Rusqlite is an ergonomic wrapper for using SQLite from Rust.
2//!
3//! Historically, the API was based on the one from
4//! [`rust-postgres`](https://github.com/sfackler/rust-postgres). However, the
5//! two have diverged in many ways, and no compatibility between the two is
6//! intended.
7//!
8//! ```rust
9//! use rusqlite::{params, Connection, Result};
10//!
11//! #[derive(Debug)]
12//! struct Person {
13//!     id: i32,
14//!     name: String,
15//!     data: Option<Vec<u8>>,
16//! }
17//!
18//! fn main() -> Result<()> {
19//!     let conn = Connection::open_in_memory()?;
20//!
21//!     conn.execute(
22//!         "CREATE TABLE person (
23//!             id   INTEGER PRIMARY KEY,
24//!             name TEXT NOT NULL,
25//!             data BLOB
26//!         )",
27//!         (), // empty list of parameters.
28//!     )?;
29//!     let me = Person {
30//!         id: 0,
31//!         name: "Steven".to_string(),
32//!         data: None,
33//!     };
34//!     conn.execute(
35//!         "INSERT INTO person (name, data) VALUES (?1, ?2)",
36//!         (&me.name, &me.data),
37//!     )?;
38//!
39//!     let mut stmt = conn.prepare("SELECT id, name, data FROM person")?;
40//!     let person_iter = stmt.query_map([], |row| {
41//!         Ok(Person {
42//!             id: row.get(0)?,
43//!             name: row.get(1)?,
44//!             data: row.get(2)?,
45//!         })
46//!     })?;
47//!
48//!     for person in person_iter {
49//!         println!("Found person {:?}", person?);
50//!     }
51//!     Ok(())
52//! }
53//! ```
54#![warn(missing_docs)]
55#![cfg_attr(docsrs, feature(doc_cfg))]
56
57pub use fallible_iterator;
58pub use fallible_streaming_iterator;
59
60#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
61pub use libsqlite3_sys as ffi;
62#[cfg(all(target_family = "wasm", target_os = "unknown"))]
63pub use sqlite_wasm_rs as ffi;
64
65use std::cell::RefCell;
66use std::default::Default;
67use std::ffi::{c_char, c_int, c_uint, CStr, CString};
68use std::fmt;
69
70use std::path::Path;
71use std::result;
72use std::str;
73use std::sync::{Arc, Mutex};
74
75#[cfg(feature = "cache")]
76use crate::cache::StatementCache;
77use crate::inner_connection::InnerConnection;
78use crate::raw_statement::RawStatement;
79use crate::types::ValueRef;
80
81pub use crate::bind::BindIndex;
82#[cfg(feature = "cache")]
83pub use crate::cache::CachedStatement;
84#[cfg(feature = "column_decltype")]
85pub use crate::column::Column;
86#[cfg(feature = "column_metadata")]
87pub use crate::column::ColumnMetadata;
88pub use crate::error::{to_sqlite_error, Error};
89pub use crate::ffi::ErrorCode;
90#[cfg(feature = "load_extension")]
91pub use crate::load_extension_guard::LoadExtensionGuard;
92pub use crate::params::{params_from_iter, Params, ParamsFromIter};
93pub use crate::row::{AndThenRows, Map, MappedRows, Row, RowIndex, Rows};
94pub use crate::statement::{Statement, StatementStatus};
95#[cfg(feature = "modern_sqlite")]
96pub use crate::transaction::TransactionState;
97pub use crate::transaction::{DropBehavior, Savepoint, Transaction, TransactionBehavior};
98pub use crate::types::ToSql;
99pub use crate::util::Name;
100pub use crate::version::*;
101#[cfg(feature = "rusqlite-macros")]
102#[doc(hidden)]
103pub use rusqlite_macros::__bind;
104
105#[macro_use]
106mod error;
107
108#[cfg(not(feature = "loadable_extension"))]
109pub mod auto_extension;
110#[cfg(feature = "backup")]
111pub mod backup;
112mod bind;
113#[cfg(feature = "blob")]
114pub mod blob;
115mod busy;
116#[cfg(feature = "cache")]
117mod cache;
118#[cfg(feature = "collation")]
119mod collation;
120mod column;
121pub mod config;
122#[cfg(any(feature = "functions", feature = "vtab"))]
123mod context;
124#[cfg(feature = "functions")]
125pub mod functions;
126#[cfg(feature = "hooks")]
127pub mod hooks;
128mod inner_connection;
129#[cfg(feature = "limits")]
130pub mod limits;
131#[cfg(feature = "load_extension")]
132mod load_extension_guard;
133mod params;
134mod pragma;
135mod raw_statement;
136mod row;
137#[cfg(feature = "serialize")]
138pub mod serialize;
139#[cfg(feature = "session")]
140pub mod session;
141mod statement;
142#[cfg(feature = "trace")]
143pub mod trace;
144mod transaction;
145pub mod types;
146#[cfg(feature = "unlock_notify")]
147mod unlock_notify;
148mod version;
149#[cfg(feature = "vtab")]
150pub mod vtab;
151
152pub(crate) mod util;
153
154// Actually, only sqlite3_enable_load_extension is disabled (not sqlite3_load_extension)
155#[cfg(all(feature = "loadable_extension", feature = "load_extension"))]
156compile_error!("feature \"loadable_extension\" and feature \"load_extension\" cannot be enabled at the same time");
157
158// Number of cached prepared statements we'll hold on to.
159#[cfg(feature = "cache")]
160const STATEMENT_CACHE_DEFAULT_CAPACITY: usize = 16;
161
162/// A macro making it more convenient to pass longer lists of
163/// parameters as a `&[&dyn ToSql]`.
164///
165/// # Example
166///
167/// ```rust,no_run
168/// # use rusqlite::{Result, Connection, params};
169///
170/// struct Person {
171///     name: String,
172///     age_in_years: u8,
173///     data: Option<Vec<u8>>,
174/// }
175///
176/// fn add_person(conn: &Connection, person: &Person) -> Result<()> {
177///     conn.execute(
178///         "INSERT INTO person(name, age_in_years, data) VALUES (?1, ?2, ?3)",
179///         params![person.name, person.age_in_years, person.data],
180///     )?;
181///     Ok(())
182/// }
183/// ```
184#[macro_export]
185macro_rules! params {
186    () => {
187        &[] as &[&dyn $crate::ToSql]
188    };
189    ($($param:expr),+ $(,)?) => {
190        &[$(&$param as &dyn $crate::ToSql),+] as &[&dyn $crate::ToSql]
191    };
192}
193
194/// A macro making it more convenient to pass lists of named parameters
195/// as a `&[(&str, &dyn ToSql)]`.
196///
197/// # Example
198///
199/// ```rust,no_run
200/// # use rusqlite::{Result, Connection, named_params};
201///
202/// struct Person {
203///     name: String,
204///     age_in_years: u8,
205///     data: Option<Vec<u8>>,
206/// }
207///
208/// fn add_person(conn: &Connection, person: &Person) -> Result<()> {
209///     conn.execute(
210///         "INSERT INTO person (name, age_in_years, data)
211///          VALUES (:name, :age, :data)",
212///         named_params! {
213///             ":name": person.name,
214///             ":age": person.age_in_years,
215///             ":data": person.data,
216///         },
217///     )?;
218///     Ok(())
219/// }
220/// ```
221#[macro_export]
222macro_rules! named_params {
223    () => {
224        &[] as &[(&str, &dyn $crate::ToSql)]
225    };
226    // Note: It's a lot more work to support this as part of the same macro as
227    // `params!`, unfortunately.
228    ($($param_name:literal: $param_val:expr),+ $(,)?) => {
229        &[$(($param_name, &$param_val as &dyn $crate::ToSql)),+] as &[(&str, &dyn $crate::ToSql)]
230    };
231}
232
233/// Captured identifiers in SQL
234///
235/// * only SQLite `$x` / `@x` / `:x` syntax works (Rust `&x` syntax does not
236///   work).
237/// * `$x.y` expression does not work.
238///
239/// # Example
240///
241/// ```rust, no_run
242/// # use rusqlite::{prepare_and_bind, Connection, Result, Statement};
243///
244/// fn misc(db: &Connection) -> Result<Statement> {
245///     let name = "Lisa";
246///     let age = 8;
247///     let smart = true;
248///     Ok(prepare_and_bind!(db, "SELECT $name, @age, :smart;"))
249/// }
250/// ```
251#[cfg(feature = "rusqlite-macros")]
252#[macro_export]
253macro_rules! prepare_and_bind {
254    ($conn:expr, $sql:literal) => {{
255        let mut stmt = $conn.prepare($sql)?;
256        $crate::__bind!(stmt $sql);
257        stmt
258    }};
259}
260
261/// Captured identifiers in SQL
262///
263/// * only SQLite `$x` / `@x` / `:x` syntax works (Rust `&x` syntax does not
264///   work).
265/// * `$x.y` expression does not work.
266#[cfg(feature = "rusqlite-macros")]
267#[macro_export]
268macro_rules! prepare_cached_and_bind {
269    ($conn:expr, $sql:literal) => {{
270        let mut stmt = $conn.prepare_cached($sql)?;
271        $crate::__bind!(stmt $sql);
272        stmt
273    }};
274}
275
276/// A typedef of the result returned by many methods.
277pub type Result<T, E = Error> = result::Result<T, E>;
278
279/// See the [method documentation](#tymethod.optional).
280pub trait OptionalExtension<T> {
281    /// Converts a `Result<T>` into a `Result<Option<T>>`.
282    ///
283    /// By default, Rusqlite treats 0 rows being returned from a query that is
284    /// expected to return 1 row as an error. This method will
285    /// handle that error, and give you back an `Option<T>` instead.
286    fn optional(self) -> Result<Option<T>>;
287}
288
289impl<T> OptionalExtension<T> for Result<T> {
290    fn optional(self) -> Result<Option<T>> {
291        match self {
292            Ok(value) => Ok(Some(value)),
293            Err(Error::QueryReturnedNoRows) => Ok(None),
294            Err(e) => Err(e),
295        }
296    }
297}
298
299unsafe fn errmsg_to_string(errmsg: *const c_char) -> String {
300    CStr::from_ptr(errmsg).to_string_lossy().into_owned()
301}
302
303#[cfg(any(feature = "functions", feature = "vtab", test))]
304fn str_to_cstring(s: &str) -> Result<util::SmallCString> {
305    Ok(util::SmallCString::new(s)?)
306}
307
308/// Returns `(string ptr, len as c_int, SQLITE_STATIC | SQLITE_TRANSIENT)`
309/// normally.
310/// The `sqlite3_destructor_type` item is always `SQLITE_TRANSIENT` unless
311/// the string was empty (in which case it's `SQLITE_STATIC`, and the ptr is
312/// static).
313fn str_for_sqlite(
314    s: &[u8],
315) -> (
316    *const c_char,
317    ffi::sqlite3_uint64,
318    ffi::sqlite3_destructor_type,
319) {
320    let len = s.len();
321    let (ptr, dtor_info) = if len != 0 {
322        (s.as_ptr().cast::<c_char>(), ffi::SQLITE_TRANSIENT())
323    } else {
324        // Return a pointer guaranteed to live forever
325        ("".as_ptr().cast::<c_char>(), ffi::SQLITE_STATIC())
326    };
327    (ptr, len as ffi::sqlite3_uint64, dtor_info)
328}
329
330#[cfg(unix)]
331fn path_to_cstring(p: &Path) -> Result<CString> {
332    use std::os::unix::ffi::OsStrExt;
333    Ok(CString::new(p.as_os_str().as_bytes())?)
334}
335
336#[cfg(not(unix))]
337fn path_to_cstring(p: &Path) -> Result<CString> {
338    let s = p.to_str().ok_or_else(|| Error::InvalidPath(p.to_owned()))?;
339    Ok(CString::new(s)?)
340}
341
342/// Shorthand for `Main` database.
343pub const MAIN_DB: &CStr = c"main";
344/// Shorthand for `Temp` database.
345pub const TEMP_DB: &CStr = c"temp";
346
347/// A connection to a SQLite database.
348pub struct Connection {
349    db: RefCell<InnerConnection>,
350    #[cfg(feature = "cache")]
351    cache: StatementCache,
352    transaction_behavior: TransactionBehavior,
353}
354
355unsafe impl Send for Connection {}
356
357impl Drop for Connection {
358    #[inline]
359    fn drop(&mut self) {
360        #[cfg(feature = "cache")]
361        self.flush_prepared_statement_cache();
362    }
363}
364
365impl Connection {
366    /// Open a new connection to a SQLite database. If a database does not exist
367    /// at the path, one is created.
368    ///
369    /// ```rust,no_run
370    /// # use rusqlite::{Connection, Result};
371    /// fn open_my_db() -> Result<()> {
372    ///     let path = "./my_db.db3";
373    ///     let db = Connection::open(path)?;
374    ///     // Use the database somehow...
375    ///     println!("{}", db.is_autocommit());
376    ///     Ok(())
377    /// }
378    /// ```
379    ///
380    /// # Flags
381    ///
382    /// `Connection::open(path)` is equivalent to using
383    /// [`Connection::open_with_flags`] with the default [`OpenFlags`]. That is,
384    /// it's equivalent to:
385    ///
386    /// ```ignore
387    /// Connection::open_with_flags(
388    ///     path,
389    ///     OpenFlags::SQLITE_OPEN_READ_WRITE
390    ///         | OpenFlags::SQLITE_OPEN_CREATE
391    ///         | OpenFlags::SQLITE_OPEN_URI
392    ///         | OpenFlags::SQLITE_OPEN_NO_MUTEX,
393    /// )
394    /// ```
395    ///
396    /// These flags have the following effects:
397    ///
398    /// - Open the database for both reading or writing.
399    /// - Create the database if one does not exist at the path.
400    /// - Allow the filename to be interpreted as a URI (see <https://www.sqlite.org/uri.html#uri_filenames_in_sqlite>
401    ///   for details).
402    /// - Disables the use of a per-connection mutex.
403    ///
404    ///   Rusqlite enforces thread-safety at compile time, so additional
405    ///   locking is not needed and provides no benefit. (See the
406    ///   documentation on [`OpenFlags::SQLITE_OPEN_FULL_MUTEX`] for some
407    ///   additional discussion about this).
408    ///
409    /// Most of these are also the default settings for the C API, although
410    /// technically the default locking behavior is controlled by the flags used
411    /// when compiling SQLite -- rather than let it vary, we choose `NO_MUTEX`
412    /// because it's a fairly clearly the best choice for users of this library.
413    ///
414    /// # Failure
415    ///
416    /// Will return `Err` if `path` cannot be converted to a C-compatible string
417    /// or if the underlying SQLite open call fails.
418    ///
419    /// # WASM support
420    ///
421    /// If you plan to use this connection type on the `wasm32-unknown-unknown` target please
422    /// make sure to read the following notes:
423    ///
424    /// - The database is stored in memory by default.
425    /// - Persistent VFS (Virtual File Systems) is optional,
426    ///   see <https://github.com/Spxg/sqlite-wasm-rs> for details
427    #[inline]
428    pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
429        let flags = OpenFlags::default();
430        Self::open_with_flags(path, flags)
431    }
432
433    /// Open a new connection to an in-memory SQLite database.
434    ///
435    /// # Failure
436    ///
437    /// Will return `Err` if the underlying SQLite open call fails.
438    #[inline]
439    pub fn open_in_memory() -> Result<Self> {
440        let flags = OpenFlags::default();
441        Self::open_in_memory_with_flags(flags)
442    }
443
444    /// Open a new connection to a SQLite database.
445    ///
446    /// [Database Connection](http://www.sqlite.org/c3ref/open.html) for a description of valid
447    /// flag combinations.
448    ///
449    /// # Failure
450    ///
451    /// Will return `Err` if `path` cannot be converted to a C-compatible
452    /// string or if the underlying SQLite open call fails.
453    #[inline]
454    pub fn open_with_flags<P: AsRef<Path>>(path: P, flags: OpenFlags) -> Result<Self> {
455        let c_path = path_to_cstring(path.as_ref())?;
456        InnerConnection::open_with_flags(&c_path, flags, None).map(|db| Self {
457            db: RefCell::new(db),
458            #[cfg(feature = "cache")]
459            cache: StatementCache::with_capacity(STATEMENT_CACHE_DEFAULT_CAPACITY),
460            transaction_behavior: TransactionBehavior::Deferred,
461        })
462    }
463
464    /// Open a new connection to a SQLite database using the specific flags and
465    /// vfs name.
466    ///
467    /// [Database Connection](http://www.sqlite.org/c3ref/open.html) for a description of valid
468    /// flag combinations.
469    ///
470    /// # Failure
471    ///
472    /// Will return `Err` if either `path` or `vfs` cannot be converted to a
473    /// C-compatible string or if the underlying SQLite open call fails.
474    #[inline]
475    pub fn open_with_flags_and_vfs<P: AsRef<Path>, V: Name>(
476        path: P,
477        flags: OpenFlags,
478        vfs: V,
479    ) -> Result<Self> {
480        let c_path = path_to_cstring(path.as_ref())?;
481        let c_vfs = vfs.as_cstr()?;
482        InnerConnection::open_with_flags(&c_path, flags, Some(&c_vfs)).map(|db| Self {
483            db: RefCell::new(db),
484            #[cfg(feature = "cache")]
485            cache: StatementCache::with_capacity(STATEMENT_CACHE_DEFAULT_CAPACITY),
486            transaction_behavior: TransactionBehavior::Deferred,
487        })
488    }
489
490    /// Open a new connection to an in-memory SQLite database.
491    ///
492    /// [Database Connection](http://www.sqlite.org/c3ref/open.html) for a description of valid
493    /// flag combinations.
494    ///
495    /// # Failure
496    ///
497    /// Will return `Err` if the underlying SQLite open call fails.
498    #[inline]
499    pub fn open_in_memory_with_flags(flags: OpenFlags) -> Result<Self> {
500        Self::open_with_flags(":memory:", flags)
501    }
502
503    /// Open a new connection to an in-memory SQLite database using the specific
504    /// flags and vfs name.
505    ///
506    /// [Database Connection](http://www.sqlite.org/c3ref/open.html) for a description of valid
507    /// flag combinations.
508    ///
509    /// # Failure
510    ///
511    /// Will return `Err` if `vfs` cannot be converted to a C-compatible
512    /// string or if the underlying SQLite open call fails.
513    #[inline]
514    pub fn open_in_memory_with_flags_and_vfs<V: Name>(flags: OpenFlags, vfs: V) -> Result<Self> {
515        Self::open_with_flags_and_vfs(":memory:", flags, vfs)
516    }
517
518    /// Convenience method to run multiple SQL statements (that cannot take any
519    /// parameters).
520    ///
521    /// ## Example
522    ///
523    /// ```rust,no_run
524    /// # use rusqlite::{Connection, Result};
525    /// fn create_tables(conn: &Connection) -> Result<()> {
526    ///     conn.execute_batch(
527    ///         "BEGIN;
528    ///          CREATE TABLE foo(x INTEGER);
529    ///          CREATE TABLE bar(y TEXT);
530    ///          COMMIT;",
531    ///     )
532    /// }
533    /// ```
534    ///
535    /// # Failure
536    ///
537    /// Will return `Err` if `sql` cannot be converted to a C-compatible string
538    /// or if the underlying SQLite call fails.
539    pub fn execute_batch(&self, sql: &str) -> Result<()> {
540        let mut sql = sql;
541        while !sql.is_empty() {
542            let (stmt, tail) = self
543                .db
544                .borrow_mut()
545                .prepare(self, sql, PrepFlags::default())?;
546            if !stmt.stmt.is_null() && stmt.step()? {
547                // Some PRAGMA may return rows
548                if false {
549                    return Err(Error::ExecuteReturnedResults);
550                }
551            }
552            if tail == 0 || tail >= sql.len() {
553                break;
554            }
555            sql = &sql[tail..];
556        }
557        Ok(())
558    }
559
560    /// Convenience method to prepare and execute a single SQL statement.
561    ///
562    /// On success, returns the number of rows that were changed or inserted or
563    /// deleted (via `sqlite3_changes`).
564    ///
565    /// ## Example
566    ///
567    /// ### With positional params
568    ///
569    /// ```rust,no_run
570    /// # use rusqlite::{Connection};
571    /// fn update_rows(conn: &Connection) {
572    ///     match conn.execute("UPDATE foo SET bar = 'baz' WHERE qux = ?1", [1i32]) {
573    ///         Ok(updated) => println!("{} rows were updated", updated),
574    ///         Err(err) => println!("update failed: {}", err),
575    ///     }
576    /// }
577    /// ```
578    ///
579    /// ### With positional params of varying types
580    ///
581    /// ```rust,no_run
582    /// # use rusqlite::{params, Connection};
583    /// fn update_rows(conn: &Connection) {
584    ///     match conn.execute(
585    ///         "UPDATE foo SET bar = 'baz' WHERE qux = ?1 AND quux = ?2",
586    ///         params![1i32, 1.5f64],
587    ///     ) {
588    ///         Ok(updated) => println!("{} rows were updated", updated),
589    ///         Err(err) => println!("update failed: {}", err),
590    ///     }
591    /// }
592    /// ```
593    ///
594    /// ### With named params
595    ///
596    /// ```rust,no_run
597    /// # use rusqlite::{Connection, Result};
598    /// fn insert(conn: &Connection) -> Result<usize> {
599    ///     conn.execute(
600    ///         "INSERT INTO test (name) VALUES (:name)",
601    ///         &[(":name", "one")],
602    ///     )
603    /// }
604    /// ```
605    ///
606    /// # Failure
607    ///
608    /// Will return `Err` if `sql` cannot be converted to a C-compatible string
609    /// or if the underlying SQLite call fails.
610    #[inline]
611    pub fn execute<P: Params>(&self, sql: &str, params: P) -> Result<usize> {
612        self.prepare(sql).and_then(|mut stmt| stmt.execute(params))
613    }
614
615    /// Returns the path to the database file, if one exists and is known.
616    ///
617    /// Returns `Some("")` for a temporary or in-memory database.
618    ///
619    /// Note that in some cases [PRAGMA
620    /// database_list](https://sqlite.org/pragma.html#pragma_database_list) is
621    /// likely to be more robust.
622    #[inline]
623    pub fn path(&self) -> Option<&str> {
624        unsafe { inner_connection::db_filename(std::marker::PhantomData, self.handle(), MAIN_DB) }
625    }
626
627    /// Attempts to free as much heap memory as possible from the database
628    /// connection.
629    ///
630    /// This calls [`sqlite3_db_release_memory`](https://www.sqlite.org/c3ref/db_release_memory.html).
631    #[inline]
632    pub fn release_memory(&self) -> Result<()> {
633        self.db.borrow_mut().release_memory()
634    }
635
636    /// Get the SQLite rowid of the most recent successful INSERT.
637    ///
638    /// Uses [sqlite3_last_insert_rowid](https://www.sqlite.org/c3ref/last_insert_rowid.html) under
639    /// the hood.
640    #[inline]
641    pub fn last_insert_rowid(&self) -> i64 {
642        self.db.borrow_mut().last_insert_rowid()
643    }
644
645    /// Convenience method to execute a query that is expected to return a
646    /// single row.
647    ///
648    /// ## Example
649    ///
650    /// ```rust,no_run
651    /// # use rusqlite::{Result, Connection};
652    /// fn preferred_locale(conn: &Connection) -> Result<String> {
653    ///     conn.query_row(
654    ///         "SELECT value FROM preferences WHERE name='locale'",
655    ///         [],
656    ///         |row| row.get(0),
657    ///     )
658    /// }
659    /// ```
660    ///
661    /// If the query returns more than one row, all rows except the first are
662    /// ignored.
663    ///
664    /// Returns `Err(QueryReturnedNoRows)` if no results are returned. If the
665    /// query truly is optional, you can call `.optional()` on the result of
666    /// this to get a `Result<Option<T>>`.
667    ///
668    /// # Failure
669    ///
670    /// Will return `Err` if `sql` cannot be converted to a C-compatible string
671    /// or if the underlying SQLite call fails.
672    #[inline]
673    pub fn query_row<T, P, F>(&self, sql: &str, params: P, f: F) -> Result<T>
674    where
675        P: Params,
676        F: FnOnce(&Row<'_>) -> Result<T>,
677    {
678        let mut stmt = self.prepare(sql)?;
679        stmt.query_row(params, f)
680    }
681
682    /// Convenience method to execute a query that is expected to return exactly
683    /// one row.
684    ///
685    /// Returns `Err(QueryReturnedMoreThanOneRow)` if the query returns more than one row.
686    ///
687    /// Returns `Err(QueryReturnedNoRows)` if no results are returned. If the
688    /// query truly is optional, you can call
689    /// [`.optional()`](crate::OptionalExtension::optional) on the result of
690    /// this to get a `Result<Option<T>>` (requires that the trait
691    /// `rusqlite::OptionalExtension` is imported).
692    ///
693    /// # Failure
694    ///
695    /// Will return `Err` if the underlying SQLite call fails.
696    pub fn query_one<T, P, F>(&self, sql: &str, params: P, f: F) -> Result<T>
697    where
698        P: Params,
699        F: FnOnce(&Row<'_>) -> Result<T>,
700    {
701        let mut stmt = self.prepare(sql)?;
702        stmt.query_one(params, f)
703    }
704
705    // https://sqlite.org/tclsqlite.html#onecolumn
706    #[cfg(test)]
707    pub(crate) fn one_column<T, P>(&self, sql: &str, params: P) -> Result<T>
708    where
709        T: types::FromSql,
710        P: Params,
711    {
712        self.query_one(sql, params, |r| r.get(0))
713    }
714
715    /// Convenience method to execute a query that is expected to return a
716    /// single row, and execute a mapping via `f` on that returned row with
717    /// the possibility of failure. The `Result` type of `f` must implement
718    /// `std::convert::From<Error>`.
719    ///
720    /// ## Example
721    ///
722    /// ```rust,no_run
723    /// # use rusqlite::{Result, Connection};
724    /// fn preferred_locale(conn: &Connection) -> Result<String> {
725    ///     conn.query_row_and_then(
726    ///         "SELECT value FROM preferences WHERE name='locale'",
727    ///         [],
728    ///         |row| row.get(0),
729    ///     )
730    /// }
731    /// ```
732    ///
733    /// If the query returns more than one row, all rows except the first are
734    /// ignored.
735    ///
736    /// # Failure
737    ///
738    /// Will return `Err` if `sql` cannot be converted to a C-compatible string
739    /// or if the underlying SQLite call fails.
740    #[inline]
741    pub fn query_row_and_then<T, E, P, F>(&self, sql: &str, params: P, f: F) -> Result<T, E>
742    where
743        P: Params,
744        F: FnOnce(&Row<'_>) -> Result<T, E>,
745        E: From<Error>,
746    {
747        let mut stmt = self.prepare(sql)?;
748        let mut rows = stmt.query(params)?;
749
750        rows.get_expected_row().map_err(E::from).and_then(f)
751    }
752
753    /// Prepare a SQL statement for execution.
754    ///
755    /// ## Example
756    ///
757    /// ```rust,no_run
758    /// # use rusqlite::{Connection, Result};
759    /// fn insert_new_people(conn: &Connection) -> Result<()> {
760    ///     let mut stmt = conn.prepare("INSERT INTO People (name) VALUES (?1)")?;
761    ///     stmt.execute(["Joe Smith"])?;
762    ///     stmt.execute(["Bob Jones"])?;
763    ///     Ok(())
764    /// }
765    /// ```
766    ///
767    /// # Failure
768    ///
769    /// Will return `Err` if `sql` cannot be converted to a C-compatible string
770    /// or if the underlying SQLite call fails.
771    #[inline]
772    pub fn prepare(&self, sql: &str) -> Result<Statement<'_>> {
773        self.prepare_with_flags(sql, PrepFlags::default())
774    }
775
776    /// Prepare a SQL statement for execution.
777    ///
778    /// # Failure
779    ///
780    /// Will return `Err` if `sql` cannot be converted to a C-compatible string
781    /// or if the underlying SQLite call fails.
782    #[inline]
783    pub fn prepare_with_flags(&self, sql: &str, flags: PrepFlags) -> Result<Statement<'_>> {
784        let (stmt, tail) = self.db.borrow_mut().prepare(self, sql, flags)?;
785        if tail != 0 && !self.prepare(&sql[tail..])?.stmt.is_null() {
786            Err(Error::MultipleStatement)
787        } else {
788            Ok(stmt)
789        }
790    }
791
792    /// Close the SQLite connection.
793    ///
794    /// This is functionally equivalent to the `Drop` implementation for
795    /// `Connection` except that on failure, it returns an error and the
796    /// connection itself (presumably so closing can be attempted again).
797    ///
798    /// # Failure
799    ///
800    /// Will return `Err` if the underlying SQLite call fails.
801    #[expect(clippy::result_large_err)]
802    #[inline]
803    pub fn close(self) -> Result<(), (Self, Error)> {
804        #[cfg(feature = "cache")]
805        self.flush_prepared_statement_cache();
806        let r = self.db.borrow_mut().close();
807        r.map_err(move |err| (self, err))
808    }
809
810    /// Enable loading of SQLite extensions from both SQL queries and Rust.
811    ///
812    /// You must call [`Connection::load_extension_disable`] when you're
813    /// finished loading extensions (failure to call it can lead to bad things,
814    /// see "Safety"), so you should strongly consider using
815    /// [`LoadExtensionGuard`] instead of this function, automatically disables
816    /// extension loading when it goes out of scope.
817    ///
818    /// # Example
819    ///
820    /// ```rust,no_run
821    /// # use rusqlite::{Connection, Result};
822    /// fn load_my_extension(conn: &Connection) -> Result<()> {
823    ///     // Safety: We fully trust the loaded extension and execute no untrusted SQL
824    ///     // while extension loading is enabled.
825    ///     unsafe {
826    ///         conn.load_extension_enable()?;
827    ///         let r = conn.load_extension("my/trusted/extension", None::<&str>);
828    ///         conn.load_extension_disable()?;
829    ///         r
830    ///     }
831    /// }
832    /// ```
833    ///
834    /// # Failure
835    ///
836    /// Will return `Err` if the underlying SQLite call fails.
837    ///
838    /// # Safety
839    ///
840    /// TLDR: Don't execute any untrusted queries between this call and
841    /// [`Connection::load_extension_disable`].
842    ///
843    /// Perhaps surprisingly, this function does not only allow the use of
844    /// [`Connection::load_extension`] from Rust, but it also allows SQL queries
845    /// to perform [the same operation][loadext]. For example, in the period
846    /// between `load_extension_enable` and `load_extension_disable`, the
847    /// following operation will load and call some function in some dynamic
848    /// library:
849    ///
850    /// ```sql
851    /// SELECT load_extension('why_is_this_possible.dll', 'dubious_func');
852    /// ```
853    ///
854    /// This means that while this is enabled a carefully crafted SQL query can
855    /// be used to escalate a SQL injection attack into code execution.
856    ///
857    /// Safely using this function requires that you trust all SQL queries run
858    /// between when it is called, and when loading is disabled (by
859    /// [`Connection::load_extension_disable`]).
860    ///
861    /// [loadext]: https://www.sqlite.org/lang_corefunc.html#load_extension
862    #[cfg(feature = "load_extension")]
863    #[inline]
864    pub unsafe fn load_extension_enable(&self) -> Result<()> {
865        self.db.borrow_mut().enable_load_extension(1)
866    }
867
868    /// Disable loading of SQLite extensions.
869    ///
870    /// See [`Connection::load_extension_enable`] for an example.
871    ///
872    /// # Failure
873    ///
874    /// Will return `Err` if the underlying SQLite call fails.
875    #[cfg(feature = "load_extension")]
876    #[inline]
877    pub fn load_extension_disable(&self) -> Result<()> {
878        // It's always safe to turn off extension loading.
879        unsafe { self.db.borrow_mut().enable_load_extension(0) }
880    }
881
882    /// Load the SQLite extension at `dylib_path`. `dylib_path` is passed
883    /// through to `sqlite3_load_extension`, which may attempt OS-specific
884    /// modifications if the file cannot be loaded directly (for example
885    /// converting `"some/ext"` to `"some/ext.so"`, `"some\\ext.dll"`, ...).
886    ///
887    /// If `entry_point` is `None`, SQLite will attempt to find the entry point.
888    /// If it is not `None`, the entry point will be passed through to
889    /// `sqlite3_load_extension`.
890    ///
891    /// ## Example
892    ///
893    /// ```rust,no_run
894    /// # use rusqlite::{Connection, Result, LoadExtensionGuard};
895    /// fn load_my_extension(conn: &Connection) -> Result<()> {
896    ///     // Safety: we don't execute any SQL statements while
897    ///     // extension loading is enabled.
898    ///     let _guard = unsafe { LoadExtensionGuard::new(conn)? };
899    ///     // Safety: `my_sqlite_extension` is highly trustworthy.
900    ///     unsafe { conn.load_extension("my_sqlite_extension", None::<&str>) }
901    /// }
902    /// ```
903    ///
904    /// # Failure
905    ///
906    /// Will return `Err` if the underlying SQLite call fails.
907    ///
908    /// # Safety
909    ///
910    /// This is equivalent to performing a `dlopen`/`LoadLibrary` on a shared
911    /// library, and calling a function inside, and thus requires that you trust
912    /// the library that you're loading.
913    ///
914    /// That is to say: to safely use this, the code in the extension must be
915    /// sound, trusted, correctly use the SQLite APIs, and not contain any
916    /// memory or thread safety errors.
917    #[cfg(feature = "load_extension")]
918    #[inline]
919    pub unsafe fn load_extension<P: AsRef<Path>, N: Name>(
920        &self,
921        dylib_path: P,
922        entry_point: Option<N>,
923    ) -> Result<()> {
924        self.db
925            .borrow_mut()
926            .load_extension(dylib_path.as_ref(), entry_point)
927    }
928
929    /// Get access to the underlying SQLite database connection handle.
930    ///
931    /// # Warning
932    ///
933    /// You should not need to use this function. If you do need to, please
934    /// [open an issue on the rusqlite repository](https://github.com/rusqlite/rusqlite/issues) and describe
935    /// your use case.
936    ///
937    /// # Safety
938    ///
939    /// This function is unsafe because it gives you raw access
940    /// to the SQLite connection, and what you do with it could impact the
941    /// safety of this `Connection`.
942    #[inline]
943    pub unsafe fn handle(&self) -> *mut ffi::sqlite3 {
944        self.db.borrow().db()
945    }
946
947    /// Create a `Connection` from a raw handle.
948    ///
949    /// The underlying SQLite database connection handle will not be closed when
950    /// the returned connection is dropped/closed.
951    ///
952    /// # Safety
953    ///
954    /// This function is unsafe because improper use may impact the Connection.
955    #[inline]
956    pub unsafe fn from_handle(db: *mut ffi::sqlite3) -> Result<Self> {
957        let db = InnerConnection::new(db, false);
958        Ok(Self {
959            db: RefCell::new(db),
960            #[cfg(feature = "cache")]
961            cache: StatementCache::with_capacity(STATEMENT_CACHE_DEFAULT_CAPACITY),
962            transaction_behavior: TransactionBehavior::Deferred,
963        })
964    }
965
966    /// Helper to register an SQLite extension written in Rust.
967    /// For [persistent](https://sqlite.org/loadext.html#persistent_loadable_extensions) extension,
968    /// `init` should return `Ok(true)`.
969    /// # Safety
970    /// * Results are undefined if `init` does not just register features.
971    #[cfg(feature = "loadable_extension")]
972    pub unsafe fn extension_init2(
973        db: *mut ffi::sqlite3,
974        pz_err_msg: *mut *mut c_char,
975        p_api: *mut ffi::sqlite3_api_routines,
976        init: fn(Self) -> Result<bool>,
977    ) -> c_int {
978        if p_api.is_null() {
979            return ffi::SQLITE_ERROR;
980        }
981        match ffi::rusqlite_extension_init2(p_api)
982            .map_err(Error::from)
983            .and(Self::from_handle(db))
984            .and_then(init)
985        {
986            Err(err) => to_sqlite_error(&err, pz_err_msg),
987            Ok(true) => ffi::SQLITE_OK_LOAD_PERMANENTLY,
988            _ => ffi::SQLITE_OK,
989        }
990    }
991
992    /// Create a `Connection` from a raw owned handle.
993    ///
994    /// The returned connection will attempt to close the inner connection
995    /// when dropped/closed. This function should only be called on connections
996    /// owned by the caller.
997    ///
998    /// # Safety
999    ///
1000    /// This function is unsafe because improper use may impact the Connection.
1001    /// In particular, it should only be called on connections created
1002    /// and owned by the caller, e.g. as a result of calling
1003    /// `ffi::sqlite3_open`().
1004    #[inline]
1005    pub unsafe fn from_handle_owned(db: *mut ffi::sqlite3) -> Result<Self> {
1006        let db = InnerConnection::new(db, true);
1007        Ok(Self {
1008            db: RefCell::new(db),
1009            #[cfg(feature = "cache")]
1010            cache: StatementCache::with_capacity(STATEMENT_CACHE_DEFAULT_CAPACITY),
1011            transaction_behavior: TransactionBehavior::Deferred,
1012        })
1013    }
1014
1015    /// Get access to a handle that can be used to interrupt long-running
1016    /// queries from another thread.
1017    #[inline]
1018    pub fn get_interrupt_handle(&self) -> InterruptHandle {
1019        self.db.borrow().get_interrupt_handle()
1020    }
1021
1022    #[inline]
1023    fn decode_result(&self, code: c_int) -> Result<()> {
1024        self.db.borrow().decode_result(code)
1025    }
1026
1027    /// Return the number of rows modified, inserted or deleted by the most
1028    /// recently completed INSERT, UPDATE or DELETE statement on the database
1029    /// connection.
1030    ///
1031    /// See <https://www.sqlite.org/c3ref/changes.html>
1032    #[inline]
1033    pub fn changes(&self) -> u64 {
1034        self.db.borrow().changes()
1035    }
1036
1037    /// Return the total number of rows modified, inserted or deleted by all
1038    /// completed INSERT, UPDATE or DELETE statements since the database
1039    /// connection was opened, including those executed as part of trigger programs.
1040    ///
1041    /// See <https://www.sqlite.org/c3ref/total_changes.html>
1042    #[inline]
1043    pub fn total_changes(&self) -> u64 {
1044        self.db.borrow().total_changes()
1045    }
1046
1047    /// Test for auto-commit mode.
1048    /// Autocommit mode is on by default.
1049    #[inline]
1050    pub fn is_autocommit(&self) -> bool {
1051        self.db.borrow().is_autocommit()
1052    }
1053
1054    /// Determine if all associated prepared statements have been reset.
1055    #[inline]
1056    pub fn is_busy(&self) -> bool {
1057        self.db.borrow().is_busy()
1058    }
1059
1060    /// Flush caches to disk mid-transaction
1061    pub fn cache_flush(&self) -> Result<()> {
1062        self.db.borrow_mut().cache_flush()
1063    }
1064
1065    /// Determine if a database is read-only
1066    pub fn is_readonly<N: Name>(&self, db_name: N) -> Result<bool> {
1067        self.db.borrow().db_readonly(db_name)
1068    }
1069
1070    /// Return the schema name for a database connection
1071    ///
1072    /// ## Failure
1073    ///
1074    /// Return an `Error::InvalidDatabaseIndex` if `index` is out of range.
1075    #[cfg(feature = "modern_sqlite")] // 3.39.0
1076    pub fn db_name(&self, index: usize) -> Result<String> {
1077        unsafe {
1078            let db = self.handle();
1079            let name = ffi::sqlite3_db_name(db, index as c_int);
1080            if name.is_null() {
1081                Err(Error::InvalidDatabaseIndex(index))
1082            } else {
1083                Ok(CStr::from_ptr(name).to_str()?.to_owned())
1084            }
1085        }
1086    }
1087
1088    /// Determine whether an interrupt is currently in effect
1089    #[cfg(feature = "modern_sqlite")] // 3.41.0
1090    pub fn is_interrupted(&self) -> bool {
1091        self.db.borrow().is_interrupted()
1092    }
1093}
1094
1095impl fmt::Debug for Connection {
1096    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1097        f.debug_struct("Connection")
1098            .field("path", &self.path())
1099            .finish()
1100    }
1101}
1102
1103/// Batch fallible iterator
1104///
1105/// # Warning
1106///
1107/// There is no recovery on parsing error, when an invalid statement is found in `sql`, SQLite cannot jump to the next statement.
1108/// So you should break the loop when an error is raised by the `next` method.
1109///
1110/// ```rust
1111/// use fallible_iterator::FallibleIterator;
1112/// use rusqlite::{Batch, Connection, Result};
1113///
1114/// fn main() -> Result<()> {
1115///     let conn = Connection::open_in_memory()?;
1116///     let sql = r"
1117///     CREATE TABLE tbl1 (col);
1118///     CREATE TABLE tbl2 (col);
1119///     ";
1120///     let mut batch = Batch::new(&conn, sql);
1121///     while let Some(mut stmt) = batch.next()? {
1122///         stmt.execute([])?;
1123///     }
1124///     Ok(())
1125/// }
1126/// ```
1127#[derive(Debug)]
1128pub struct Batch<'conn, 'sql> {
1129    conn: &'conn Connection,
1130    sql: &'sql str,
1131    tail: usize,
1132}
1133
1134impl<'conn, 'sql> Batch<'conn, 'sql> {
1135    /// Constructor
1136    pub fn new(conn: &'conn Connection, sql: &'sql str) -> Self {
1137        Batch { conn, sql, tail: 0 }
1138    }
1139}
1140impl<'conn> fallible_iterator::FallibleIterator for Batch<'conn, '_> {
1141    type Item = Statement<'conn>;
1142    type Error = Error;
1143
1144    /// Iterates on each batch statements.
1145    ///
1146    /// Returns `Ok(None)` when batch is completed.
1147    fn next(&mut self) -> Result<Option<Statement<'conn>>> {
1148        while self.tail < self.sql.len() {
1149            let sql = &self.sql[self.tail..];
1150            let (next, tail) =
1151                self.conn
1152                    .db
1153                    .borrow_mut()
1154                    .prepare(self.conn, sql, PrepFlags::default())?;
1155            if tail == 0 {
1156                self.tail = self.sql.len();
1157            } else {
1158                self.tail += tail;
1159            }
1160            if next.stmt.is_null() {
1161                continue;
1162            }
1163            return Ok(Some(next));
1164        }
1165        Ok(None)
1166    }
1167}
1168
1169bitflags::bitflags! {
1170    /// Flags for opening SQLite database connections. See
1171    /// [sqlite3_open_v2](https://www.sqlite.org/c3ref/open.html) for details.
1172    ///
1173    /// The default open flags are `SQLITE_OPEN_READ_WRITE | SQLITE_OPEN_CREATE
1174    /// | SQLITE_OPEN_URI | SQLITE_OPEN_NO_MUTEX`. See [`Connection::open`] for
1175    /// some discussion about these flags.
1176    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1177    #[repr(C)]
1178    pub struct OpenFlags: c_int {
1179        /// The database is opened in read-only mode.
1180        /// If the database does not already exist, an error is returned.
1181        const SQLITE_OPEN_READ_ONLY = ffi::SQLITE_OPEN_READONLY;
1182        /// The database is opened for reading and writing if possible,
1183        /// or reading only if the file is write-protected by the operating system.
1184        /// In either case the database must already exist, otherwise an error is returned.
1185        const SQLITE_OPEN_READ_WRITE = ffi::SQLITE_OPEN_READWRITE;
1186        /// The database is created if it does not already exist
1187        const SQLITE_OPEN_CREATE = ffi::SQLITE_OPEN_CREATE;
1188        /// The filename can be interpreted as a URI if this flag is set.
1189        const SQLITE_OPEN_URI = ffi::SQLITE_OPEN_URI;
1190        /// The database will be opened as an in-memory database.
1191        const SQLITE_OPEN_MEMORY = ffi::SQLITE_OPEN_MEMORY;
1192        /// The new database connection will not use a per-connection mutex (the
1193        /// connection will use the "multi-thread" threading mode, in SQLite
1194        /// parlance).
1195        ///
1196        /// This is used by default, as proper `Send`/`Sync` usage (in
1197        /// particular, the fact that [`Connection`] does not implement `Sync`)
1198        /// ensures thread-safety without the need to perform locking around all
1199        /// calls.
1200        const SQLITE_OPEN_NO_MUTEX = ffi::SQLITE_OPEN_NOMUTEX;
1201        /// The new database connection will use a per-connection mutex -- the
1202        /// "serialized" threading mode, in SQLite parlance.
1203        ///
1204        /// # Caveats
1205        ///
1206        /// This flag should probably never be used with `rusqlite`, as we
1207        /// ensure thread-safety statically (we implement [`Send`] and not
1208        /// [`Sync`]).
1209        ///
1210        /// Critically, even if this flag is used, the [`Connection`] is not
1211        /// safe to use across multiple threads simultaneously. To access a
1212        /// database from multiple threads, you should either create multiple
1213        /// connections, one for each thread (if you have very many threads,
1214        /// wrapping the `rusqlite::Connection` in a mutex is also reasonable).
1215        ///
1216        /// This is both because of the additional per-connection state stored
1217        /// by `rusqlite` (for example, the prepared statement cache), and
1218        /// because not all of SQLites functions are fully thread safe, even in
1219        /// serialized/`SQLITE_OPEN_FULLMUTEX` mode.
1220        ///
1221        /// All that said, it's fairly harmless to enable this flag with
1222        /// `rusqlite`, it will just slow things down while providing no
1223        /// benefit.
1224        const SQLITE_OPEN_FULL_MUTEX = ffi::SQLITE_OPEN_FULLMUTEX;
1225        /// The database is opened with shared cache enabled.
1226        ///
1227        /// This is frequently useful for in-memory connections, but note that
1228        /// broadly speaking it's discouraged by SQLite itself, which states
1229        /// "Any use of shared cache is discouraged" in the official
1230        /// [documentation](https://www.sqlite.org/c3ref/enable_shared_cache.html).
1231        const SQLITE_OPEN_SHARED_CACHE = 0x0002_0000;
1232        /// The database is opened shared cache disabled.
1233        const SQLITE_OPEN_PRIVATE_CACHE = 0x0004_0000;
1234        /// The database filename is not allowed to be a symbolic link. (3.31.0)
1235        const SQLITE_OPEN_NOFOLLOW = 0x0100_0000;
1236        /// Extended result codes. (3.37.0)
1237        const SQLITE_OPEN_EXRESCODE = 0x0200_0000;
1238    }
1239}
1240
1241impl Default for OpenFlags {
1242    #[inline]
1243    fn default() -> Self {
1244        // Note: update the `Connection::open` and top-level `OpenFlags` docs if
1245        // you change these.
1246        Self::SQLITE_OPEN_READ_WRITE
1247            | Self::SQLITE_OPEN_CREATE
1248            | Self::SQLITE_OPEN_NO_MUTEX
1249            | Self::SQLITE_OPEN_URI
1250    }
1251}
1252
1253bitflags::bitflags! {
1254    /// Prepare flags. See
1255    /// [sqlite3_prepare_v3](https://sqlite.org/c3ref/c_prepare_dont_log.html) for details.
1256    #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
1257    #[repr(C)]
1258    pub struct PrepFlags: c_uint {
1259        /// A hint to the query planner that the prepared statement will be retained for a long time and probably reused many times.
1260        const SQLITE_PREPARE_PERSISTENT = 0x01;
1261        /// Causes the SQL compiler to return an error (error code SQLITE_ERROR) if the statement uses any virtual tables.
1262        const SQLITE_PREPARE_NO_VTAB = 0x04;
1263        /// Prevents SQL compiler errors from being sent to the error log.
1264        const SQLITE_PREPARE_DONT_LOG = 0x10;
1265    }
1266}
1267
1268/// Allows interrupting a long-running computation.
1269pub struct InterruptHandle {
1270    db_lock: Arc<Mutex<*mut ffi::sqlite3>>,
1271}
1272
1273unsafe impl Send for InterruptHandle {}
1274unsafe impl Sync for InterruptHandle {}
1275
1276impl InterruptHandle {
1277    /// Interrupt the query currently executing on another thread. This will
1278    /// cause that query to fail with a `SQLITE3_INTERRUPT` error.
1279    pub fn interrupt(&self) {
1280        let db_handle = self.db_lock.lock().unwrap();
1281        if !db_handle.is_null() {
1282            unsafe { ffi::sqlite3_interrupt(*db_handle) }
1283        }
1284    }
1285}
1286
1287#[cfg(doctest)]
1288doc_comment::doctest!("../README.md");
1289
1290#[cfg(test)]
1291mod test {
1292    #[cfg(all(target_family = "wasm", target_os = "unknown"))]
1293    use wasm_bindgen_test::wasm_bindgen_test as test;
1294
1295    use super::*;
1296    use fallible_iterator::FallibleIterator;
1297    use std::error::Error as StdError;
1298    use std::fmt;
1299
1300    // this function is never called, but is still type checked; in
1301    // particular, calls with specific instantiations will require
1302    // that those types are `Send`.
1303    #[allow(dead_code)]
1304    #[expect(unconditional_recursion, clippy::extra_unused_type_parameters)]
1305    fn ensure_send<T: Send>() {
1306        ensure_send::<Connection>();
1307        ensure_send::<InterruptHandle>();
1308    }
1309
1310    #[allow(dead_code)]
1311    #[expect(unconditional_recursion, clippy::extra_unused_type_parameters)]
1312    fn ensure_sync<T: Sync>() {
1313        ensure_sync::<InterruptHandle>();
1314    }
1315
1316    fn checked_memory_handle() -> Connection {
1317        Connection::open_in_memory().unwrap()
1318    }
1319
1320    #[cfg_attr(
1321        all(target_family = "wasm", target_os = "unknown"),
1322        ignore = "no filesystem on this platform"
1323    )]
1324    #[test]
1325    fn test_concurrent_transactions_busy_commit() -> Result<()> {
1326        use std::time::Duration;
1327        let tmp = tempfile::tempdir().unwrap();
1328        let path = tmp.path().join("transactions.db3");
1329
1330        Connection::open(&path)?.execute_batch(
1331            "
1332            BEGIN; CREATE TABLE foo(x INTEGER);
1333            INSERT INTO foo VALUES(42); END;",
1334        )?;
1335
1336        let mut db1 = Connection::open_with_flags(&path, OpenFlags::SQLITE_OPEN_READ_WRITE)?;
1337        let mut db2 = Connection::open_with_flags(&path, OpenFlags::SQLITE_OPEN_READ_ONLY)?;
1338
1339        db1.busy_timeout(Duration::from_millis(0))?;
1340        db2.busy_timeout(Duration::from_millis(0))?;
1341
1342        {
1343            let tx1 = db1.transaction()?;
1344            let tx2 = db2.transaction()?;
1345
1346            // SELECT first makes sqlite lock with a shared lock
1347            tx1.query_row("SELECT x FROM foo LIMIT 1", [], |_| Ok(()))?;
1348            tx2.query_row("SELECT x FROM foo LIMIT 1", [], |_| Ok(()))?;
1349
1350            tx1.execute("INSERT INTO foo VALUES(?1)", [1])?;
1351            let _ = tx2.execute("INSERT INTO foo VALUES(?1)", [2]);
1352
1353            let _ = tx1.commit();
1354            let _ = tx2.commit();
1355        }
1356
1357        let _ = db1
1358            .transaction()
1359            .expect("commit should have closed transaction");
1360        let _ = db2
1361            .transaction()
1362            .expect("commit should have closed transaction");
1363        Ok(())
1364    }
1365
1366    #[cfg_attr(
1367        all(target_family = "wasm", target_os = "unknown"),
1368        ignore = "no filesystem on this platform"
1369    )]
1370    #[test]
1371    fn test_persistence() -> Result<()> {
1372        let temp_dir = tempfile::tempdir().unwrap();
1373        let path = temp_dir.path().join("test.db3");
1374
1375        {
1376            let db = Connection::open(&path)?;
1377            let sql = "BEGIN;
1378                   CREATE TABLE foo(x INTEGER);
1379                   INSERT INTO foo VALUES(42);
1380                   END;";
1381            db.execute_batch(sql)?;
1382        }
1383
1384        let path_string = path.to_str().unwrap();
1385        let db = Connection::open(path_string)?;
1386
1387        assert_eq!(42, db.one_column::<i64, _>("SELECT x FROM foo", [])?);
1388        Ok(())
1389    }
1390
1391    #[test]
1392    fn test_open() {
1393        Connection::open_in_memory().unwrap();
1394
1395        let db = checked_memory_handle();
1396        db.close().unwrap();
1397    }
1398
1399    #[cfg_attr(
1400        all(target_family = "wasm", target_os = "unknown"),
1401        ignore = "no filesystem on this platform"
1402    )]
1403    #[test]
1404    fn test_path() -> Result<()> {
1405        let tmp = tempfile::tempdir().unwrap();
1406        let db = Connection::open("")?;
1407        assert_eq!(Some(""), db.path());
1408        let db = Connection::open_in_memory()?;
1409        assert_eq!(Some(""), db.path());
1410        let db = Connection::open("file:dummy.db?mode=memory&cache=shared")?;
1411        assert_eq!(Some(""), db.path());
1412        let path = tmp.path().join("file.db");
1413        let db = Connection::open(path)?;
1414        assert!(db.path().is_some_and(|p| p.ends_with("file.db")));
1415        Ok(())
1416    }
1417
1418    #[test]
1419    fn test_open_failure() {
1420        let filename = "no_such_file.db";
1421        let result = Connection::open_with_flags(filename, OpenFlags::SQLITE_OPEN_READ_ONLY);
1422        let err = result.unwrap_err();
1423        if let Error::SqliteFailure(e, Some(msg)) = err {
1424            assert_eq!(ErrorCode::CannotOpen, e.code);
1425            assert_eq!(ffi::SQLITE_CANTOPEN, e.extended_code);
1426            assert!(
1427                msg.contains(filename),
1428                "error message '{msg}' does not contain '{filename}'"
1429            );
1430        } else {
1431            panic!("SqliteFailure expected");
1432        }
1433    }
1434
1435    #[cfg(unix)]
1436    #[test]
1437    fn test_invalid_unicode_file_names() -> Result<()> {
1438        use std::ffi::OsStr;
1439        use std::fs::File;
1440        use std::os::unix::ffi::OsStrExt;
1441        let temp_dir = tempfile::tempdir().unwrap();
1442
1443        let path = temp_dir.path();
1444        if File::create(path.join(OsStr::from_bytes(&[0xFE]))).is_err() {
1445            // Skip test, filesystem doesn't support invalid Unicode
1446            return Ok(());
1447        }
1448        let db_path = path.join(OsStr::from_bytes(&[0xFF]));
1449        {
1450            let db = Connection::open(&db_path)?;
1451            let sql = "BEGIN;
1452                   CREATE TABLE foo(x INTEGER);
1453                   INSERT INTO foo VALUES(42);
1454                   END;";
1455            db.execute_batch(sql)?;
1456        }
1457
1458        let db = Connection::open(&db_path)?;
1459
1460        assert_eq!(42, db.one_column::<i64, _>("SELECT x FROM foo", [])?);
1461        Ok(())
1462    }
1463
1464    #[test]
1465    fn test_close_retry() -> Result<()> {
1466        let db = Connection::open_in_memory()?;
1467
1468        // force the DB to be busy by preparing a statement; this must be done at the
1469        // FFI level to allow us to call .close() without dropping the prepared
1470        // statement first.
1471        let raw_stmt = {
1472            use super::str_to_cstring;
1473            use std::ffi::c_int;
1474            use std::ptr;
1475
1476            let raw_db = db.db.borrow_mut().db;
1477            let sql = "SELECT 1";
1478            let mut raw_stmt: *mut ffi::sqlite3_stmt = ptr::null_mut();
1479            let cstring = str_to_cstring(sql)?;
1480            let rc = unsafe {
1481                ffi::sqlite3_prepare_v2(
1482                    raw_db,
1483                    cstring.as_ptr(),
1484                    (sql.len() + 1) as c_int,
1485                    &mut raw_stmt,
1486                    ptr::null_mut(),
1487                )
1488            };
1489            assert_eq!(rc, ffi::SQLITE_OK);
1490            raw_stmt
1491        };
1492
1493        // now that we have an open statement, trying (and retrying) to close should
1494        // fail.
1495        let (db, _) = db.close().unwrap_err();
1496        let (db, _) = db.close().unwrap_err();
1497        let (db, _) = db.close().unwrap_err();
1498
1499        // finalize the open statement so a final close will succeed
1500        assert_eq!(ffi::SQLITE_OK, unsafe { ffi::sqlite3_finalize(raw_stmt) });
1501
1502        db.close().unwrap();
1503        Ok(())
1504    }
1505
1506    #[test]
1507    fn test_open_with_flags() {
1508        for bad_flags in &[
1509            OpenFlags::empty(),
1510            OpenFlags::SQLITE_OPEN_READ_ONLY | OpenFlags::SQLITE_OPEN_READ_WRITE,
1511            OpenFlags::SQLITE_OPEN_READ_ONLY | OpenFlags::SQLITE_OPEN_CREATE,
1512        ] {
1513            Connection::open_in_memory_with_flags(*bad_flags).unwrap_err();
1514        }
1515    }
1516
1517    #[test]
1518    fn test_execute_batch() -> Result<()> {
1519        let db = Connection::open_in_memory()?;
1520        let sql = "BEGIN;
1521                   CREATE TABLE foo(x INTEGER);
1522                   INSERT INTO foo VALUES(1);
1523                   INSERT INTO foo VALUES(2);
1524                   INSERT INTO foo VALUES(3);
1525                   INSERT INTO foo VALUES(4);
1526                   END;";
1527        db.execute_batch(sql)?;
1528
1529        db.execute_batch("UPDATE foo SET x = 3 WHERE x < 3")?;
1530
1531        db.execute_batch("INVALID SQL").unwrap_err();
1532
1533        db.execute_batch("PRAGMA locking_mode = EXCLUSIVE")?;
1534        Ok(())
1535    }
1536
1537    #[test]
1538    fn test_execute() -> Result<()> {
1539        let db = Connection::open_in_memory()?;
1540        db.execute_batch("CREATE TABLE foo(x INTEGER)")?;
1541
1542        assert_eq!(1, db.execute("INSERT INTO foo(x) VALUES (?1)", [1i32])?);
1543        assert_eq!(1, db.execute("INSERT INTO foo(x) VALUES (?1)", [2i32])?);
1544
1545        assert_eq!(3, db.one_column::<i32, _>("SELECT SUM(x) FROM foo", [])?);
1546        Ok(())
1547    }
1548
1549    #[test]
1550    #[cfg(feature = "extra_check")]
1551    fn test_execute_select_with_no_row() {
1552        let db = checked_memory_handle();
1553        let err = db.execute("SELECT 1 WHERE 1 < ?1", [1i32]).unwrap_err();
1554        assert_eq!(
1555            err,
1556            Error::ExecuteReturnedResults,
1557            "Unexpected error: {err}"
1558        );
1559    }
1560
1561    #[test]
1562    fn test_execute_select_with_row() {
1563        let db = checked_memory_handle();
1564        let err = db.execute("SELECT 1", []).unwrap_err();
1565        assert_eq!(err, Error::ExecuteReturnedResults);
1566    }
1567
1568    #[test]
1569    fn test_execute_multiple() {
1570        let db = checked_memory_handle();
1571        let err = db
1572            .execute(
1573                "CREATE TABLE foo(x INTEGER); CREATE TABLE foo(x INTEGER)",
1574                [],
1575            )
1576            .unwrap_err();
1577        match err {
1578            Error::MultipleStatement => (),
1579            _ => panic!("Unexpected error: {err}"),
1580        }
1581        db.execute("CREATE TABLE t(c); -- bim", [])
1582            .expect("Tail comment should be ignored");
1583    }
1584
1585    #[test]
1586    fn test_prepare_column_names() -> Result<()> {
1587        let db = Connection::open_in_memory()?;
1588        db.execute_batch("CREATE TABLE foo(x INTEGER);")?;
1589
1590        let stmt = db.prepare("SELECT * FROM foo")?;
1591        assert_eq!(stmt.column_count(), 1);
1592        assert_eq!(stmt.column_names(), vec!["x"]);
1593
1594        let stmt = db.prepare("SELECT x AS a, x AS b FROM foo")?;
1595        assert_eq!(stmt.column_count(), 2);
1596        assert_eq!(stmt.column_names(), vec!["a", "b"]);
1597        Ok(())
1598    }
1599
1600    #[test]
1601    fn test_prepare_execute() -> Result<()> {
1602        let db = Connection::open_in_memory()?;
1603        db.execute_batch("CREATE TABLE foo(x INTEGER);")?;
1604
1605        let mut insert_stmt = db.prepare("INSERT INTO foo(x) VALUES(?1)")?;
1606        assert_eq!(insert_stmt.execute([1i32])?, 1);
1607        assert_eq!(insert_stmt.execute([2i32])?, 1);
1608        assert_eq!(insert_stmt.execute([3i32])?, 1);
1609
1610        assert_eq!(insert_stmt.execute(["hello"])?, 1);
1611        assert_eq!(insert_stmt.execute(["goodbye"])?, 1);
1612        assert_eq!(insert_stmt.execute([types::Null])?, 1);
1613
1614        let mut update_stmt = db.prepare("UPDATE foo SET x=?1 WHERE x<?2")?;
1615        assert_eq!(update_stmt.execute([3i32, 3i32])?, 2);
1616        assert_eq!(update_stmt.execute([3i32, 3i32])?, 0);
1617        assert_eq!(update_stmt.execute([8i32, 8i32])?, 3);
1618        Ok(())
1619    }
1620
1621    #[test]
1622    fn test_prepare_query() -> Result<()> {
1623        let db = Connection::open_in_memory()?;
1624        db.execute_batch("CREATE TABLE foo(x INTEGER);")?;
1625
1626        let mut insert_stmt = db.prepare("INSERT INTO foo(x) VALUES(?1)")?;
1627        assert_eq!(insert_stmt.execute([1i32])?, 1);
1628        assert_eq!(insert_stmt.execute([2i32])?, 1);
1629        assert_eq!(insert_stmt.execute([3i32])?, 1);
1630
1631        let mut query = db.prepare("SELECT x FROM foo WHERE x < ?1 ORDER BY x DESC")?;
1632        {
1633            let mut rows = query.query([4i32])?;
1634            let mut v = Vec::<i32>::new();
1635
1636            while let Some(row) = rows.next()? {
1637                v.push(row.get(0)?);
1638            }
1639
1640            assert_eq!(v, [3i32, 2, 1]);
1641        }
1642
1643        {
1644            let mut rows = query.query([3i32])?;
1645            let mut v = Vec::<i32>::new();
1646
1647            while let Some(row) = rows.next()? {
1648                v.push(row.get(0)?);
1649            }
1650
1651            assert_eq!(v, [2i32, 1]);
1652        }
1653        Ok(())
1654    }
1655
1656    #[test]
1657    fn test_query_map() -> Result<()> {
1658        let db = Connection::open_in_memory()?;
1659        let sql = "BEGIN;
1660                   CREATE TABLE foo(x INTEGER, y TEXT);
1661                   INSERT INTO foo VALUES(4, \"hello\");
1662                   INSERT INTO foo VALUES(3, \", \");
1663                   INSERT INTO foo VALUES(2, \"world\");
1664                   INSERT INTO foo VALUES(1, \"!\");
1665                   END;";
1666        db.execute_batch(sql)?;
1667
1668        let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC")?;
1669        let results: Result<Vec<String>> = query.query([])?.map(|row| row.get(1)).collect();
1670
1671        assert_eq!(results?.concat(), "hello, world!");
1672        Ok(())
1673    }
1674
1675    #[test]
1676    fn test_query_row() -> Result<()> {
1677        let db = Connection::open_in_memory()?;
1678        let sql = "BEGIN;
1679                   CREATE TABLE foo(x INTEGER);
1680                   INSERT INTO foo VALUES(1);
1681                   INSERT INTO foo VALUES(2);
1682                   INSERT INTO foo VALUES(3);
1683                   INSERT INTO foo VALUES(4);
1684                   END;";
1685        db.execute_batch(sql)?;
1686
1687        assert_eq!(10, db.one_column::<i64, _>("SELECT SUM(x) FROM foo", [])?);
1688
1689        let result: Result<i64> = db.one_column("SELECT x FROM foo WHERE x > 5", []);
1690        match result.unwrap_err() {
1691            Error::QueryReturnedNoRows => (),
1692            err => panic!("Unexpected error {err}"),
1693        }
1694
1695        db.query_row("NOT A PROPER QUERY; test123", [], |_| Ok(()))
1696            .unwrap_err();
1697
1698        db.query_row("SELECT 1; SELECT 2;", [], |_| Ok(()))
1699            .unwrap_err();
1700
1701        Ok(())
1702    }
1703
1704    #[test]
1705    fn test_optional() -> Result<()> {
1706        let db = Connection::open_in_memory()?;
1707
1708        let result: Result<i64> = db.one_column("SELECT 1 WHERE 0 <> 0", []);
1709        let result = result.optional();
1710        match result? {
1711            None => (),
1712            _ => panic!("Unexpected result"),
1713        }
1714
1715        let result: Result<i64> = db.one_column("SELECT 1 WHERE 0 == 0", []);
1716        let result = result.optional();
1717        match result? {
1718            Some(1) => (),
1719            _ => panic!("Unexpected result"),
1720        }
1721
1722        let bad_query_result: Result<i64> = db.one_column("NOT A PROPER QUERY", []);
1723        let bad_query_result = bad_query_result.optional();
1724        bad_query_result.unwrap_err();
1725        Ok(())
1726    }
1727
1728    #[test]
1729    fn test_pragma_query_row() -> Result<()> {
1730        let db = Connection::open_in_memory()?;
1731        assert_eq!(
1732            "memory",
1733            db.one_column::<String, _>("PRAGMA journal_mode", [])?
1734        );
1735        let mode = db.one_column::<String, _>("PRAGMA journal_mode=off", [])?;
1736        if cfg!(feature = "bundled") {
1737            assert_eq!(mode, "off");
1738        } else {
1739            // Note: system SQLite on macOS defaults to "off" rather than
1740            // "memory" for the journal mode (which cannot be changed for
1741            // in-memory connections). This seems like it's *probably* legal
1742            // according to the docs below, so we relax this test when not
1743            // bundling:
1744            //
1745            // From https://www.sqlite.org/pragma.html#pragma_journal_mode
1746            // > Note that the journal_mode for an in-memory database is either
1747            // > MEMORY or OFF and can not be changed to a different value. An
1748            // > attempt to change the journal_mode of an in-memory database to
1749            // > any setting other than MEMORY or OFF is ignored.
1750            assert!(mode == "memory" || mode == "off", "Got mode {mode:?}");
1751        }
1752
1753        Ok(())
1754    }
1755
1756    #[test]
1757    fn test_prepare_failures() -> Result<()> {
1758        let db = Connection::open_in_memory()?;
1759        db.execute_batch("CREATE TABLE foo(x INTEGER);")?;
1760
1761        let err = db.prepare("SELECT * FROM does_not_exist").unwrap_err();
1762        assert!(format!("{err}").contains("does_not_exist"));
1763        Ok(())
1764    }
1765
1766    #[test]
1767    fn test_last_insert_rowid() -> Result<()> {
1768        let db = Connection::open_in_memory()?;
1769        db.execute_batch("CREATE TABLE foo(x INTEGER PRIMARY KEY)")?;
1770        db.execute_batch("INSERT INTO foo DEFAULT VALUES")?;
1771
1772        assert_eq!(db.last_insert_rowid(), 1);
1773
1774        let mut stmt = db.prepare("INSERT INTO foo DEFAULT VALUES")?;
1775        for _ in 0i32..9 {
1776            stmt.execute([])?;
1777        }
1778        assert_eq!(db.last_insert_rowid(), 10);
1779        Ok(())
1780    }
1781
1782    #[test]
1783    fn test_total_changes() -> Result<()> {
1784        let db = Connection::open_in_memory()?;
1785        let sql = "CREATE TABLE foo(x INTEGER PRIMARY KEY, value TEXT default '' NOT NULL,
1786                                    desc TEXT default '');
1787                   CREATE VIEW foo_bar AS SELECT x, desc FROM foo WHERE value = 'bar';
1788                   CREATE TRIGGER INSERT_FOOBAR
1789                   INSTEAD OF INSERT
1790                   ON foo_bar
1791                   BEGIN
1792                       INSERT INTO foo VALUES(new.x, 'bar', new.desc);
1793                   END;";
1794        db.execute_batch(sql)?;
1795        let total_changes_before = db.total_changes();
1796        let changes = db
1797            .prepare("INSERT INTO foo_bar VALUES(null, 'baz');")?
1798            .execute([])?;
1799        let total_changes_after = db.total_changes();
1800        assert_eq!(changes, 0);
1801        assert_eq!(total_changes_after - total_changes_before, 1);
1802        Ok(())
1803    }
1804
1805    #[test]
1806    fn test_is_autocommit() -> Result<()> {
1807        let db = Connection::open_in_memory()?;
1808        assert!(
1809            db.is_autocommit(),
1810            "autocommit expected to be active by default"
1811        );
1812        Ok(())
1813    }
1814
1815    #[test]
1816    fn test_is_busy() -> Result<()> {
1817        let db = Connection::open_in_memory()?;
1818        assert!(!db.is_busy());
1819        let mut stmt = db.prepare("PRAGMA schema_version")?;
1820        assert!(!db.is_busy());
1821        {
1822            let mut rows = stmt.query([])?;
1823            assert!(!db.is_busy());
1824            let row = rows.next()?;
1825            assert!(db.is_busy());
1826            assert!(row.is_some());
1827        }
1828        assert!(!db.is_busy());
1829        Ok(())
1830    }
1831
1832    #[test]
1833    fn test_statement_debugging() -> Result<()> {
1834        let db = Connection::open_in_memory()?;
1835        let query = "SELECT 12345";
1836        let stmt = db.prepare(query)?;
1837
1838        assert!(format!("{stmt:?}").contains(query));
1839        Ok(())
1840    }
1841
1842    #[test]
1843    fn test_notnull_constraint_error() -> Result<()> {
1844        let db = Connection::open_in_memory()?;
1845        db.execute_batch("CREATE TABLE foo(x NOT NULL)")?;
1846
1847        let result = db.execute("INSERT INTO foo (x) VALUES (NULL)", []);
1848
1849        match result.unwrap_err() {
1850            Error::SqliteFailure(err, _) => {
1851                assert_eq!(err.code, ErrorCode::ConstraintViolation);
1852                assert_eq!(err.extended_code, ffi::SQLITE_CONSTRAINT_NOTNULL);
1853            }
1854            err => panic!("Unexpected error {err}"),
1855        }
1856        Ok(())
1857    }
1858
1859    #[test]
1860    fn test_version_string() {
1861        let n = version_number();
1862        let major = n / 1_000_000;
1863        let minor = (n % 1_000_000) / 1_000;
1864        let patch = n % 1_000;
1865
1866        assert!(version().contains(&format!("{major}.{minor}.{patch}")));
1867    }
1868
1869    #[test]
1870    #[cfg(feature = "functions")]
1871    fn test_interrupt() -> Result<()> {
1872        let db = Connection::open_in_memory()?;
1873
1874        let interrupt_handle = db.get_interrupt_handle();
1875
1876        db.create_scalar_function(
1877            "interrupt",
1878            0,
1879            functions::FunctionFlags::default(),
1880            move |_| {
1881                interrupt_handle.interrupt();
1882                Ok(0)
1883            },
1884        )?;
1885
1886        let mut stmt =
1887            db.prepare("SELECT interrupt() FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3)")?;
1888
1889        let result: Result<Vec<i32>> = stmt.query([])?.map(|r| r.get(0)).collect();
1890
1891        assert_eq!(
1892            result.unwrap_err().sqlite_error_code(),
1893            Some(ErrorCode::OperationInterrupted)
1894        );
1895        Ok(())
1896    }
1897
1898    #[test]
1899    fn test_interrupt_close() {
1900        let db = checked_memory_handle();
1901        let handle = db.get_interrupt_handle();
1902        handle.interrupt();
1903        db.close().unwrap();
1904        handle.interrupt();
1905
1906        // Look at its internals to see if we cleared it out properly.
1907        let db_guard = handle.db_lock.lock().unwrap();
1908        assert!(db_guard.is_null());
1909        // It would be nice to test that we properly handle close/interrupt
1910        // running at the same time, but it seems impossible to do with any
1911        // degree of reliability.
1912    }
1913
1914    #[test]
1915    fn test_get_raw() -> Result<()> {
1916        let db = Connection::open_in_memory()?;
1917        db.execute_batch("CREATE TABLE foo(i, x);")?;
1918        let vals = ["foobar", "1234", "qwerty"];
1919        let mut insert_stmt = db.prepare("INSERT INTO foo(i, x) VALUES(?1, ?2)")?;
1920        for (i, v) in vals.iter().enumerate() {
1921            let i_to_insert = i as i64;
1922            assert_eq!(insert_stmt.execute(params![i_to_insert, v])?, 1);
1923        }
1924
1925        let mut query = db.prepare("SELECT i, x FROM foo")?;
1926        let mut rows = query.query([])?;
1927
1928        while let Some(row) = rows.next()? {
1929            let i = row.get_ref(0)?.as_i64()?;
1930            let expect = vals[i as usize];
1931            let x = row.get_ref("x")?.as_str()?;
1932            assert_eq!(x, expect);
1933        }
1934
1935        let mut query = db.prepare("SELECT x FROM foo")?;
1936        let rows = query.query_map([], |row| {
1937            let x = row.get_ref(0)?.as_str()?; // check From<FromSqlError> for Error
1938            Ok(x[..].to_owned())
1939        })?;
1940
1941        for (i, row) in rows.enumerate() {
1942            assert_eq!(row?, vals[i]);
1943        }
1944        Ok(())
1945    }
1946
1947    #[test]
1948    fn test_from_handle() -> Result<()> {
1949        let db = Connection::open_in_memory()?;
1950        let handle = unsafe { db.handle() };
1951        {
1952            let db = unsafe { Connection::from_handle(handle) }?;
1953            db.execute_batch("PRAGMA VACUUM")?;
1954        }
1955        db.close().unwrap();
1956        Ok(())
1957    }
1958
1959    #[test]
1960    fn test_from_handle_owned() -> Result<()> {
1961        let mut handle: *mut ffi::sqlite3 = std::ptr::null_mut();
1962        let r = unsafe { ffi::sqlite3_open(c":memory:".as_ptr(), &mut handle) };
1963        assert_eq!(r, ffi::SQLITE_OK);
1964        let db = unsafe { Connection::from_handle_owned(handle) }?;
1965        db.execute_batch("PRAGMA VACUUM")?;
1966        Ok(())
1967    }
1968
1969    mod query_and_then_tests {
1970        #[cfg(all(target_family = "wasm", target_os = "unknown"))]
1971        use wasm_bindgen_test::wasm_bindgen_test as test;
1972
1973        use super::*;
1974
1975        #[derive(Debug)]
1976        enum CustomError {
1977            SomeError,
1978            Sqlite(Error),
1979        }
1980
1981        impl fmt::Display for CustomError {
1982            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
1983                match *self {
1984                    Self::SomeError => write!(f, "my custom error"),
1985                    Self::Sqlite(ref se) => write!(f, "my custom error: {se}"),
1986                }
1987            }
1988        }
1989
1990        impl StdError for CustomError {
1991            fn description(&self) -> &str {
1992                "my custom error"
1993            }
1994
1995            fn cause(&self) -> Option<&dyn StdError> {
1996                match *self {
1997                    Self::SomeError => None,
1998                    Self::Sqlite(ref se) => Some(se),
1999                }
2000            }
2001        }
2002
2003        impl From<Error> for CustomError {
2004            fn from(se: Error) -> Self {
2005                Self::Sqlite(se)
2006            }
2007        }
2008
2009        type CustomResult<T> = Result<T, CustomError>;
2010
2011        #[test]
2012        fn test_query_and_then() -> Result<()> {
2013            let db = Connection::open_in_memory()?;
2014            let sql = "BEGIN;
2015                       CREATE TABLE foo(x INTEGER, y TEXT);
2016                       INSERT INTO foo VALUES(4, \"hello\");
2017                       INSERT INTO foo VALUES(3, \", \");
2018                       INSERT INTO foo VALUES(2, \"world\");
2019                       INSERT INTO foo VALUES(1, \"!\");
2020                       END;";
2021            db.execute_batch(sql)?;
2022
2023            let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC")?;
2024            let results: Result<Vec<String>> =
2025                query.query_and_then([], |row| row.get(1))?.collect();
2026
2027            assert_eq!(results?.concat(), "hello, world!");
2028            Ok(())
2029        }
2030
2031        #[test]
2032        fn test_query_and_then_fails() -> Result<()> {
2033            let db = Connection::open_in_memory()?;
2034            let sql = "BEGIN;
2035                       CREATE TABLE foo(x INTEGER, y TEXT);
2036                       INSERT INTO foo VALUES(4, \"hello\");
2037                       INSERT INTO foo VALUES(3, \", \");
2038                       INSERT INTO foo VALUES(2, \"world\");
2039                       INSERT INTO foo VALUES(1, \"!\");
2040                       END;";
2041            db.execute_batch(sql)?;
2042
2043            let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC")?;
2044            let bad_type: Result<Vec<f64>> = query.query_and_then([], |row| row.get(1))?.collect();
2045
2046            match bad_type.unwrap_err() {
2047                Error::InvalidColumnType(..) => (),
2048                err => panic!("Unexpected error {err}"),
2049            }
2050
2051            let bad_idx: Result<Vec<String>> =
2052                query.query_and_then([], |row| row.get(3))?.collect();
2053
2054            match bad_idx.unwrap_err() {
2055                Error::InvalidColumnIndex(_) => (),
2056                err => panic!("Unexpected error {err}"),
2057            }
2058            Ok(())
2059        }
2060
2061        #[test]
2062        fn test_query_and_then_custom_error() -> CustomResult<()> {
2063            let db = Connection::open_in_memory()?;
2064            let sql = "BEGIN;
2065                       CREATE TABLE foo(x INTEGER, y TEXT);
2066                       INSERT INTO foo VALUES(4, \"hello\");
2067                       INSERT INTO foo VALUES(3, \", \");
2068                       INSERT INTO foo VALUES(2, \"world\");
2069                       INSERT INTO foo VALUES(1, \"!\");
2070                       END;";
2071            db.execute_batch(sql)?;
2072
2073            let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC")?;
2074            let results: CustomResult<Vec<String>> = query
2075                .query_and_then([], |row| row.get(1).map_err(CustomError::Sqlite))?
2076                .collect();
2077
2078            assert_eq!(results?.concat(), "hello, world!");
2079            Ok(())
2080        }
2081
2082        #[test]
2083        fn test_query_and_then_custom_error_fails() -> Result<()> {
2084            let db = Connection::open_in_memory()?;
2085            let sql = "BEGIN;
2086                       CREATE TABLE foo(x INTEGER, y TEXT);
2087                       INSERT INTO foo VALUES(4, \"hello\");
2088                       INSERT INTO foo VALUES(3, \", \");
2089                       INSERT INTO foo VALUES(2, \"world\");
2090                       INSERT INTO foo VALUES(1, \"!\");
2091                       END;";
2092            db.execute_batch(sql)?;
2093
2094            let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC")?;
2095            let bad_type: CustomResult<Vec<f64>> = query
2096                .query_and_then([], |row| row.get(1).map_err(CustomError::Sqlite))?
2097                .collect();
2098
2099            match bad_type.unwrap_err() {
2100                CustomError::Sqlite(Error::InvalidColumnType(..)) => (),
2101                err => panic!("Unexpected error {err}"),
2102            }
2103
2104            let bad_idx: CustomResult<Vec<String>> = query
2105                .query_and_then([], |row| row.get(3).map_err(CustomError::Sqlite))?
2106                .collect();
2107
2108            match bad_idx.unwrap_err() {
2109                CustomError::Sqlite(Error::InvalidColumnIndex(_)) => (),
2110                err => panic!("Unexpected error {err}"),
2111            }
2112
2113            let non_sqlite_err: CustomResult<Vec<String>> = query
2114                .query_and_then([], |_| Err(CustomError::SomeError))?
2115                .collect();
2116
2117            match non_sqlite_err.unwrap_err() {
2118                CustomError::SomeError => (),
2119                err => panic!("Unexpected error {err}"),
2120            }
2121            Ok(())
2122        }
2123
2124        #[test]
2125        fn test_query_row_and_then_custom_error() -> CustomResult<()> {
2126            let db = Connection::open_in_memory()?;
2127            let sql = "BEGIN;
2128                       CREATE TABLE foo(x INTEGER, y TEXT);
2129                       INSERT INTO foo VALUES(4, \"hello\");
2130                       END;";
2131            db.execute_batch(sql)?;
2132
2133            let query = "SELECT x, y FROM foo ORDER BY x DESC";
2134            let results: CustomResult<String> =
2135                db.query_row_and_then(query, [], |row| row.get(1).map_err(CustomError::Sqlite));
2136
2137            assert_eq!(results?, "hello");
2138            Ok(())
2139        }
2140
2141        #[test]
2142        fn test_query_row_and_then_custom_error_fails() -> Result<()> {
2143            let db = Connection::open_in_memory()?;
2144            let sql = "BEGIN;
2145                       CREATE TABLE foo(x INTEGER, y TEXT);
2146                       INSERT INTO foo VALUES(4, \"hello\");
2147                       END;";
2148            db.execute_batch(sql)?;
2149
2150            let query = "SELECT x, y FROM foo ORDER BY x DESC";
2151            let bad_type: CustomResult<f64> =
2152                db.query_row_and_then(query, [], |row| row.get(1).map_err(CustomError::Sqlite));
2153
2154            match bad_type.unwrap_err() {
2155                CustomError::Sqlite(Error::InvalidColumnType(..)) => (),
2156                err => panic!("Unexpected error {err}"),
2157            }
2158
2159            let bad_idx: CustomResult<String> =
2160                db.query_row_and_then(query, [], |row| row.get(3).map_err(CustomError::Sqlite));
2161
2162            match bad_idx.unwrap_err() {
2163                CustomError::Sqlite(Error::InvalidColumnIndex(_)) => (),
2164                err => panic!("Unexpected error {err}"),
2165            }
2166
2167            let non_sqlite_err: CustomResult<String> =
2168                db.query_row_and_then(query, [], |_| Err(CustomError::SomeError));
2169
2170            match non_sqlite_err.unwrap_err() {
2171                CustomError::SomeError => (),
2172                err => panic!("Unexpected error {err}"),
2173            }
2174            Ok(())
2175        }
2176    }
2177
2178    #[test]
2179    fn test_dynamic() -> Result<()> {
2180        let db = Connection::open_in_memory()?;
2181        let sql = "BEGIN;
2182                       CREATE TABLE foo(x INTEGER, y TEXT);
2183                       INSERT INTO foo VALUES(4, \"hello\");
2184                       END;";
2185        db.execute_batch(sql)?;
2186
2187        db.query_row("SELECT * FROM foo", [], |r| {
2188            assert_eq!(2, r.as_ref().column_count());
2189            Ok(())
2190        })
2191    }
2192    #[test]
2193    fn test_dyn_box() -> Result<()> {
2194        let db = Connection::open_in_memory()?;
2195        db.execute_batch("CREATE TABLE foo(x INTEGER);")?;
2196        let b: Box<dyn ToSql> = Box::new(5);
2197        db.execute("INSERT INTO foo VALUES(?1)", [b])?;
2198        db.query_row("SELECT x FROM foo", [], |r| {
2199            assert_eq!(5, r.get_unwrap::<_, i32>(0));
2200            Ok(())
2201        })
2202    }
2203
2204    #[test]
2205    fn test_params() -> Result<()> {
2206        let db = Connection::open_in_memory()?;
2207        db.query_row(
2208            "SELECT
2209            ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10,
2210            ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20,
2211            ?21, ?22, ?23, ?24, ?25, ?26, ?27, ?28, ?29, ?30,
2212            ?31, ?32, ?33, ?34;",
2213            params![
2214                1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2215                1, 1, 1, 1, 1, 1,
2216            ],
2217            |r| {
2218                assert_eq!(1, r.get_unwrap::<_, i32>(0));
2219                Ok(())
2220            },
2221        )
2222    }
2223
2224    #[test]
2225    fn test_alter_table() -> Result<()> {
2226        let db = Connection::open_in_memory()?;
2227        db.execute_batch("CREATE TABLE x(t);")?;
2228        // `execute_batch` should be used but `execute` should also work
2229        db.execute("ALTER TABLE x RENAME TO y;", [])?;
2230        Ok(())
2231    }
2232
2233    #[test]
2234    fn test_batch() -> Result<()> {
2235        let db = Connection::open_in_memory()?;
2236        let sql = r"
2237             CREATE TABLE tbl1 (col);
2238             CREATE TABLE tbl2 (col);
2239             ";
2240        let mut batch = Batch::new(&db, sql);
2241        while let Some(mut stmt) = batch.next()? {
2242            stmt.execute([])?;
2243        }
2244        Ok(())
2245    }
2246
2247    #[test]
2248    fn test_invalid_batch() -> Result<()> {
2249        let db = Connection::open_in_memory()?;
2250        let sql = r"
2251            PRAGMA test1;
2252            PRAGMA test2=?;
2253            PRAGMA test3;
2254            ";
2255        let mut batch = Batch::new(&db, sql);
2256        assert!(batch.next().is_ok());
2257        assert!(batch.next().is_err());
2258        assert!(batch.next().is_err());
2259        assert!(Batch::new(&db, sql).count().is_err());
2260        Ok(())
2261    }
2262
2263    #[test]
2264    #[cfg(feature = "modern_sqlite")]
2265    fn test_returning() -> Result<()> {
2266        let db = Connection::open_in_memory()?;
2267        db.execute_batch("CREATE TABLE foo(x INTEGER PRIMARY KEY)")?;
2268        let row_id =
2269            db.one_column::<i64, _>("INSERT INTO foo DEFAULT VALUES RETURNING ROWID", [])?;
2270        assert_eq!(row_id, 1);
2271        Ok(())
2272    }
2273
2274    #[test]
2275    fn test_cache_flush() -> Result<()> {
2276        let db = Connection::open_in_memory()?;
2277        db.cache_flush()
2278    }
2279
2280    #[test]
2281    fn db_readonly() -> Result<()> {
2282        let db = Connection::open_in_memory()?;
2283        assert!(!db.is_readonly(MAIN_DB)?);
2284        Ok(())
2285    }
2286
2287    #[test]
2288    #[cfg(feature = "rusqlite-macros")]
2289    fn prepare_and_bind() -> Result<()> {
2290        let db = Connection::open_in_memory()?;
2291        let name = "Lisa";
2292        let age = 8;
2293        let mut stmt = prepare_and_bind!(db, "SELECT $name, $age;");
2294        let (v1, v2) = stmt
2295            .raw_query()
2296            .next()
2297            .and_then(|o| o.ok_or(Error::QueryReturnedNoRows))
2298            .and_then(|r| Ok((r.get::<_, String>(0)?, r.get::<_, i64>(1)?)))?;
2299        assert_eq!((v1.as_str(), v2), (name, age));
2300        Ok(())
2301    }
2302
2303    #[test]
2304    #[cfg(feature = "modern_sqlite")]
2305    fn test_db_name() -> Result<()> {
2306        let db = Connection::open_in_memory()?;
2307        assert_eq!(db.db_name(0)?, "main");
2308        assert_eq!(db.db_name(1)?, "temp");
2309        assert_eq!(db.db_name(2), Err(Error::InvalidDatabaseIndex(2)));
2310        db.execute_batch("ATTACH DATABASE ':memory:' AS xyz;")?;
2311        assert_eq!(db.db_name(2)?, "xyz");
2312        Ok(())
2313    }
2314
2315    #[test]
2316    #[cfg(feature = "modern_sqlite")]
2317    fn test_is_interrupted() -> Result<()> {
2318        let db = Connection::open_in_memory()?;
2319        assert!(!db.is_interrupted());
2320        db.get_interrupt_handle().interrupt();
2321        assert!(db.is_interrupted());
2322        Ok(())
2323    }
2324
2325    #[test]
2326    fn release_memory() -> Result<()> {
2327        let db = Connection::open_in_memory()?;
2328        db.release_memory()
2329    }
2330}