rusqlite/src/lib.rs

1660 lines
55 KiB
Rust
Raw Normal View History

//! Rusqlite is an ergonomic wrapper for using SQLite from Rust. It attempts to expose
2014-11-04 06:11:00 +08:00
//! an interface similar to [rust-postgres](https://github.com/sfackler/rust-postgres).
//!
//! ```rust
//! extern crate rusqlite;
//! extern crate time;
//!
//! use time::Timespec;
//! use rusqlite::Connection;
2014-11-04 06:11:00 +08:00
//!
//! #[derive(Debug)]
2014-11-04 06:11:00 +08:00
//! struct Person {
//! id: i32,
//! name: String,
//! time_created: Timespec,
//! data: Option<Vec<u8>>
//! }
//!
//! fn main() {
//! let conn = Connection::open_in_memory().unwrap();
2014-11-04 06:11:00 +08:00
//!
//! conn.execute("CREATE TABLE person (
//! id INTEGER PRIMARY KEY,
//! name TEXT NOT NULL,
//! time_created TEXT NOT NULL,
//! data BLOB
2014-11-19 23:48:40 +08:00
//! )", &[]).unwrap();
2014-11-04 06:11:00 +08:00
//! let me = Person {
//! id: 0,
//! name: "Steven".to_string(),
//! time_created: time::get_time(),
//! data: None
//! };
//! conn.execute("INSERT INTO person (name, time_created, data)
//! VALUES ($1, $2, $3)",
//! &[&me.name, &me.time_created, &me.data]).unwrap();
//!
//! let mut stmt = conn.prepare("SELECT id, name, time_created, data FROM person").unwrap();
//! let mut person_iter = stmt.query_map(&[], |row| {
//! Person {
2014-11-04 06:11:00 +08:00
//! id: row.get(0),
//! name: row.get(1),
//! time_created: row.get(2),
//! data: row.get(3)
//! }
//! }).unwrap();
//!
//! for person in person_iter {
//! println!("Found person {:?}", person.unwrap());
2014-11-04 06:11:00 +08:00
//! }
//! }
//! ```
2014-10-20 07:56:41 +08:00
extern crate libc;
2015-03-27 03:48:29 +08:00
extern crate libsqlite3_sys as ffi;
2015-12-11 05:48:09 +08:00
#[macro_use]
extern crate bitflags;
#[cfg(test)]
#[macro_use]
extern crate lazy_static;
2014-10-20 07:56:41 +08:00
use std::default::Default;
use std::convert;
2014-10-20 07:56:41 +08:00
use std::mem;
use std::ptr;
2014-10-20 07:56:41 +08:00
use std::fmt;
2015-12-11 05:48:09 +08:00
use std::path::{Path, PathBuf};
use std::error;
2015-12-11 05:48:09 +08:00
use std::rc::Rc;
2014-10-20 07:56:41 +08:00
use std::cell::{RefCell, Cell};
2015-02-24 08:52:48 +08:00
use std::ffi::{CStr, CString};
2015-12-13 03:06:03 +08:00
use std::result;
use std::str;
2014-10-20 07:56:41 +08:00
use libc::{c_int, c_void, c_char};
use types::{ToSql, FromSql};
pub use transaction::{SqliteTransaction, Transaction, TransactionBehavior};
2014-10-20 07:56:41 +08:00
2015-12-11 05:48:09 +08:00
#[cfg(feature = "load_extension")]
pub use load_extension_guard::{SqliteLoadExtensionGuard, LoadExtensionGuard};
2014-10-20 07:56:41 +08:00
pub mod types;
mod transaction;
mod named_params;
2015-12-11 05:48:09 +08:00
#[cfg(feature = "load_extension")]mod load_extension_guard;
#[cfg(feature = "trace")]pub mod trace;
#[cfg(feature = "backup")]pub mod backup;
#[cfg(feature = "functions")] pub mod functions;
2014-10-20 07:56:41 +08:00
2015-12-13 03:06:03 +08:00
/// Old name for `Result`. `SqliteResult` is deprecated.
pub type SqliteResult<T> = Result<T>;
2014-11-04 06:11:00 +08:00
/// A typedef of the result returned by many methods.
2015-12-13 03:06:03 +08:00
pub type Result<T> = result::Result<T, Error>;
2014-10-20 07:56:41 +08:00
unsafe fn errmsg_to_string(errmsg: *const c_char) -> String {
2015-02-24 08:52:48 +08:00
let c_slice = CStr::from_ptr(errmsg).to_bytes();
let utf8_str = str::from_utf8(c_slice);
utf8_str.unwrap_or("Invalid string encoding").to_string()
2014-10-20 07:56:41 +08:00
}
2015-12-13 02:53:58 +08:00
/// Old name for `Error`. `SqliteError` is deprecated.
pub type SqliteError = Error;
2014-11-04 06:11:00 +08:00
/// Encompasses an error result from a call to the SQLite C API.
#[derive(Debug, PartialEq)]
2015-12-13 02:53:58 +08:00
pub struct Error {
2014-11-04 06:11:00 +08:00
/// The error code returned by a SQLite C API call. See [SQLite Result
/// Codes](http://www.sqlite.org/rescode.html) for details.
2014-10-20 07:56:41 +08:00
pub code: c_int,
2014-11-04 06:11:00 +08:00
/// The error message provided by [sqlite3_errmsg](http://www.sqlite.org/c3ref/errcode.html),
/// if possible, or a generic error message based on `code` otherwise.
2014-10-20 07:56:41 +08:00
pub message: String,
}
2015-12-13 02:53:58 +08:00
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} (SQLite error {})", self.message, self.code)
}
}
2015-12-13 02:53:58 +08:00
impl error::Error for Error {
fn description(&self) -> &str {
2015-03-17 12:55:28 +08:00
&self.message
2015-01-11 10:50:03 +08:00
}
}
2015-12-13 02:53:58 +08:00
impl Error {
fn from_handle(db: *mut ffi::Struct_sqlite3, code: c_int) -> Error {
2014-10-20 07:56:41 +08:00
let message = if db.is_null() {
ffi::code_to_str(code).to_string()
} else {
unsafe { errmsg_to_string(ffi::sqlite3_errmsg(db)) }
};
2015-12-13 02:53:58 +08:00
Error {
2015-12-11 05:48:09 +08:00
code: code,
message: message,
}
2014-10-20 07:56:41 +08:00
}
}
2015-12-13 03:06:03 +08:00
fn str_to_cstring(s: &str) -> Result<CString> {
2015-12-11 05:48:09 +08:00
CString::new(s).map_err(|_| {
2015-12-13 02:53:58 +08:00
Error {
2015-12-11 05:48:09 +08:00
code: ffi::SQLITE_MISUSE,
message: format!("Could not convert string {} to C-combatible string", s),
}
2015-02-24 08:52:48 +08:00
})
}
2015-12-13 03:06:03 +08:00
fn path_to_cstring(p: &Path) -> Result<CString> {
2015-12-13 02:53:58 +08:00
let s = try!(p.to_str().ok_or(Error {
2015-02-24 08:52:48 +08:00
code: ffi::SQLITE_MISUSE,
2015-12-11 05:48:09 +08:00
message: format!("Could not convert path {} to UTF-8 string",
p.to_string_lossy()),
2015-02-24 08:52:48 +08:00
}));
str_to_cstring(s)
}
2015-12-10 05:27:18 +08:00
/// Name for a database within a SQLite connection.
pub enum DatabaseName<'a> {
/// The main database.
Main,
/// The temporary database (e.g., any "CREATE TEMPORARY TABLE" tables).
Temp,
/// A database that has been attached via "ATTACH DATABASE ...".
Attached(&'a str),
}
// Currently DatabaseName is only used by the backup mod, so hide this (private)
// impl to avoid dead code warnings.
#[cfg(feature = "backup")]
impl<'a> DatabaseName<'a> {
2015-12-13 03:06:03 +08:00
fn to_cstring(self) -> Result<CString> {
2015-12-10 05:27:18 +08:00
use self::DatabaseName::{Main, Temp, Attached};
match self {
2015-12-11 05:48:09 +08:00
Main => str_to_cstring("main"),
Temp => str_to_cstring("temp"),
2015-12-10 05:27:18 +08:00
Attached(s) => str_to_cstring(s),
}
}
}
/// Old name for `Connection`. `SqliteConnection` is deprecated.
pub type SqliteConnection = Connection;
2014-11-04 06:11:00 +08:00
/// A connection to a SQLite database.
pub struct Connection {
db: RefCell<InnerConnection>,
2015-08-01 18:04:02 +08:00
path: Option<PathBuf>,
2014-10-20 07:56:41 +08:00
}
unsafe impl Send for Connection {}
impl Connection {
2014-11-04 06:11:00 +08:00
/// Open a new connection to a SQLite database.
///
/// `Connection::open(path)` is equivalent to `Connection::open_with_flags(path,
2014-11-04 06:11:00 +08:00
/// SQLITE_OPEN_READ_WRITE | SQLITE_OPEN_CREATE)`.
///
/// # Failure
///
/// Will return `Err` if `path` cannot be converted to a C-compatible string or if the
/// underlying SQLite open call fails.
2015-12-13 03:06:03 +08:00
pub fn open<P: AsRef<Path>>(path: P) -> Result<Connection> {
let flags = Default::default();
Connection::open_with_flags(path, flags)
2014-10-20 07:56:41 +08:00
}
/// Open a new connection to an in-memory SQLite database.
///
/// # Failure
///
/// Will return `Err` if the underlying SQLite open call fails.
2015-12-13 03:06:03 +08:00
pub fn open_in_memory() -> Result<Connection> {
let flags = Default::default();
Connection::open_in_memory_with_flags(flags)
}
2014-11-04 06:11:00 +08:00
/// Open a new connection to a SQLite database.
///
/// Database Connection](http://www.sqlite.org/c3ref/open.html) for a description of valid
/// flag combinations.
///
/// # Failure
///
/// Will return `Err` if `path` cannot be converted to a C-compatible string or if the
/// underlying SQLite open call fails.
2015-12-11 05:48:09 +08:00
pub fn open_with_flags<P: AsRef<Path>>(path: P,
flags: OpenFlags)
2015-12-13 03:06:03 +08:00
-> Result<Connection> {
2015-12-11 05:48:09 +08:00
let c_path = try!(path_to_cstring(path.as_ref()));
InnerConnection::open_with_flags(&c_path, flags).map(|db| {
Connection {
2015-12-11 05:48:09 +08:00
db: RefCell::new(db),
path: Some(path.as_ref().to_path_buf()),
}
})
}
/// Open a new connection to an in-memory SQLite database.
///
/// Database Connection](http://www.sqlite.org/c3ref/open.html) for a description of valid
/// flag combinations.
///
/// # Failure
///
/// Will return `Err` if the underlying SQLite open call fails.
pub fn open_in_memory_with_flags(flags: OpenFlags) -> Result<Connection> {
2015-02-24 10:44:29 +08:00
let c_memory = try!(str_to_cstring(":memory:"));
InnerConnection::open_with_flags(&c_memory, flags).map(|db| {
Connection {
2015-12-11 05:48:09 +08:00
db: RefCell::new(db),
path: None,
}
2014-10-20 07:56:41 +08:00
})
}
2014-11-04 06:11:00 +08:00
/// Begin a new transaction with the default behavior (DEFERRED).
///
/// The transaction defaults to rolling back when it is dropped. If you want the transaction to
/// commit, you must call `commit` or `set_commit`.
///
/// ## Example
///
/// ```rust,no_run
2015-12-13 03:06:03 +08:00
/// # use rusqlite::{Connection, Result};
/// # fn do_queries_part_1(conn: &Connection) -> Result<()> { Ok(()) }
/// # fn do_queries_part_2(conn: &Connection) -> Result<()> { Ok(()) }
/// fn perform_queries(conn: &Connection) -> Result<()> {
2014-11-04 06:11:00 +08:00
/// let tx = try!(conn.transaction());
///
/// try!(do_queries_part_1(conn)); // tx causes rollback if this fails
/// try!(do_queries_part_2(conn)); // tx causes rollback if this fails
///
/// tx.commit()
/// }
/// ```
///
/// # Failure
///
/// Will return `Err` if the underlying SQLite call fails.
pub fn transaction<'a>(&'a self) -> Result<Transaction<'a>> {
Transaction::new(self, TransactionBehavior::Deferred)
2014-10-20 07:56:41 +08:00
}
2014-11-04 06:11:00 +08:00
/// Begin a new transaction with a specified behavior.
///
/// See `transaction`.
///
/// # Failure
///
/// Will return `Err` if the underlying SQLite call fails.
2015-12-11 05:48:09 +08:00
pub fn transaction_with_behavior<'a>(&'a self,
behavior: TransactionBehavior)
-> Result<Transaction<'a>> {
Transaction::new(self, behavior)
2015-12-11 05:48:09 +08:00
}
2014-10-20 07:56:41 +08:00
2014-11-04 06:11:00 +08:00
/// Convenience method to run multiple SQL statements (that cannot take any parameters).
///
/// Uses [sqlite3_exec](http://www.sqlite.org/c3ref/exec.html) under the hood.
///
/// ## Example
///
/// ```rust,no_run
2015-12-13 03:06:03 +08:00
/// # use rusqlite::{Connection, Result};
/// fn create_tables(conn: &Connection) -> Result<()> {
2014-11-04 06:11:00 +08:00
/// conn.execute_batch("BEGIN;
/// CREATE TABLE foo(x INTEGER);
/// CREATE TABLE bar(y TEXT);
/// COMMIT;")
/// }
/// ```
///
/// # Failure
///
/// Will return `Err` if `sql` cannot be converted to a C-compatible string or if the
/// underlying SQLite call fails.
2015-12-13 03:06:03 +08:00
pub fn execute_batch(&self, sql: &str) -> Result<()> {
2014-10-20 07:56:41 +08:00
self.db.borrow_mut().execute_batch(sql)
}
2014-11-04 06:11:00 +08:00
/// Convenience method to prepare and execute a single SQL statement.
///
/// On success, returns the number of rows that were changed or inserted or deleted (via
/// `sqlite3_changes`).
///
/// ## Example
///
/// ```rust,no_run
/// # use rusqlite::{Connection};
/// fn update_rows(conn: &Connection) {
2014-11-04 06:11:00 +08:00
/// match conn.execute("UPDATE foo SET bar = 'baz' WHERE qux = ?", &[&1i32]) {
/// Ok(updated) => println!("{} rows were updated", updated),
/// Err(err) => println!("update failed: {}", err),
/// }
/// }
/// ```
///
/// # Failure
///
/// Will return `Err` if `sql` cannot be converted to a C-compatible string or if the
/// underlying SQLite call fails.
2015-12-13 03:06:03 +08:00
pub fn execute(&self, sql: &str, params: &[&ToSql]) -> Result<c_int> {
2014-10-20 07:56:41 +08:00
self.prepare(sql).and_then(|mut stmt| stmt.execute(params))
}
2014-11-04 06:11:00 +08:00
/// Get the SQLite rowid of the most recent successful INSERT.
///
/// Uses [sqlite3_last_insert_rowid](https://www.sqlite.org/c3ref/last_insert_rowid.html) under
/// the hood.
2014-10-20 07:56:41 +08:00
pub fn last_insert_rowid(&self) -> i64 {
self.db.borrow_mut().last_insert_rowid()
}
2014-11-04 06:11:00 +08:00
/// Convenience method to execute a query that is expected to return a single row.
///
/// ## Example
///
/// ```rust,no_run
2015-12-13 03:06:03 +08:00
/// # use rusqlite::{Result,Connection};
/// fn preferred_locale(conn: &Connection) -> Result<String> {
2015-05-07 21:41:02 +08:00
/// conn.query_row("SELECT value FROM preferences WHERE name='locale'", &[], |row| {
2014-11-04 06:11:00 +08:00
/// row.get(0)
/// })
/// }
/// ```
///
/// If the query returns more than one row, all rows except the first are ignored.
///
/// # Failure
///
/// Will return `Err` if `sql` cannot be converted to a C-compatible string or if the
/// underlying SQLite call fails.
2015-12-13 03:06:03 +08:00
pub fn query_row<T, F>(&self, sql: &str, params: &[&ToSql], f: F) -> Result<T>
2015-12-13 03:11:24 +08:00
where F: FnOnce(Row) -> T
{
let mut stmt = try!(self.prepare(sql));
let mut rows = try!(stmt.query(params));
2015-12-11 05:48:09 +08:00
rows.get_expected_row().map(f)
}
2014-10-20 07:56:41 +08:00
/// Convenience method to execute a query that is expected to return a single row,
/// and execute a mapping via `f` on that returned row with the possibility of failure.
2015-12-13 02:53:58 +08:00
/// The `Result` type of `f` must implement `std::convert::From<Error>`.
///
/// ## Example
///
/// ```rust,no_run
2015-12-13 03:06:03 +08:00
/// # use rusqlite::{Result,Connection};
/// fn preferred_locale(conn: &Connection) -> Result<String> {
/// conn.query_row_and_then("SELECT value FROM preferences WHERE name='locale'", &[], |row| {
/// row.get_checked(0)
/// })
/// }
/// ```
///
/// If the query returns more than one row, all rows except the first are ignored.
///
/// # Failure
///
/// Will return `Err` if `sql` cannot be converted to a C-compatible string or if the
/// underlying SQLite call fails.
2015-12-13 03:06:03 +08:00
pub fn query_row_and_then<T, E, F>(&self, sql: &str, params: &[&ToSql], f: F) -> result::Result<T, E>
2015-12-13 03:11:24 +08:00
where F: FnOnce(Row) -> result::Result<T, E>,
2015-12-13 02:53:58 +08:00
E: convert::From<Error>
{
let mut stmt = try!(self.prepare(sql));
let mut rows = try!(stmt.query(params));
rows.get_expected_row().map_err(E::from).and_then(f)
}
/// Convenience method to execute a query that is expected to return a single row.
///
/// ## Example
///
/// ```rust,no_run
2015-12-13 03:06:03 +08:00
/// # use rusqlite::{Result,Connection};
/// fn preferred_locale(conn: &Connection) -> Result<String> {
/// conn.query_row_safe("SELECT value FROM preferences WHERE name='locale'", &[], |row| {
/// row.get(0)
/// })
/// }
/// ```
///
/// If the query returns more than one row, all rows except the first are ignored.
///
/// ## Deprecated
///
/// This method should be considered deprecated. Use `query_row` instead, which now
/// does exactly the same thing.
2015-12-13 03:06:03 +08:00
pub fn query_row_safe<T, F>(&self, sql: &str, params: &[&ToSql], f: F) -> Result<T>
2015-12-13 03:11:24 +08:00
where F: FnOnce(Row) -> T
2015-12-11 05:48:09 +08:00
{
self.query_row(sql, params, f)
}
2014-11-04 06:11:00 +08:00
/// Prepare a SQL statement for execution.
///
/// ## Example
///
/// ```rust,no_run
2015-12-13 03:06:03 +08:00
/// # use rusqlite::{Connection, Result};
/// fn insert_new_people(conn: &Connection) -> Result<()> {
2014-11-04 06:11:00 +08:00
/// let mut stmt = try!(conn.prepare("INSERT INTO People (name) VALUES (?)"));
/// try!(stmt.execute(&[&"Joe Smith"]));
/// try!(stmt.execute(&[&"Bob Jones"]));
/// Ok(())
/// }
/// ```
///
/// # Failure
///
/// Will return `Err` if `sql` cannot be converted to a C-compatible string or if the
/// underlying SQLite call fails.
pub fn prepare<'a>(&'a self, sql: &str) -> Result<Statement<'a>> {
2014-10-20 07:56:41 +08:00
self.db.borrow_mut().prepare(self, sql)
}
2014-11-04 06:11:00 +08:00
/// Close the SQLite connection.
///
/// This is functionally equivalent to the `Drop` implementation for `Connection` except
2014-11-04 06:11:00 +08:00
/// that it returns any error encountered to the caller.
///
/// # Failure
///
/// Will return `Err` if the underlying SQLite call fails.
2015-12-13 03:06:03 +08:00
pub fn close(self) -> Result<()> {
2015-02-14 04:44:24 +08:00
let mut db = self.db.borrow_mut();
db.close()
2014-10-20 07:56:41 +08:00
}
/// Enable loading of SQLite extensions. Strongly consider using `LoadExtensionGuard`
/// instead of this function.
2015-02-24 08:52:48 +08:00
///
/// ## Example
///
/// ```rust,no_run
2015-12-13 03:06:03 +08:00
/// # use rusqlite::{Connection, Result};
2015-02-24 08:52:48 +08:00
/// # use std::path::{Path};
2015-12-13 03:06:03 +08:00
/// fn load_my_extension(conn: &Connection) -> Result<()> {
2015-02-24 08:52:48 +08:00
/// try!(conn.load_extension_enable());
/// try!(conn.load_extension(Path::new("my_sqlite_extension"), None));
/// conn.load_extension_disable()
/// }
/// ```
///
/// # Failure
///
/// Will return `Err` if the underlying SQLite call fails.
2015-02-24 08:52:48 +08:00
#[cfg(feature = "load_extension")]
2015-12-13 03:06:03 +08:00
pub fn load_extension_enable(&self) -> Result<()> {
2015-02-24 08:52:48 +08:00
self.db.borrow_mut().enable_load_extension(1)
}
/// Disable loading of SQLite extensions.
///
/// See `load_extension_enable` for an example.
///
/// # Failure
///
/// Will return `Err` if the underlying SQLite call fails.
2015-02-24 08:52:48 +08:00
#[cfg(feature = "load_extension")]
2015-12-13 03:06:03 +08:00
pub fn load_extension_disable(&self) -> Result<()> {
2015-02-24 08:52:48 +08:00
self.db.borrow_mut().enable_load_extension(0)
}
/// Load the SQLite extension at `dylib_path`. `dylib_path` is passed through to
/// `sqlite3_load_extension`, which may attempt OS-specific modifications if the file
/// cannot be loaded directly.
///
/// If `entry_point` is `None`, SQLite will attempt to find the entry point. If it is not
/// `None`, the entry point will be passed through to `sqlite3_load_extension`.
///
/// ## Example
///
/// ```rust,no_run
/// # use rusqlite::{Connection, Result, LoadExtensionGuard};
/// # use std::path::{Path};
2015-12-13 03:06:03 +08:00
/// fn load_my_extension(conn: &Connection) -> Result<()> {
/// let _guard = try!(LoadExtensionGuard::new(conn));
///
/// conn.load_extension("my_sqlite_extension", None)
/// }
2015-12-09 10:15:23 +08:00
/// ```
///
/// # Failure
///
/// Will return `Err` if the underlying SQLite call fails.
2015-02-24 08:52:48 +08:00
#[cfg(feature = "load_extension")]
2015-12-11 05:48:09 +08:00
pub fn load_extension<P: AsRef<Path>>(&self,
dylib_path: P,
entry_point: Option<&str>)
2015-12-13 03:06:03 +08:00
-> Result<()> {
2015-12-11 05:48:09 +08:00
self.db.borrow_mut().load_extension(dylib_path.as_ref(), entry_point)
}
2014-10-20 07:56:41 +08:00
2015-12-13 03:06:03 +08:00
fn decode_result(&self, code: c_int) -> Result<()> {
2014-10-20 07:56:41 +08:00
self.db.borrow_mut().decode_result(code)
}
2015-01-11 10:39:59 +08:00
fn changes(&self) -> c_int {
2014-10-20 07:56:41 +08:00
self.db.borrow_mut().changes()
}
}
impl fmt::Debug for Connection {
2014-10-20 07:56:41 +08:00
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Connection")
2015-11-11 22:14:31 +08:00
.field("path", &self.path)
.finish()
2014-10-20 07:56:41 +08:00
}
}
struct InnerConnection {
db: *mut ffi::Struct_sqlite3,
2014-10-20 07:56:41 +08:00
}
/// Old name for `OpenFlags`. `SqliteOpenFlags` is deprecated.
pub type SqliteOpenFlags = OpenFlags;
2014-10-20 07:56:41 +08:00
bitflags! {
2014-11-04 06:11:00 +08:00
#[doc = "Flags for opening SQLite database connections."]
#[doc = "See [sqlite3_open_v2](http://www.sqlite.org/c3ref/open.html) for details."]
#[repr(C)]
flags OpenFlags: c_int {
2014-10-20 07:56:41 +08:00
const SQLITE_OPEN_READ_ONLY = 0x00000001,
const SQLITE_OPEN_READ_WRITE = 0x00000002,
const SQLITE_OPEN_CREATE = 0x00000004,
const SQLITE_OPEN_URI = 0x00000040,
const SQLITE_OPEN_MEMORY = 0x00000080,
const SQLITE_OPEN_NO_MUTEX = 0x00008000,
const SQLITE_OPEN_FULL_MUTEX = 0x00010000,
const SQLITE_OPEN_SHARED_CACHE = 0x00020000,
const SQLITE_OPEN_PRIVATE_CACHE = 0x00040000,
}
}
impl Default for OpenFlags {
fn default() -> OpenFlags {
2015-12-11 05:48:09 +08:00
SQLITE_OPEN_READ_WRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NO_MUTEX | SQLITE_OPEN_URI
}
}
impl InnerConnection {
2015-12-11 05:48:09 +08:00
fn open_with_flags(c_path: &CString,
flags: OpenFlags)
2015-12-13 03:06:03 +08:00
-> Result<InnerConnection> {
2015-12-11 05:48:09 +08:00
unsafe {
let mut db: *mut ffi::sqlite3 = mem::uninitialized();
let r = ffi::sqlite3_open_v2(c_path.as_ptr(), &mut db, flags.bits(), ptr::null());
if r != ffi::SQLITE_OK {
let e = if db.is_null() {
2015-12-13 02:53:58 +08:00
Error {
2015-12-11 05:48:09 +08:00
code: r,
message: ffi::code_to_str(r).to_string(),
}
} else {
2015-12-13 02:53:58 +08:00
let e = Error::from_handle(db, r);
2015-12-11 05:48:09 +08:00
ffi::sqlite3_close(db);
e
};
return Err(e);
}
let r = ffi::sqlite3_busy_timeout(db, 5000);
if r != ffi::SQLITE_OK {
2015-12-13 02:53:58 +08:00
let e = Error::from_handle(db, r);
2014-10-20 07:56:41 +08:00
ffi::sqlite3_close(db);
2015-12-11 05:48:09 +08:00
return Err(e);
}
Ok(InnerConnection { db: db })
2014-12-24 01:26:57 +08:00
}
}
2014-10-20 07:56:41 +08:00
fn db(&self) -> *mut ffi::Struct_sqlite3 {
self.db
}
2015-12-13 03:06:03 +08:00
fn decode_result(&mut self, code: c_int) -> Result<()> {
2014-10-20 07:56:41 +08:00
if code == ffi::SQLITE_OK {
Ok(())
} else {
2015-12-13 02:53:58 +08:00
Err(Error::from_handle(self.db(), code))
2014-10-20 07:56:41 +08:00
}
}
2015-12-11 05:48:09 +08:00
unsafe fn decode_result_with_errmsg(&self,
code: c_int,
errmsg: *mut c_char)
2015-12-13 03:06:03 +08:00
-> Result<()> {
2015-12-11 05:48:09 +08:00
if code == ffi::SQLITE_OK {
Ok(())
} else {
let message = errmsg_to_string(&*errmsg);
ffi::sqlite3_free(errmsg as *mut c_void);
2015-12-13 02:53:58 +08:00
Err(Error {
2015-12-11 05:48:09 +08:00
code: code,
message: message,
})
}
2015-02-24 08:52:48 +08:00
}
2015-12-13 03:06:03 +08:00
fn close(&mut self) -> Result<()> {
unsafe {
let r = ffi::sqlite3_close(self.db());
self.db = ptr::null_mut();
self.decode_result(r)
}
2014-10-20 07:56:41 +08:00
}
2015-12-13 03:06:03 +08:00
fn execute_batch(&mut self, sql: &str) -> Result<()> {
2015-02-24 09:20:35 +08:00
let c_sql = try!(str_to_cstring(sql));
unsafe {
2014-10-20 07:56:41 +08:00
let mut errmsg: *mut c_char = mem::uninitialized();
2015-12-11 05:48:09 +08:00
let r = ffi::sqlite3_exec(self.db(),
c_sql.as_ptr(),
None,
ptr::null_mut(),
&mut errmsg);
2015-02-24 08:52:48 +08:00
self.decode_result_with_errmsg(r, errmsg)
}
}
#[cfg(feature = "load_extension")]
2015-12-13 03:06:03 +08:00
fn enable_load_extension(&mut self, onoff: c_int) -> Result<()> {
2015-02-24 08:52:48 +08:00
let r = unsafe { ffi::sqlite3_enable_load_extension(self.db, onoff) };
self.decode_result(r)
}
#[cfg(feature = "load_extension")]
2015-12-13 03:06:03 +08:00
fn load_extension(&self, dylib_path: &Path, entry_point: Option<&str>) -> Result<()> {
2015-02-24 08:52:48 +08:00
let dylib_str = try!(path_to_cstring(dylib_path));
unsafe {
let mut errmsg: *mut c_char = mem::uninitialized();
let r = if let Some(entry_point) = entry_point {
let c_entry = try!(str_to_cstring(entry_point));
2015-12-11 05:48:09 +08:00
ffi::sqlite3_load_extension(self.db,
dylib_str.as_ptr(),
c_entry.as_ptr(),
&mut errmsg)
2014-10-20 07:56:41 +08:00
} else {
2015-02-24 08:52:48 +08:00
ffi::sqlite3_load_extension(self.db, dylib_str.as_ptr(), ptr::null(), &mut errmsg)
};
self.decode_result_with_errmsg(r, errmsg)
}
2014-10-20 07:56:41 +08:00
}
fn last_insert_rowid(&self) -> i64 {
2015-12-11 05:48:09 +08:00
unsafe { ffi::sqlite3_last_insert_rowid(self.db()) }
2014-10-20 07:56:41 +08:00
}
fn prepare<'a>(&mut self,
conn: &'a Connection,
2015-12-11 05:48:09 +08:00
sql: &str)
-> Result<Statement<'a>> {
2015-12-11 05:48:09 +08:00
if sql.len() >= ::std::i32::MAX as usize {
2015-12-13 02:53:58 +08:00
return Err(Error {
2015-12-11 05:48:09 +08:00
code: ffi::SQLITE_TOOBIG,
message: "statement too long".to_string(),
});
}
let mut c_stmt: *mut ffi::sqlite3_stmt = unsafe { mem::uninitialized() };
let c_sql = try!(str_to_cstring(sql));
let r = unsafe {
let len_with_nul = (sql.len() + 1) as c_int;
ffi::sqlite3_prepare_v2(self.db(),
c_sql.as_ptr(),
len_with_nul,
&mut c_stmt,
ptr::null_mut())
};
self.decode_result(r).map(|_| Statement::new(conn, c_stmt))
2015-08-08 15:30:50 +08:00
}
2014-10-20 07:56:41 +08:00
2015-01-11 10:39:59 +08:00
fn changes(&mut self) -> c_int {
2015-12-11 05:48:09 +08:00
unsafe { ffi::sqlite3_changes(self.db()) }
2014-10-20 07:56:41 +08:00
}
}
impl Drop for InnerConnection {
2014-10-20 07:56:41 +08:00
#[allow(unused_must_use)]
fn drop(&mut self) {
self.close();
}
}
/// Old name for `Statement`. `SqliteStatement` is deprecated.
pub type SqliteStatement<'conn> = Statement<'conn>;
2014-11-04 06:11:00 +08:00
/// A prepared statement.
pub struct Statement<'conn> {
conn: &'conn Connection,
2014-10-20 07:56:41 +08:00
stmt: *mut ffi::sqlite3_stmt,
needs_reset: bool,
column_count: c_int,
2014-10-20 07:56:41 +08:00
}
impl<'conn> Statement<'conn> {
fn new(conn: &Connection, stmt: *mut ffi::sqlite3_stmt) -> Statement {
Statement {
2015-12-11 05:48:09 +08:00
conn: conn,
stmt: stmt,
needs_reset: false,
column_count: unsafe { ffi::sqlite3_column_count(stmt) },
}
2014-10-20 07:56:41 +08:00
}
2015-07-25 10:11:59 +08:00
/// Get all the column names in the result set of the prepared statement.
pub fn column_names(&self) -> Vec<&str> {
let n = self.column_count;
2015-07-25 10:11:59 +08:00
let mut cols = Vec::with_capacity(n as usize);
for i in 0..n {
2015-12-11 05:48:09 +08:00
let slice = unsafe { CStr::from_ptr(ffi::sqlite3_column_name(self.stmt, i)) };
2015-07-25 10:11:59 +08:00
let s = str::from_utf8(slice.to_bytes()).unwrap();
cols.push(s);
}
cols
}
2014-11-04 06:11:00 +08:00
/// Execute the prepared statement.
///
/// On success, returns the number of rows that were changed or inserted or deleted (via
/// `sqlite3_changes`).
///
/// ## Example
///
/// ```rust,no_run
2015-12-13 03:06:03 +08:00
/// # use rusqlite::{Connection, Result};
/// fn update_rows(conn: &Connection) -> Result<()> {
2014-11-04 06:11:00 +08:00
/// let mut stmt = try!(conn.prepare("UPDATE foo SET bar = 'baz' WHERE qux = ?"));
///
/// try!(stmt.execute(&[&1i32]));
/// try!(stmt.execute(&[&2i32]));
///
/// Ok(())
/// }
/// ```
///
/// # Failure
///
/// Will return `Err` if binding parameters fails, the executed statement returns rows (in
/// which case `query` should be used instead), or the underling SQLite call fails.
2015-12-13 03:06:03 +08:00
pub fn execute(&mut self, params: &[&ToSql]) -> Result<c_int> {
2014-10-20 07:56:41 +08:00
unsafe {
2015-08-01 16:18:06 +08:00
try!(self.bind_parameters(params));
self.execute_()
}
}
2014-10-20 07:56:41 +08:00
2015-12-13 03:06:03 +08:00
unsafe fn execute_(&mut self) -> Result<c_int> {
let r = ffi::sqlite3_step(self.stmt);
ffi::sqlite3_reset(self.stmt);
match r {
ffi::SQLITE_DONE => {
if self.column_count != 0 {
2015-12-13 02:53:58 +08:00
Err(Error {
code: ffi::SQLITE_MISUSE,
message: "Unexpected column count - did you mean to call query?"
.to_string(),
2015-12-11 05:48:09 +08:00
})
} else {
Ok(self.conn.changes())
2015-12-11 05:48:09 +08:00
}
2014-10-20 07:56:41 +08:00
}
ffi::SQLITE_ROW => {
2015-12-13 02:53:58 +08:00
Err(Error {
code: r,
message: "Unexpected row result - did you mean to call query?".to_string(),
})
}
_ => Err(self.conn.decode_result(r).unwrap_err()),
2014-10-20 07:56:41 +08:00
}
}
2014-11-04 06:11:00 +08:00
/// Execute the prepared statement, returning an iterator over the resulting rows.
///
/// ## Example
///
/// ```rust,no_run
2015-12-13 03:06:03 +08:00
/// # use rusqlite::{Connection, Result};
/// fn get_names(conn: &Connection) -> Result<Vec<String>> {
2014-11-04 06:11:00 +08:00
/// let mut stmt = try!(conn.prepare("SELECT name FROM people"));
2014-11-19 23:48:40 +08:00
/// let mut rows = try!(stmt.query(&[]));
2014-11-04 06:11:00 +08:00
///
/// let mut names = Vec::new();
/// for result_row in rows {
/// let row = try!(result_row);
/// names.push(row.get(0));
/// }
///
/// Ok(names)
/// }
/// ```
///
/// # Failure
///
/// Will return `Err` if binding parameters fails.
2015-12-13 03:09:37 +08:00
pub fn query<'a>(&'a mut self, params: &[&ToSql]) -> Result<Rows<'a>> {
2014-10-20 07:56:41 +08:00
self.reset_if_needed();
unsafe {
try!(self.bind_parameters(params));
}
2015-08-01 16:18:06 +08:00
self.needs_reset = true;
2015-12-13 03:09:37 +08:00
Ok(Rows::new(self))
}
2014-10-20 07:56:41 +08:00
/// Executes the prepared statement and maps a function over the resulting
2015-08-01 16:18:06 +08:00
/// rows.
///
/// Unlike the iterator produced by `query`, the returned iterator does not expose the possibility
/// for accessing stale rows.
///
/// # Failure
///
/// Will return `Err` if binding parameters fails.
2015-12-11 05:48:09 +08:00
pub fn query_map<'a, T, F>(&'a mut self,
params: &[&ToSql],
f: F)
2015-12-13 03:06:03 +08:00
-> Result<MappedRows<'a, F>>
2015-12-13 03:11:24 +08:00
where F: FnMut(&Row) -> T
2015-12-11 05:48:09 +08:00
{
let row_iter = try!(self.query(params));
Ok(MappedRows {
rows: row_iter,
map: f,
})
}
2014-10-20 07:56:41 +08:00
/// Executes the prepared statement and maps a function over the resulting
/// rows, where the function returns a `Result` with `Error` type implementing
2015-12-13 02:53:58 +08:00
/// `std::convert::From<Error>` (so errors can be unified).
///
/// Unlike the iterator produced by `query`, the returned iterator does not expose the possibility
/// for accessing stale rows.
///
/// # Failure
///
/// Will return `Err` if binding parameters fails.
2015-12-11 05:48:09 +08:00
pub fn query_and_then<'a, T, E, F>(&'a mut self,
params: &[&ToSql],
f: F)
2015-12-13 03:06:03 +08:00
-> Result<AndThenRows<'a, F>>
2015-12-13 02:53:58 +08:00
where E: convert::From<Error>,
2015-12-13 03:11:24 +08:00
F: FnMut(&Row) -> result::Result<T, E>
2015-12-11 05:48:09 +08:00
{
let row_iter = try!(self.query(params));
Ok(AndThenRows {
rows: row_iter,
map: f,
})
}
2014-11-04 06:11:00 +08:00
/// Consumes the statement.
///
/// Functionally equivalent to the `Drop` implementation, but allows callers to see any errors
/// that occur.
///
/// # Failure
///
/// Will return `Err` if the underlying SQLite call fails.
2015-12-13 03:06:03 +08:00
pub fn finalize(mut self) -> Result<()> {
2014-10-20 07:56:41 +08:00
self.finalize_()
}
2015-12-13 03:06:03 +08:00
unsafe fn bind_parameters(&mut self, params: &[&ToSql]) -> Result<()> {
assert!(params.len() as c_int == ffi::sqlite3_bind_parameter_count(self.stmt),
2015-12-11 05:48:09 +08:00
"incorrect number of parameters to query(): expected {}, got {}",
ffi::sqlite3_bind_parameter_count(self.stmt),
params.len());
for (i, p) in params.iter().enumerate() {
try!(self.conn.decode_result(p.bind_parameter(self.stmt, (i + 1) as c_int)));
}
Ok(())
}
2014-10-20 07:56:41 +08:00
fn reset_if_needed(&mut self) {
if self.needs_reset {
2015-12-11 05:48:09 +08:00
unsafe {
ffi::sqlite3_reset(self.stmt);
};
2014-10-20 07:56:41 +08:00
self.needs_reset = false;
}
}
2015-12-13 03:06:03 +08:00
fn finalize_(&mut self) -> Result<()> {
2014-10-20 07:56:41 +08:00
let r = unsafe { ffi::sqlite3_finalize(self.stmt) };
self.stmt = ptr::null_mut();
self.conn.decode_result(r)
}
}
impl<'conn> fmt::Debug for Statement<'conn> {
2014-10-20 07:56:41 +08:00
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2015-08-01 18:04:02 +08:00
let sql = unsafe {
let c_slice = CStr::from_ptr(ffi::sqlite3_sql(self.stmt)).to_bytes();
str::from_utf8(c_slice)
};
f.debug_struct("Statement")
2015-11-11 22:14:31 +08:00
.field("conn", self.conn)
.field("stmt", &self.stmt)
.field("sql", &sql)
.finish()
2014-10-20 07:56:41 +08:00
}
}
impl<'conn> Drop for Statement<'conn> {
2014-10-20 07:56:41 +08:00
#[allow(unused_must_use)]
fn drop(&mut self) {
self.finalize_();
}
}
/// An iterator over the mapped resulting rows of a query.
pub struct MappedRows<'stmt, F> {
2015-12-13 03:09:37 +08:00
rows: Rows<'stmt>,
map: F,
}
2015-12-13 03:11:24 +08:00
impl<'stmt, T, F> Iterator for MappedRows<'stmt, F> where F: FnMut(&Row) -> T
2015-12-11 05:48:09 +08:00
{
2015-12-13 03:06:03 +08:00
type Item = Result<T>;
2015-12-13 03:06:03 +08:00
fn next(&mut self) -> Option<Result<T>> {
self.rows.next().map(|row_result| row_result.map(|row| (self.map)(&row)))
}
}
/// An iterator over the mapped resulting rows of a query, with an Error type
2015-12-13 02:53:58 +08:00
/// unifying with Error.
pub struct AndThenRows<'stmt, F> {
2015-12-13 03:09:37 +08:00
rows: Rows<'stmt>,
map: F,
}
impl<'stmt, T, E, F> Iterator for AndThenRows<'stmt, F>
2015-12-13 02:53:58 +08:00
where E: convert::From<Error>,
2015-12-13 03:11:24 +08:00
F: FnMut(&Row) -> result::Result<T, E>
2015-12-11 05:48:09 +08:00
{
2015-12-13 03:06:03 +08:00
type Item = result::Result<T, E>;
fn next(&mut self) -> Option<Self::Item> {
2015-12-11 05:48:09 +08:00
self.rows.next().map(|row_result| {
row_result.map_err(E::from)
.and_then(|row| (self.map)(&row))
})
}
}
2015-12-13 03:09:37 +08:00
/// Old name for `Rows`. `SqliteRows` is deprecated.
pub type SqliteRows<'stmt> = Rows<'stmt>;
2014-11-04 06:11:00 +08:00
/// An iterator over the resulting rows of a query.
///
/// ## Warning
///
/// Due to the way SQLite returns result rows of a query, it is not safe to attempt to get values
2015-12-13 03:09:37 +08:00
/// from a row after it has become stale (i.e., `next()` has been called again on the `Rows`
/// iterator). For example:
///
/// ```rust,no_run
2015-12-13 03:06:03 +08:00
/// # use rusqlite::{Connection, Result};
/// fn bad_function_will_panic(conn: &Connection) -> Result<i64> {
/// let mut stmt = try!(conn.prepare("SELECT id FROM my_table"));
2014-11-19 23:48:40 +08:00
/// let mut rows = try!(stmt.query(&[]));
///
/// let row0 = try!(rows.next().unwrap());
/// // row 0 is value now...
///
/// let row1 = try!(rows.next().unwrap());
/// // row 0 is now STALE, and row 1 is valid
///
/// let my_id = row0.get(0); // WILL PANIC because row 0 is stale
/// Ok(my_id)
/// }
/// ```
///
/// Please note that this means some of the methods on `Iterator` are not useful, such as `collect`
/// (which would result in a collection of rows, only the last of which can safely be used) and
/// `min`/`max` (which could return a stale row unless the last row happened to be the min or max,
/// respectively).
///
/// This problem could be solved by changing the signature of `next` to tie the lifetime of the
/// returned row to the lifetime of (a mutable reference to) the result rows handle, but this would
/// no longer implement `Iterator`, and therefore you would lose access to the majority of
/// functions which are useful (such as support for `for ... in ...` looping, `map`, `filter`,
/// etc.).
2015-12-13 03:09:37 +08:00
pub struct Rows<'stmt> {
stmt: &'stmt Statement<'stmt>,
2014-10-20 07:56:41 +08:00
current_row: Rc<Cell<c_int>>,
failed: bool,
}
2015-12-13 03:09:37 +08:00
impl<'stmt> Rows<'stmt> {
fn new(stmt: &'stmt Statement<'stmt>) -> Rows<'stmt> {
Rows {
2015-12-11 05:48:09 +08:00
stmt: stmt,
current_row: Rc::new(Cell::new(0)),
failed: false,
}
2014-10-20 07:56:41 +08:00
}
2015-12-13 03:11:24 +08:00
fn get_expected_row(&mut self) -> Result<Row<'stmt>> {
match self.next() {
Some(row) => row,
None => {
2015-12-13 02:53:58 +08:00
Err(Error {
code: ffi::SQLITE_NOTICE,
message: "Query did not return a row".to_string(),
})
}
}
}
2014-10-20 07:56:41 +08:00
}
2015-12-13 03:09:37 +08:00
impl<'stmt> Iterator for Rows<'stmt> {
2015-12-13 03:11:24 +08:00
type Item = Result<Row<'stmt>>;
2015-01-06 00:15:24 +08:00
2015-12-13 03:11:24 +08:00
fn next(&mut self) -> Option<Result<Row<'stmt>>> {
2014-10-20 07:56:41 +08:00
if self.failed {
return None;
}
match unsafe { ffi::sqlite3_step(self.stmt.stmt) } {
ffi::SQLITE_ROW => {
let current_row = self.current_row.get() + 1;
self.current_row.set(current_row);
2015-12-13 03:11:24 +08:00
Some(Ok(Row {
2014-10-20 07:56:41 +08:00
stmt: self.stmt,
current_row: self.current_row.clone(),
row_idx: current_row,
}))
2015-12-11 05:48:09 +08:00
}
2014-10-20 07:56:41 +08:00
ffi::SQLITE_DONE => None,
code => {
self.failed = true;
Some(Err(self.stmt.conn.decode_result(code).unwrap_err()))
}
}
}
}
2015-12-13 03:11:24 +08:00
/// Old name for `Row`. `SqliteRow` is deprecated.
pub type SqliteRow<'stmt> = Row<'stmt>;
2014-11-04 06:11:00 +08:00
/// A single result row of a query.
2015-12-13 03:11:24 +08:00
pub struct Row<'stmt> {
stmt: &'stmt Statement<'stmt>,
2014-10-20 07:56:41 +08:00
current_row: Rc<Cell<c_int>>,
row_idx: c_int,
}
2015-12-13 03:11:24 +08:00
impl<'stmt> Row<'stmt> {
2014-11-04 06:11:00 +08:00
/// Get the value of a particular column of the result row.
///
2015-12-13 03:11:24 +08:00
/// Note that `Row` can panic at runtime if you use it incorrectly. When you are
2014-11-04 06:11:00 +08:00
/// retrieving the rows of a query, a row becomes stale once you have requested the next row,
/// and the values can no longer be retrieved. In general (when using looping over the rows,
/// for example) this isn't an issue, but it means you cannot do something like this:
2014-11-04 06:11:00 +08:00
///
/// ```rust,no_run
2015-12-13 03:06:03 +08:00
/// # use rusqlite::{Connection, Result};
/// fn bad_function_will_panic(conn: &Connection) -> Result<i64> {
2014-11-04 06:11:00 +08:00
/// let mut stmt = try!(conn.prepare("SELECT id FROM my_table"));
2014-11-19 23:48:40 +08:00
/// let mut rows = try!(stmt.query(&[]));
2014-11-04 06:11:00 +08:00
///
/// let row0 = try!(rows.next().unwrap());
/// // row 0 is value now...
///
/// let row1 = try!(rows.next().unwrap());
/// // row 0 is now STALE, and row 1 is valid
///
/// let my_id = row0.get(0); // WILL PANIC because row 0 is stale
/// Ok(my_id)
/// }
/// ```
///
/// ## Failure
///
/// Panics if `idx` is outside the range of columns in the returned query or if this row
/// is stale.
2014-10-20 07:56:41 +08:00
pub fn get<T: FromSql>(&self, idx: c_int) -> T {
self.get_checked(idx).unwrap()
2014-10-20 07:56:41 +08:00
}
/// Get the value of a particular column of the result row.
///
/// ## Failure
///
2015-12-13 02:53:58 +08:00
/// Returns a `SQLITE_MISMATCH`-coded `Error` if the underlying SQLite column
/// type is not a valid type as a source for `T`.
///
2015-12-13 02:53:58 +08:00
/// Returns a `SQLITE_MISUSE`-coded `Error` if `idx` is outside the valid column range
2014-11-04 06:11:00 +08:00
/// for this row or if this row is stale.
2015-12-13 03:06:03 +08:00
pub fn get_checked<T: FromSql>(&self, idx: c_int) -> Result<T> {
2014-10-20 07:56:41 +08:00
if self.row_idx != self.current_row.get() {
2015-12-13 02:53:58 +08:00
return Err(Error {
2015-12-11 05:48:09 +08:00
code: ffi::SQLITE_MISUSE,
message: "Cannot get values from a row after advancing to next row".to_string(),
});
2014-10-20 07:56:41 +08:00
}
unsafe {
if idx < 0 || idx >= self.stmt.column_count {
2015-12-13 02:53:58 +08:00
return Err(Error {
2015-12-11 05:48:09 +08:00
code: ffi::SQLITE_MISUSE,
message: "Invalid column index".to_string(),
});
2014-10-20 07:56:41 +08:00
}
if T::column_has_valid_sqlite_type(self.stmt.stmt, idx) {
FromSql::column_result(self.stmt.stmt, idx)
} else {
2015-12-13 02:53:58 +08:00
Err(Error {
code: ffi::SQLITE_MISMATCH,
message: "Invalid column type".to_string(),
})
2014-10-20 07:56:41 +08:00
}
}
}
}
#[cfg(test)]
mod test {
2015-03-27 03:48:29 +08:00
extern crate libsqlite3_sys as ffi;
extern crate tempdir;
pub use super::*;
use self::tempdir::TempDir;
pub use std::error::Error as StdError;
pub use std::fmt;
2014-10-20 07:56:41 +08:00
// this function is never called, but is still type checked; in
// particular, calls with specific instantiations will require
// that those types are `Send`.
#[allow(dead_code, unconditional_recursion)]
fn ensure_send<T: Send>() {
ensure_send::<Connection>();
}
pub fn checked_memory_handle() -> Connection {
Connection::open_in_memory().unwrap()
2014-10-20 07:56:41 +08:00
}
#[test]
2015-12-11 05:48:09 +08:00
#[cfg_attr(rustfmt, rustfmt_skip)]
fn test_persistence() {
let temp_dir = TempDir::new("test_open_file").unwrap();
let path = temp_dir.path().join("test.db3");
{
let db = Connection::open(&path).unwrap();
let sql = "BEGIN;
CREATE TABLE foo(x INTEGER);
INSERT INTO foo VALUES(42);
END;";
2015-12-11 05:48:09 +08:00
db.execute_batch(sql).unwrap();
}
2015-05-05 08:02:33 +08:00
let path_string = path.to_str().unwrap();
let db = Connection::open(&path_string).unwrap();
2015-12-11 05:48:09 +08:00
let the_answer = db.query_row("SELECT x FROM foo", &[], |r| r.get::<i64>(0));
assert_eq!(42i64, the_answer.unwrap());
}
2014-10-20 07:56:41 +08:00
#[test]
fn test_open() {
assert!(Connection::open_in_memory().is_ok());
2014-10-20 07:56:41 +08:00
let db = checked_memory_handle();
assert!(db.close().is_ok());
}
#[test]
fn test_open_with_flags() {
for bad_flags in [OpenFlags::empty(),
2015-12-11 05:48:09 +08:00
SQLITE_OPEN_READ_ONLY | SQLITE_OPEN_READ_WRITE,
SQLITE_OPEN_READ_ONLY | SQLITE_OPEN_CREATE]
.iter() {
assert!(Connection::open_in_memory_with_flags(*bad_flags).is_err());
2015-12-11 05:48:09 +08:00
}
2014-10-20 07:56:41 +08:00
}
#[test]
2015-12-11 05:48:09 +08:00
#[cfg_attr(rustfmt, rustfmt_skip)]
2014-10-20 07:56:41 +08:00
fn test_execute_batch() {
let db = checked_memory_handle();
let sql = "BEGIN;
CREATE TABLE foo(x INTEGER);
INSERT INTO foo VALUES(1);
INSERT INTO foo VALUES(2);
INSERT INTO foo VALUES(3);
INSERT INTO foo VALUES(4);
END;";
db.execute_batch(sql).unwrap();
db.execute_batch("UPDATE foo SET x = 3 WHERE x < 3").unwrap();
assert!(db.execute_batch("INVALID SQL").is_err());
}
#[test]
fn test_execute() {
let db = checked_memory_handle();
db.execute_batch("CREATE TABLE foo(x INTEGER)").unwrap();
2015-12-13 03:06:03 +08:00
assert_eq!(1,
db.execute("INSERT INTO foo(x) VALUES (?)", &[&1i32]).unwrap());
assert_eq!(1,
db.execute("INSERT INTO foo(x) VALUES (?)", &[&2i32]).unwrap());
2014-10-20 07:56:41 +08:00
2015-12-11 05:48:09 +08:00
assert_eq!(3i32,
db.query_row("SELECT SUM(x) FROM foo", &[], |r| r.get(0)).unwrap());
2014-10-20 07:56:41 +08:00
}
2015-08-01 14:09:59 +08:00
#[test]
fn test_execute_select() {
let db = checked_memory_handle();
let err = db.execute("SELECT 1 WHERE 1 < ?", &[&1i32]).unwrap_err();
2015-08-01 15:11:31 +08:00
assert!(err.code == ffi::SQLITE_MISUSE);
assert!(err.message == "Unexpected column count - did you mean to call query?");
2015-08-01 14:09:59 +08:00
}
2015-07-25 10:11:59 +08:00
#[test]
fn test_prepare_column_names() {
let db = checked_memory_handle();
db.execute_batch("CREATE TABLE foo(x INTEGER);").unwrap();
let stmt = db.prepare("SELECT * FROM foo").unwrap();
assert_eq!(stmt.column_names(), vec!["x"]);
let stmt = db.prepare("SELECT x AS a, x AS b FROM foo").unwrap();
assert_eq!(stmt.column_names(), vec!["a", "b"]);
}
2014-10-20 07:56:41 +08:00
#[test]
fn test_prepare_execute() {
let db = checked_memory_handle();
db.execute_batch("CREATE TABLE foo(x INTEGER);").unwrap();
let mut insert_stmt = db.prepare("INSERT INTO foo(x) VALUES(?)").unwrap();
assert_eq!(insert_stmt.execute(&[&1i32]).unwrap(), 1);
assert_eq!(insert_stmt.execute(&[&2i32]).unwrap(), 1);
assert_eq!(insert_stmt.execute(&[&3i32]).unwrap(), 1);
assert_eq!(insert_stmt.execute(&[&"hello".to_string()]).unwrap(), 1);
assert_eq!(insert_stmt.execute(&[&"goodbye".to_string()]).unwrap(), 1);
assert_eq!(insert_stmt.execute(&[&types::Null]).unwrap(), 1);
let mut update_stmt = db.prepare("UPDATE foo SET x=? WHERE x<?").unwrap();
assert_eq!(update_stmt.execute(&[&3i32, &3i32]).unwrap(), 2);
assert_eq!(update_stmt.execute(&[&3i32, &3i32]).unwrap(), 0);
assert_eq!(update_stmt.execute(&[&8i32, &8i32]).unwrap(), 3);
}
#[test]
fn test_prepare_query() {
let db = checked_memory_handle();
db.execute_batch("CREATE TABLE foo(x INTEGER);").unwrap();
let mut insert_stmt = db.prepare("INSERT INTO foo(x) VALUES(?)").unwrap();
assert_eq!(insert_stmt.execute(&[&1i32]).unwrap(), 1);
assert_eq!(insert_stmt.execute(&[&2i32]).unwrap(), 1);
assert_eq!(insert_stmt.execute(&[&3i32]).unwrap(), 1);
let mut query = db.prepare("SELECT x FROM foo WHERE x < ? ORDER BY x DESC").unwrap();
{
let rows = query.query(&[&4i32]).unwrap();
let v: Vec<i32> = rows.map(|r| r.unwrap().get(0)).collect();
2015-03-17 12:55:28 +08:00
assert_eq!(v, [3i32, 2, 1]);
2014-10-20 07:56:41 +08:00
}
{
let rows = query.query(&[&3i32]).unwrap();
let v: Vec<i32> = rows.map(|r| r.unwrap().get(0)).collect();
2015-03-17 12:55:28 +08:00
assert_eq!(v, [2i32, 1]);
2014-10-20 07:56:41 +08:00
}
}
#[test]
2015-12-11 05:48:09 +08:00
#[cfg_attr(rustfmt, rustfmt_skip)]
fn test_query_map() {
let db = checked_memory_handle();
let sql = "BEGIN;
CREATE TABLE foo(x INTEGER, y TEXT);
INSERT INTO foo VALUES(4, \"hello\");
INSERT INTO foo VALUES(3, \", \");
INSERT INTO foo VALUES(2, \"world\");
INSERT INTO foo VALUES(1, \"!\");
END;";
db.execute_batch(sql).unwrap();
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
2015-12-13 03:06:03 +08:00
let results: Result<Vec<String>> = query.query_map(&[], |row| row.get(1))
.unwrap()
.collect();
assert_eq!(results.unwrap().concat(), "hello, world!");
}
#[test]
2015-12-11 05:48:09 +08:00
#[cfg_attr(rustfmt, rustfmt_skip)]
2015-05-07 21:41:02 +08:00
fn test_query_row() {
let db = checked_memory_handle();
let sql = "BEGIN;
CREATE TABLE foo(x INTEGER);
INSERT INTO foo VALUES(1);
INSERT INTO foo VALUES(2);
INSERT INTO foo VALUES(3);
INSERT INTO foo VALUES(4);
END;";
db.execute_batch(sql).unwrap();
2015-12-11 05:48:09 +08:00
assert_eq!(10i64,
db.query_row("SELECT SUM(x) FROM foo", &[], |r| r.get::<i64>(0))
.unwrap());
2015-05-07 21:41:02 +08:00
let result = db.query_row("SELECT x FROM foo WHERE x > 5", &[], |r| r.get::<i64>(0));
let error = result.unwrap_err();
assert!(error.code == ffi::SQLITE_NOTICE);
2015-03-17 12:55:28 +08:00
assert!(error.message == "Query did not return a row");
2015-05-07 21:41:02 +08:00
let bad_query_result = db.query_row("NOT A PROPER QUERY; test123", &[], |_| ());
assert!(bad_query_result.is_err());
}
2014-10-20 07:56:41 +08:00
#[test]
fn test_prepare_failures() {
let db = checked_memory_handle();
db.execute_batch("CREATE TABLE foo(x INTEGER);").unwrap();
let err = db.prepare("SELECT * FROM does_not_exist").unwrap_err();
2015-03-17 12:55:28 +08:00
assert!(err.message.contains("does_not_exist"));
2014-10-20 07:56:41 +08:00
}
#[test]
fn test_row_expiration() {
let db = checked_memory_handle();
db.execute_batch("CREATE TABLE foo(x INTEGER)").unwrap();
db.execute_batch("INSERT INTO foo(x) VALUES(1)").unwrap();
db.execute_batch("INSERT INTO foo(x) VALUES(2)").unwrap();
let mut stmt = db.prepare("SELECT x FROM foo ORDER BY x").unwrap();
2014-11-19 23:48:40 +08:00
let mut rows = stmt.query(&[]).unwrap();
2014-10-20 07:56:41 +08:00
let first = rows.next().unwrap().unwrap();
let second = rows.next().unwrap().unwrap();
assert_eq!(2i32, second.get(0));
let result = first.get_checked::<i32>(0);
2015-03-17 12:55:28 +08:00
assert!(result.unwrap_err().message.contains("advancing to next row"));
2014-10-20 07:56:41 +08:00
}
#[test]
fn test_last_insert_rowid() {
let db = checked_memory_handle();
db.execute_batch("CREATE TABLE foo(x INTEGER PRIMARY KEY)").unwrap();
db.execute_batch("INSERT INTO foo DEFAULT VALUES").unwrap();
assert_eq!(db.last_insert_rowid(), 1);
let mut stmt = db.prepare("INSERT INTO foo DEFAULT VALUES").unwrap();
2015-12-11 05:48:09 +08:00
for _ in 0i32..9 {
2014-11-19 23:48:40 +08:00
stmt.execute(&[]).unwrap();
2014-10-20 07:56:41 +08:00
}
assert_eq!(db.last_insert_rowid(), 10);
}
#[test]
fn test_statement_debugging() {
let db = checked_memory_handle();
let query = "SELECT 12345";
let stmt = db.prepare(query).unwrap();
assert!(format!("{:?}", stmt).contains(query));
}
mod query_and_then_tests {
extern crate libsqlite3_sys as ffi;
use super::*;
#[derive(Debug, PartialEq)]
enum CustomError {
SomeError,
2015-12-13 02:53:58 +08:00
Sqlite(Error),
}
impl fmt::Display for CustomError {
2015-12-13 03:06:03 +08:00
fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
match *self {
2015-12-11 05:48:09 +08:00
CustomError::SomeError => write!(f, "{}", self.description()),
CustomError::Sqlite(ref se) => write!(f, "{}: {}", self.description(), se),
}
}
}
impl StdError for CustomError {
2015-12-11 05:48:09 +08:00
fn description(&self) -> &str {
"my custom error"
}
fn cause(&self) -> Option<&StdError> {
match *self {
2015-12-11 05:48:09 +08:00
CustomError::SomeError => None,
CustomError::Sqlite(ref se) => Some(se),
}
}
}
2015-12-13 02:53:58 +08:00
impl From<Error> for CustomError {
fn from(se: Error) -> CustomError {
CustomError::Sqlite(se)
}
}
2015-12-13 03:06:03 +08:00
type CustomResult<T> = ::std::result::Result<T, CustomError>;
#[test]
2015-12-11 05:48:09 +08:00
#[cfg_attr(rustfmt, rustfmt_skip)]
fn test_query_and_then() {
let db = checked_memory_handle();
let sql = "BEGIN;
CREATE TABLE foo(x INTEGER, y TEXT);
INSERT INTO foo VALUES(4, \"hello\");
INSERT INTO foo VALUES(3, \", \");
INSERT INTO foo VALUES(2, \"world\");
INSERT INTO foo VALUES(1, \"!\");
END;";
db.execute_batch(sql).unwrap();
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
2015-12-13 03:06:03 +08:00
let results: Result<Vec<String>> = query.query_and_then(&[],
2015-12-11 05:48:09 +08:00
|row| row.get_checked(1))
.unwrap()
.collect();
assert_eq!(results.unwrap().concat(), "hello, world!");
}
#[test]
2015-12-11 05:48:09 +08:00
#[cfg_attr(rustfmt, rustfmt_skip)]
fn test_query_and_then_fails() {
let db = checked_memory_handle();
let sql = "BEGIN;
CREATE TABLE foo(x INTEGER, y TEXT);
INSERT INTO foo VALUES(4, \"hello\");
INSERT INTO foo VALUES(3, \", \");
INSERT INTO foo VALUES(2, \"world\");
INSERT INTO foo VALUES(1, \"!\");
END;";
db.execute_batch(sql).unwrap();
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
2015-12-13 03:06:03 +08:00
let bad_type: Result<Vec<f64>> = query.query_and_then(&[],
2015-12-11 05:48:09 +08:00
|row| row.get_checked(1))
.unwrap()
.collect();
2015-12-11 05:48:09 +08:00
assert_eq!(bad_type,
2015-12-13 02:53:58 +08:00
Err(Error {
2015-12-11 05:48:09 +08:00
code: ffi::SQLITE_MISMATCH,
message: "Invalid column type".to_owned(),
}));
2015-12-13 03:06:03 +08:00
let bad_idx: Result<Vec<String>> = query.query_and_then(&[],
2015-12-11 05:48:09 +08:00
|row| row.get_checked(3))
.unwrap()
.collect();
2015-12-11 05:48:09 +08:00
assert_eq!(bad_idx,
2015-12-13 02:53:58 +08:00
Err(Error {
2015-12-11 05:48:09 +08:00
code: ffi::SQLITE_MISUSE,
message: "Invalid column index".to_owned(),
}));
}
#[test]
2015-12-11 05:48:09 +08:00
#[cfg_attr(rustfmt, rustfmt_skip)]
fn test_query_and_then_custom_error() {
let db = checked_memory_handle();
let sql = "BEGIN;
CREATE TABLE foo(x INTEGER, y TEXT);
INSERT INTO foo VALUES(4, \"hello\");
INSERT INTO foo VALUES(3, \", \");
INSERT INTO foo VALUES(2, \"world\");
INSERT INTO foo VALUES(1, \"!\");
END;";
db.execute_batch(sql).unwrap();
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
2015-12-11 05:48:09 +08:00
let results: CustomResult<Vec<String>> = query.query_and_then(&[], |row| {
row.get_checked(1)
.map_err(CustomError::Sqlite)
})
.unwrap()
.collect();
assert_eq!(results.unwrap().concat(), "hello, world!");
}
#[test]
2015-12-11 05:48:09 +08:00
#[cfg_attr(rustfmt, rustfmt_skip)]
fn test_query_and_then_custom_error_fails() {
let db = checked_memory_handle();
let sql = "BEGIN;
CREATE TABLE foo(x INTEGER, y TEXT);
INSERT INTO foo VALUES(4, \"hello\");
INSERT INTO foo VALUES(3, \", \");
INSERT INTO foo VALUES(2, \"world\");
INSERT INTO foo VALUES(1, \"!\");
END;";
db.execute_batch(sql).unwrap();
let mut query = db.prepare("SELECT x, y FROM foo ORDER BY x DESC").unwrap();
2015-12-11 05:48:09 +08:00
let bad_type: CustomResult<Vec<f64>> = query.query_and_then(&[], |row| {
row.get_checked(1)
.map_err(CustomError::Sqlite)
})
.unwrap()
.collect();
2015-12-11 05:48:09 +08:00
assert_eq!(bad_type,
2015-12-13 02:53:58 +08:00
Err(CustomError::Sqlite(Error {
2015-12-11 05:48:09 +08:00
code: ffi::SQLITE_MISMATCH,
message: "Invalid column type".to_owned(),
})));
2015-12-11 05:48:09 +08:00
let bad_idx: CustomResult<Vec<String>> = query.query_and_then(&[], |row| {
row.get_checked(3)
.map_err(CustomError::Sqlite)
})
.unwrap()
.collect();
2015-12-11 05:48:09 +08:00
assert_eq!(bad_idx,
2015-12-13 02:53:58 +08:00
Err(CustomError::Sqlite(Error {
2015-12-11 05:48:09 +08:00
code: ffi::SQLITE_MISUSE,
message: "Invalid column index".to_owned(),
})));
2015-12-11 05:48:09 +08:00
let non_sqlite_err: CustomResult<Vec<String>> = query.query_and_then(&[], |_| {
Err(CustomError::SomeError)
})
.unwrap()
.collect();
assert_eq!(non_sqlite_err, Err(CustomError::SomeError));
}
2015-09-21 09:30:40 +08:00
#[test]
2015-12-11 05:48:09 +08:00
#[cfg_attr(rustfmt, rustfmt_skip)]
2015-09-21 09:30:40 +08:00
fn test_query_row_and_then_custom_error() {
let db = checked_memory_handle();
let sql = "BEGIN;
CREATE TABLE foo(x INTEGER, y TEXT);
INSERT INTO foo VALUES(4, \"hello\");
END;";
db.execute_batch(sql).unwrap();
let query = "SELECT x, y FROM foo ORDER BY x DESC";
2015-12-11 05:48:09 +08:00
let results: CustomResult<String> = db.query_row_and_then(query, &[], |row| {
row.get_checked(1).map_err(CustomError::Sqlite)
});
2015-09-21 09:30:40 +08:00
assert_eq!(results.unwrap(), "hello");
}
#[test]
2015-12-11 05:48:09 +08:00
#[cfg_attr(rustfmt, rustfmt_skip)]
2015-09-21 09:30:40 +08:00
fn test_query_row_and_then_custom_error_fails() {
let db = checked_memory_handle();
let sql = "BEGIN;
CREATE TABLE foo(x INTEGER, y TEXT);
INSERT INTO foo VALUES(4, \"hello\");
END;";
db.execute_batch(sql).unwrap();
let query = "SELECT x, y FROM foo ORDER BY x DESC";
2015-12-11 05:48:09 +08:00
let bad_type: CustomResult<f64> = db.query_row_and_then(query, &[], |row| {
row.get_checked(1).map_err(CustomError::Sqlite)
});
2015-09-21 09:30:40 +08:00
2015-12-11 05:48:09 +08:00
assert_eq!(bad_type,
2015-12-13 02:53:58 +08:00
Err(CustomError::Sqlite(Error {
2015-12-11 05:48:09 +08:00
code: ffi::SQLITE_MISMATCH,
message: "Invalid column type".to_owned(),
})));
2015-09-21 09:30:40 +08:00
2015-12-11 05:48:09 +08:00
let bad_idx: CustomResult<String> = db.query_row_and_then(query, &[], |row| {
row.get_checked(3).map_err(CustomError::Sqlite)
});
2015-09-21 09:30:40 +08:00
2015-12-11 05:48:09 +08:00
assert_eq!(bad_idx,
2015-12-13 02:53:58 +08:00
Err(CustomError::Sqlite(Error {
2015-12-11 05:48:09 +08:00
code: ffi::SQLITE_MISUSE,
message: "Invalid column index".to_owned(),
})));
2015-09-21 09:30:40 +08:00
2015-12-11 05:48:09 +08:00
let non_sqlite_err: CustomResult<String> = db.query_row_and_then(query, &[], |_| {
Err(CustomError::SomeError)
});
2015-09-21 09:30:40 +08:00
assert_eq!(non_sqlite_err, Err(CustomError::SomeError));
}
}
2014-10-20 07:56:41 +08:00
}