mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-25 02:21:37 +08:00
Support Rust expression like {x.y}
in SQL strings
This commit is contained in:
parent
e8f73c93c4
commit
b86d9321b5
@ -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"
|
||||||
|
@ -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,
|
||||||
));
|
));
|
||||||
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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]
|
||||||
|
Loading…
Reference in New Issue
Block a user