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