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