mirror of
https://github.com/isar/rusqlite.git
synced 2025-04-02 04:12:59 +08:00
Add Connection::prepare_cached.
This commit is contained in:
parent
ed72da92ef
commit
3c15eb0218
76
src/cache.rs
76
src/cache.rs
@ -6,6 +6,38 @@ use std::ops::{Deref, DerefMut};
|
|||||||
use {Result, Connection, Statement};
|
use {Result, Connection, Statement};
|
||||||
use raw_statement::RawStatement;
|
use raw_statement::RawStatement;
|
||||||
|
|
||||||
|
impl Connection {
|
||||||
|
/// Prepare a SQL statement for execution, returning a previously prepared (but
|
||||||
|
/// not currently in-use) statement if one is available. The returned statement
|
||||||
|
/// will be cached for reuse by future calls to `prepare_cached` once it is
|
||||||
|
/// dropped.
|
||||||
|
///
|
||||||
|
/// ```rust,no_run
|
||||||
|
/// # use rusqlite::{Connection, Result};
|
||||||
|
/// fn insert_new_people(conn: &Connection) -> Result<()> {
|
||||||
|
/// {
|
||||||
|
/// let mut stmt = try!(conn.prepare_cached("INSERT INTO People (name) VALUES (?)"));
|
||||||
|
/// try!(stmt.execute(&[&"Joe Smith"]));
|
||||||
|
/// }
|
||||||
|
/// {
|
||||||
|
/// // This will return the same underlying SQLite statement handle without
|
||||||
|
/// // having to prepare it again.
|
||||||
|
/// let mut stmt = try!(conn.prepare_cached("INSERT INTO People (name) VALUES (?)"));
|
||||||
|
/// 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_cached<'a>(&'a self, sql: &str) -> Result<CachedStatement<'a, 'a>> {
|
||||||
|
self.cache.get(&self, sql)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Prepared statements LRU cache.
|
/// Prepared statements LRU cache.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StatementCache {
|
pub struct StatementCache {
|
||||||
@ -93,21 +125,6 @@ impl StatementCache {
|
|||||||
stmt.clear_bindings();
|
stmt.clear_bindings();
|
||||||
cache.push_front(stmt)
|
cache.push_front(stmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flush the prepared statement cache
|
|
||||||
pub fn clear(&self) {
|
|
||||||
self.cache.borrow_mut().clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return current cache size.
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
self.cache.borrow().len()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return maximum cache size.
|
|
||||||
pub fn capacity(&self) -> usize {
|
|
||||||
self.cache.borrow().capacity()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -115,16 +132,31 @@ mod test {
|
|||||||
use Connection;
|
use Connection;
|
||||||
use super::StatementCache;
|
use super::StatementCache;
|
||||||
|
|
||||||
|
impl StatementCache {
|
||||||
|
fn clear(&self) {
|
||||||
|
self.cache.borrow_mut().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn len(&self) -> usize {
|
||||||
|
self.cache.borrow().len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn capacity(&self) -> usize {
|
||||||
|
self.cache.borrow().capacity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cache() {
|
fn test_cache() {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory().unwrap();
|
||||||
let cache = StatementCache::with_capacity(15);
|
let cache = &db.cache;
|
||||||
|
let initial_capacity = cache.capacity();
|
||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
assert_eq!(15, cache.capacity());
|
assert!(initial_capacity > 0);
|
||||||
|
|
||||||
let sql = "PRAGMA schema_version";
|
let sql = "PRAGMA schema_version";
|
||||||
{
|
{
|
||||||
let mut stmt = cache.get(&db, sql).unwrap();
|
let mut stmt = db.prepare_cached(sql).unwrap();
|
||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
assert_eq!(0,
|
assert_eq!(0,
|
||||||
stmt.query(&[]).unwrap().get_expected_row().unwrap().get::<i32,i64>(0));
|
stmt.query(&[]).unwrap().get_expected_row().unwrap().get::<i32,i64>(0));
|
||||||
@ -132,7 +164,7 @@ mod test {
|
|||||||
assert_eq!(1, cache.len());
|
assert_eq!(1, cache.len());
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut stmt = cache.get(&db, sql).unwrap();
|
let mut stmt = db.prepare_cached(sql).unwrap();
|
||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
assert_eq!(0,
|
assert_eq!(0,
|
||||||
stmt.query(&[]).unwrap().get_expected_row().unwrap().get::<i32,i64>(0));
|
stmt.query(&[]).unwrap().get_expected_row().unwrap().get::<i32,i64>(0));
|
||||||
@ -141,17 +173,17 @@ mod test {
|
|||||||
|
|
||||||
cache.clear();
|
cache.clear();
|
||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
assert_eq!(15, cache.capacity());
|
assert_eq!(initial_capacity, cache.capacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_discard() {
|
fn test_discard() {
|
||||||
let db = Connection::open_in_memory().unwrap();
|
let db = Connection::open_in_memory().unwrap();
|
||||||
let cache = StatementCache::with_capacity(15);
|
let cache = &db.cache;
|
||||||
|
|
||||||
let sql = "PRAGMA schema_version";
|
let sql = "PRAGMA schema_version";
|
||||||
{
|
{
|
||||||
let mut stmt = cache.get(&db, sql).unwrap();
|
let mut stmt = db.prepare_cached(sql).unwrap();
|
||||||
assert_eq!(0, cache.len());
|
assert_eq!(0, cache.len());
|
||||||
assert_eq!(0,
|
assert_eq!(0,
|
||||||
stmt.query(&[]).unwrap().get_expected_row().unwrap().get::<i32,i64>(0));
|
stmt.query(&[]).unwrap().get_expected_row().unwrap().get::<i32,i64>(0));
|
||||||
|
@ -77,6 +77,7 @@ use libc::{c_int, c_char};
|
|||||||
use types::{ToSql, FromSql};
|
use types::{ToSql, FromSql};
|
||||||
use error::{error_from_sqlite_code, error_from_handle};
|
use error::{error_from_sqlite_code, error_from_handle};
|
||||||
use raw_statement::RawStatement;
|
use raw_statement::RawStatement;
|
||||||
|
use cache::StatementCache;
|
||||||
|
|
||||||
pub use transaction::{SqliteTransaction, Transaction, TransactionBehavior};
|
pub use transaction::{SqliteTransaction, Transaction, TransactionBehavior};
|
||||||
pub use error::{SqliteError, Error};
|
pub use error::{SqliteError, Error};
|
||||||
@ -98,6 +99,9 @@ mod raw_statement;
|
|||||||
#[cfg(feature = "functions")]pub mod functions;
|
#[cfg(feature = "functions")]pub mod functions;
|
||||||
#[cfg(feature = "blob")]pub mod blob;
|
#[cfg(feature = "blob")]pub mod blob;
|
||||||
|
|
||||||
|
// Number of cached prepared statements we'll hold on to.
|
||||||
|
const STATEMENT_CACHE_DEFAULT_CAPACITY: usize = 16;
|
||||||
|
|
||||||
/// Old name for `Result`. `SqliteResult` is deprecated.
|
/// Old name for `Result`. `SqliteResult` is deprecated.
|
||||||
pub type SqliteResult<T> = Result<T>;
|
pub type SqliteResult<T> = Result<T>;
|
||||||
|
|
||||||
@ -150,6 +154,7 @@ pub type SqliteConnection = Connection;
|
|||||||
/// A connection to a SQLite database.
|
/// A connection to a SQLite database.
|
||||||
pub struct Connection {
|
pub struct Connection {
|
||||||
db: RefCell<InnerConnection>,
|
db: RefCell<InnerConnection>,
|
||||||
|
cache: StatementCache,
|
||||||
path: Option<PathBuf>,
|
path: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,6 +199,7 @@ impl Connection {
|
|||||||
InnerConnection::open_with_flags(&c_path, flags).map(|db| {
|
InnerConnection::open_with_flags(&c_path, flags).map(|db| {
|
||||||
Connection {
|
Connection {
|
||||||
db: RefCell::new(db),
|
db: RefCell::new(db),
|
||||||
|
cache: StatementCache::with_capacity(STATEMENT_CACHE_DEFAULT_CAPACITY),
|
||||||
path: Some(path.as_ref().to_path_buf()),
|
path: Some(path.as_ref().to_path_buf()),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -212,6 +218,7 @@ impl Connection {
|
|||||||
InnerConnection::open_with_flags(&c_memory, flags).map(|db| {
|
InnerConnection::open_with_flags(&c_memory, flags).map(|db| {
|
||||||
Connection {
|
Connection {
|
||||||
db: RefCell::new(db),
|
db: RefCell::new(db),
|
||||||
|
cache: StatementCache::with_capacity(STATEMENT_CACHE_DEFAULT_CAPACITY),
|
||||||
path: None,
|
path: None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user