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