//! Prepared statements cache for faster execution.
usecrate::raw_statement::RawStatement; usecrate::{Connection, PrepFlags, Result, Statement}; use hashlink::LruCache; use std::cell::RefCell; use std::ops::{Deref, DerefMut}; use std::sync::Arc;
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`](Connection::prepare_cached) once it is dropped. /// /// ```rust,no_run /// # use rusqlite::{Connection, Result}; /// fn insert_new_people(conn: &Connection) -> Result<()> { /// { /// let mut stmt = conn.prepare_cached("INSERT INTO People (name) VALUES (?1)")?; /// stmt.execute(["Joe Smith"])?; /// } /// { /// // This will return the same underlying SQLite statement handle without /// // having to prepare it again. /// let mut stmt = conn.prepare_cached("INSERT INTO People (name) VALUES (?1)")?; /// 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. #[inline] pubfn prepare_cached(&self, sql: &str) -> Result<CachedStatement<'_>> { self.cache.get(self, sql)
}
/// Set the maximum number of cached prepared statements this connection /// will hold. By default, a connection will hold a relatively small /// number of cached statements. If you need more, or know that you /// will not use cached statements, you /// can set the capacity manually using this method. #[inline] pubfn set_prepared_statement_cache_capacity(&self, capacity: usize) { self.cache.set_capacity(capacity);
}
/// Remove/finalize all prepared statements currently in the cache. #[inline] pubfn flush_prepared_statement_cache(&self) { self.cache.flush();
}
}
#[allow(clippy::non_send_fields_in_send_ty)] unsafeimpl Send for StatementCache {}
/// Cacheable statement. /// /// Statement will return automatically to the cache by default. /// If you want the statement to be discarded, call /// [`discard()`](CachedStatement::discard) on it. pubstruct CachedStatement<'conn> {
stmt: Option<Statement<'conn>>,
cache: &'conn StatementCache,
}
impl<'conn> Deref for CachedStatement<'conn> { type Target = Statement<'conn>;
/// Discard the statement, preventing it from being returned to its /// [`Connection`]'s collection of cached statements. #[inline] pubfn discard(mutself) { self.stmt = None;
}
}
// Search the cache for a prepared-statement object that implements `sql`. // If no such prepared-statement can be found, allocate and prepare a new one. // // # Failure // // Will return `Err` if no cached statement can be found and the underlying // SQLite prepare call fails. fn get<'conn>(
&'conn self,
conn: &'conn Connection,
sql: &str,
) -> Result<CachedStatement<'conn>> { let trimmed = sql.trim(); letmut cache = self.0.borrow_mut(); let stmt = match cache.remove(trimmed) {
Some(raw_stmt) => Ok(Statement::new(conn, raw_stmt)),
None => conn.prepare_with_flags(trimmed, PrepFlags::SQLITE_PREPARE_PERSISTENT),
};
stmt.map(|mut stmt| {
stmt.stmt.set_statement_cache_key(trimmed);
CachedStatement::new(stmt, self)
})
}
// Return a statement to the cache. fn cache_stmt(&self, stmt: RawStatement) { if stmt.is_null() { return;
} letmut cache = self.0.borrow_mut();
stmt.clear_bindings(); iflet Some(sql) = stmt.statement_cache_key() {
cache.insert(sql, stmt);
} else {
debug_assert!( false, "bug in statement cache code, statement returned to cache that without key"
);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.