mirror of
https://github.com/isar/rusqlite.git
synced 2025-10-30 21:38:57 +08:00
Merge pull request #1346 from gwenn/captured_identifiers
Captured identifiers in SQL strings
This commit is contained in:
66
src/lib.rs
66
src/lib.rs
@@ -88,6 +88,9 @@ pub use crate::transaction::TransactionState;
|
||||
pub use crate::transaction::{DropBehavior, Savepoint, Transaction, TransactionBehavior};
|
||||
pub use crate::types::ToSql;
|
||||
pub use crate::version::*;
|
||||
#[cfg(feature = "rusqlite-macros")]
|
||||
#[doc(hidden)]
|
||||
pub use rusqlite_macros::__bind;
|
||||
|
||||
mod error;
|
||||
|
||||
@@ -218,6 +221,51 @@ macro_rules! named_params {
|
||||
};
|
||||
}
|
||||
|
||||
/// Captured identifiers in SQL
|
||||
///
|
||||
/// * only SQLite `$x` / `@x` / `:x` syntax works (Rust `&x` syntax does not
|
||||
/// work).
|
||||
/// * `$x.y` expression does not work.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust, no_run
|
||||
/// # use rusqlite::{prepare_and_bind, Connection, Result, Statement};
|
||||
///
|
||||
/// fn misc(db: &Connection) -> Result<Statement> {
|
||||
/// let name = "Lisa";
|
||||
/// let age = 8;
|
||||
/// let smart = true;
|
||||
/// Ok(prepare_and_bind!(db, "SELECT $name, @age, :smart;"))
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(feature = "rusqlite-macros")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rusqlite-macros")))]
|
||||
#[macro_export]
|
||||
macro_rules! prepare_and_bind {
|
||||
($conn:expr, $sql:literal) => {{
|
||||
let mut stmt = $conn.prepare($sql)?;
|
||||
$crate::__bind!(stmt $sql);
|
||||
stmt
|
||||
}};
|
||||
}
|
||||
|
||||
/// Captured identifiers in SQL
|
||||
///
|
||||
/// * only SQLite `$x` / `@x` / `:x` syntax works (Rust `&x` syntax does not
|
||||
/// work).
|
||||
/// * `$x.y` expression does not work.
|
||||
#[cfg(feature = "rusqlite-macros")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rusqlite-macros")))]
|
||||
#[macro_export]
|
||||
macro_rules! prepare_cached_and_bind {
|
||||
($conn:expr, $sql:literal) => {{
|
||||
let mut stmt = $conn.prepare_cached($sql)?;
|
||||
$crate::__bind!(stmt $sql);
|
||||
stmt
|
||||
}};
|
||||
}
|
||||
|
||||
/// A typedef of the result returned by many methods.
|
||||
pub type Result<T, E = Error> = result::Result<T, E>;
|
||||
|
||||
@@ -2117,9 +2165,25 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn db_readonly() -> Result<()> {
|
||||
fn db_readonly() -> Result<()> {
|
||||
let db = Connection::open_in_memory()?;
|
||||
assert!(!db.is_readonly(MAIN_DB)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "rusqlite-macros")]
|
||||
fn prepare_and_bind() -> Result<()> {
|
||||
let db = Connection::open_in_memory()?;
|
||||
let name = "Lisa";
|
||||
let age = 8;
|
||||
let mut stmt = prepare_and_bind!(db, "SELECT $name, $age;");
|
||||
let (v1, v2) = stmt
|
||||
.raw_query()
|
||||
.next()
|
||||
.and_then(|o| o.ok_or(Error::QueryReturnedNoRows))
|
||||
.and_then(|r| Ok((r.get::<_, String>(0)?, r.get::<_, i64>(1)?)))?;
|
||||
assert_eq!((v1.as_str(), v2), (name, age));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user