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