Fail to create a new CachedStatement.

This commit is contained in:
Gwenael Treguier 2015-12-17 20:33:34 +01:00
parent 109c26fea4
commit 85fb89b280

View File

@ -2,6 +2,7 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::ops::{Deref, DerefMut};
use {Result, Connection, Statement}; use {Result, Connection, Statement};
/// Prepared statements cache. /// Prepared statements cache.
@ -17,6 +18,20 @@ pub struct CachedStatement<'conn> {
pub cacheable: bool, pub cacheable: bool,
} }
impl<'conn> Deref for CachedStatement<'conn> {
type Target = Statement<'conn>;
fn deref(&self) -> &Statement<'conn> {
self.stmt.as_ref().unwrap()
}
}
impl<'conn> DerefMut for CachedStatement<'conn> {
fn deref_mut(&mut self) -> &mut Statement<'conn> {
self.stmt.as_mut().unwrap()
}
}
impl<'conn> Drop for CachedStatement<'conn> { impl<'conn> Drop for CachedStatement<'conn> {
#[allow(unused_must_use)] #[allow(unused_must_use)]
fn drop(&mut self) { fn drop(&mut self) {
@ -28,6 +43,18 @@ impl<'conn> Drop for CachedStatement<'conn> {
} }
} }
impl<'conn> CachedStatement<'conn> {
fn new(stmt: Statement<'conn>,
cache: RefCell<StatementCache<'conn>>)
-> CachedStatement<'conn> {
CachedStatement {
stmt: Some(stmt),
cache: cache,
cacheable: true,
}
}
}
impl<'conn> StatementCache<'conn> { impl<'conn> StatementCache<'conn> {
/// Create a statement cache. /// Create a statement cache.
pub fn new(conn: &'conn Connection, capacity: usize) -> StatementCache<'conn> { pub fn new(conn: &'conn Connection, capacity: usize) -> StatementCache<'conn> {
@ -43,11 +70,12 @@ impl<'conn> StatementCache<'conn> {
/// # Failure /// # Failure
/// ///
/// Will return `Err` if no cached statement can be found and the underlying SQLite prepare call fails. /// Will return `Err` if no cached statement can be found and the underlying SQLite prepare call fails.
pub fn get(&mut self, sql: &str) -> Result<Statement<'conn>> { pub fn get(&mut self, sql: &str) -> Result<CachedStatement<'conn>> {
match self.cache.iter().rposition(|entry| entry.eq(sql)) { let stmt = match self.cache.iter().rposition(|entry| entry.eq(sql)) {
Some(index) => Ok(self.cache.swap_remove_front(index).unwrap()), // FIXME Not LRU compliant Some(index) => Ok(self.cache.swap_remove_front(index).unwrap()), // FIXME Not LRU compliant
_ => self.conn.prepare(sql), _ => self.conn.prepare(sql),
} };
stmt.map(|stmt| CachedStatement::new(stmt, RefCell::new(self)))
} }
/// If `discard` is true, then the statement is deleted immediately. /// If `discard` is true, then the statement is deleted immediately.
@ -59,7 +87,8 @@ impl<'conn> StatementCache<'conn> {
/// Will return `Err` if `stmt` (or the already cached statement implementing the same SQL) statement is `discard`ed /// Will return `Err` if `stmt` (or the already cached statement implementing the same SQL) statement is `discard`ed
/// and the underlying SQLite finalize call fails. /// and the underlying SQLite finalize call fails.
fn release(&mut self, mut stmt: Statement<'conn>) { fn release(&mut self, mut stmt: Statement<'conn>) {
if self.cache.capacity() == self.cache.len() { // is full if self.cache.capacity() == self.cache.len() {
// is full
self.cache.pop_back(); // LRU dropped self.cache.pop_back(); // LRU dropped
} }
stmt.reset_if_needed(); stmt.reset_if_needed();