Make StatementCache hold RawStatements instead of Statements.

This commit is contained in:
John Gallagher 2016-05-17 11:55:10 -05:00
parent f6aba80f4b
commit 1978568d01
2 changed files with 17 additions and 16 deletions

View File

@ -4,12 +4,13 @@ use std::cell::RefCell;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use {Result, Connection, Statement}; use {Result, Connection, Statement};
use raw_statement::RawStatement;
/// Prepared statements LRU cache. /// Prepared statements LRU cache.
#[derive(Debug)] #[derive(Debug)]
pub struct StatementCache<'conn> { pub struct StatementCache<'conn> {
conn: &'conn Connection, conn: &'conn Connection,
cache: RefCell<VecDeque<Statement<'conn>>>, // back = LRU cache: RefCell<VecDeque<RawStatement>>, // back = LRU
} }
/// Cacheable statement. /// Cacheable statement.
@ -39,7 +40,7 @@ impl<'c, 's> Drop for CachedStatement<'c, 's> {
#[allow(unused_must_use)] #[allow(unused_must_use)]
fn drop(&mut self) { fn drop(&mut self) {
if let Some(stmt) = self.stmt.take() { if let Some(stmt) = self.stmt.take() {
self.cache.cache_stmt(stmt); self.cache.cache_stmt(stmt.into());
} }
} }
} }
@ -74,15 +75,18 @@ impl<'conn> StatementCache<'conn> {
/// 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<'s>(&'s self, sql: &str) -> Result<CachedStatement<'conn, 's>> { pub fn get<'s>(&'s self, sql: &str) -> Result<CachedStatement<'conn, 's>> {
let mut cache = self.cache.borrow_mut(); let mut cache = self.cache.borrow_mut();
let stmt = match cache.iter().rposition(|entry| entry.eq(sql)) { let stmt = match cache.iter().rposition(|entry| entry.sql().to_bytes().eq(sql.as_bytes())) {
Some(index) => Ok(cache.swap_remove_front(index).unwrap()), // FIXME Not LRU compliant Some(index) => {
let raw_stmt = cache.swap_remove_front(index).unwrap(); // FIXME Not LRU compliant
Ok(Statement::new(self.conn, raw_stmt))
}
_ => self.conn.prepare(sql), _ => self.conn.prepare(sql),
}; };
stmt.map(|stmt| CachedStatement::new(stmt, self)) stmt.map(|stmt| CachedStatement::new(stmt, self))
} }
// Return a statement to the cache. // Return a statement to the cache.
fn cache_stmt(&self, mut stmt: Statement<'conn>) { fn cache_stmt(&self, stmt: RawStatement) {
let mut cache = self.cache.borrow_mut(); let mut cache = self.cache.borrow_mut();
if cache.capacity() == cache.len() { if cache.capacity() == cache.len() {
// is full // is full

View File

@ -901,17 +901,6 @@ impl<'conn> Statement<'conn> {
Ok(()) Ok(())
} }
#[cfg(feature = "cache")]
fn clear_bindings(&mut self) {
self.stmt.clear_bindings();
}
#[cfg(feature = "cache")]
fn eq(&self, sql: &str) -> bool {
let c_slice = self.stmt.sql().to_bytes();
sql.as_bytes().eq(c_slice)
}
fn finalize_(&mut self) -> Result<()> { fn finalize_(&mut self) -> Result<()> {
let mut stmt = RawStatement::new(ptr::null_mut()); let mut stmt = RawStatement::new(ptr::null_mut());
mem::swap(&mut stmt, &mut self.stmt); mem::swap(&mut stmt, &mut self.stmt);
@ -919,6 +908,14 @@ impl<'conn> Statement<'conn> {
} }
} }
impl<'conn> Into<RawStatement> for Statement<'conn> {
fn into(mut self) -> RawStatement {
let mut stmt = RawStatement::new(ptr::null_mut());
mem::swap(&mut stmt, &mut self.stmt);
stmt
}
}
impl<'conn> fmt::Debug for Statement<'conn> { impl<'conn> fmt::Debug for Statement<'conn> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let sql = str::from_utf8(self.stmt.sql().to_bytes()); let sql = str::from_utf8(self.stmt.sql().to_bytes());