Support Rust expression like {x.y} in SQL strings

This commit is contained in:
gwenn 2023-08-20 10:35:26 +02:00
parent e8f73c93c4
commit b86d9321b5
4 changed files with 34 additions and 7 deletions

View File

@ -12,5 +12,5 @@ categories = ["database"]
proc-macro = true proc-macro = true
[dependencies] [dependencies]
sqlite3-parser = { version = "0.9", default-features = false, features = ["YYNOERRORRECOVERY"] } sqlite3-parser = { version = "0.10.0", default-features = false, features = ["YYNOERRORRECOVERY", "rust_variable"] }
fallible-iterator = "0.3" fallible-iterator = "0.3"

View File

@ -58,11 +58,15 @@ fn try_bind(input: TokenStream) -> Result<TokenStream> {
let mut res = TokenStream::new(); let mut res = TokenStream::new();
for (i, name) in info.names.iter().enumerate() { for (i, name) in info.names.iter().enumerate() {
res.extend(Some(stmt.clone())); res.extend(Some(stmt.clone()));
let offset = match name.as_bytes()[0] {
b'$' | b'@' | b'#' | b':' => 1,
_ => 0, // captured identifier: {...}
};
res.extend(respan( res.extend(respan(
parse_ts(&format!( parse_ts(&format!(
".raw_bind_parameter({}, &{})?;", ".raw_bind_parameter({}, &{})?;",
i + 1, i + 1,
&name[1..] &name[offset..]
)), )),
call_site, call_site,
)); ));

View File

@ -16,7 +16,30 @@ fn test_literal() -> Result {
let first_name = "El"; let first_name = "El";
let last_name = "Barto"; let last_name = "Barto";
let mut stmt = Stmt; let mut stmt = Stmt;
__bind!(stmt "SELECT $first_name, $last_name"); __bind!(stmt "SELECT $first_name, {last_name}");
Ok(())
}
#[test]
fn test_tuple() -> Result {
let names = ("El", "Barto");
let mut stmt = Stmt;
__bind!(stmt "SELECT {names.0}, {names.1}");
Ok(())
}
#[test]
fn test_struct() -> Result {
struct Person<'s> {
first_name: &'s str,
last_name: &'s str,
}
let p = Person {
first_name: "El",
last_name: "Barto",
};
let mut stmt = Stmt;
__bind!(stmt "SELECT {p.first_name}, {p.last_name}");
Ok(()) Ok(())
} }

View File

@ -220,9 +220,9 @@ macro_rules! named_params {
/// Captured identifiers in SQL /// Captured identifiers in SQL
/// ///
/// * only SQLite `$x` / `@x` / `:x` syntax works (Rust `&x` syntax does not /// * SQLite `$x` / `@x` / `:x` syntax works (Rust `&x` syntax does not work).
/// work).
/// * `$x.y` expression does not work. /// * `$x.y` expression does not work.
/// * `{x}` and `{x.y}` work
/// ///
/// # Example /// # Example
/// ///
@ -249,9 +249,9 @@ macro_rules! prepare_and_bind {
/// Captured identifiers in SQL /// Captured identifiers in SQL
/// ///
/// * only SQLite `$x` / `@x` / `:x` syntax works (Rust `&x` syntax does not /// * SQLite `$x` / `@x` / `:x` syntax works (Rust `&x` syntax does not work).
/// work).
/// * `$x.y` expression does not work. /// * `$x.y` expression does not work.
/// * `{x}` and `{x.y}` work
#[cfg(feature = "rusqlite-macros")] #[cfg(feature = "rusqlite-macros")]
#[cfg_attr(docsrs, doc(cfg(feature = "rusqlite-macros")))] #[cfg_attr(docsrs, doc(cfg(feature = "rusqlite-macros")))]
#[macro_export] #[macro_export]