diff --git a/rusqlite-macros/Cargo.toml b/rusqlite-macros/Cargo.toml index 3d40775..c50ebcf 100644 --- a/rusqlite-macros/Cargo.toml +++ b/rusqlite-macros/Cargo.toml @@ -12,5 +12,5 @@ categories = ["database"] proc-macro = true [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" diff --git a/rusqlite-macros/src/lib.rs b/rusqlite-macros/src/lib.rs index 8dda22c..583f839 100644 --- a/rusqlite-macros/src/lib.rs +++ b/rusqlite-macros/src/lib.rs @@ -58,11 +58,15 @@ fn try_bind(input: TokenStream) -> Result { let mut res = TokenStream::new(); for (i, name) in info.names.iter().enumerate() { res.extend(Some(stmt.clone())); + let offset = match name.as_bytes()[0] { + b'$' | b'@' | b'#' | b':' => 1, + _ => 0, // captured identifier: {...} + }; res.extend(respan( parse_ts(&format!( ".raw_bind_parameter({}, &{})?;", i + 1, - &name[1..] + &name[offset..] )), call_site, )); diff --git a/rusqlite-macros/tests/test.rs b/rusqlite-macros/tests/test.rs index 785ca9b..1499718 100644 --- a/rusqlite-macros/tests/test.rs +++ b/rusqlite-macros/tests/test.rs @@ -16,7 +16,30 @@ fn test_literal() -> Result { let first_name = "El"; let last_name = "Barto"; 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(()) } diff --git a/src/lib.rs b/src/lib.rs index 4106838..a9a3af4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -220,9 +220,9 @@ macro_rules! named_params { /// Captured identifiers in SQL /// -/// * only SQLite `$x` / `@x` / `:x` syntax works (Rust `&x` syntax does not -/// work). +/// * SQLite `$x` / `@x` / `:x` syntax works (Rust `&x` syntax does not work). /// * `$x.y` expression does not work. +/// * `{x}` and `{x.y}` work /// /// # Example /// @@ -249,9 +249,9 @@ macro_rules! prepare_and_bind { /// Captured identifiers in SQL /// -/// * only SQLite `$x` / `@x` / `:x` syntax works (Rust `&x` syntax does not -/// work). +/// * SQLite `$x` / `@x` / `:x` syntax works (Rust `&x` syntax does not work). /// * `$x.y` expression does not work. +/// * `{x}` and `{x.y}` work #[cfg(feature = "rusqlite-macros")] #[cfg_attr(docsrs, doc(cfg(feature = "rusqlite-macros")))] #[macro_export]