mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-25 02:21:37 +08:00
Fix macro hygiene issue
This commit is contained in:
parent
0e369ba878
commit
f0670ccadd
@ -1,6 +1,6 @@
|
||||
//! Private implementation details of `rusqlite`.
|
||||
|
||||
use proc_macro::{Delimiter, Literal, TokenStream, TokenTree};
|
||||
use proc_macro::{Delimiter, Group, Literal, Span, TokenStream, TokenTree};
|
||||
|
||||
use fallible_iterator::FallibleIterator;
|
||||
use sqlite3_parser::ast::{ParameterInfo, ToTokens};
|
||||
@ -58,15 +58,19 @@ fn try_bind(input: TokenStream) -> Result<TokenStream> {
|
||||
return Err("Mixing named and numbered parameters is not supported.".to_string());
|
||||
}
|
||||
|
||||
let call_site = literal.span();
|
||||
let mut res = TokenStream::new();
|
||||
for (i, name) in info.names.iter().enumerate() {
|
||||
//eprintln!("(i: {}, name: {})", i + 1, &name[1..]);
|
||||
res.extend(Some(stmt.clone()));
|
||||
res.extend(parse_ts(&format!(
|
||||
".raw_bind_parameter({}, &{})?;",
|
||||
i + 1,
|
||||
&name[1..]
|
||||
)));
|
||||
res.extend(respan(
|
||||
parse_ts(&format!(
|
||||
".raw_bind_parameter({}, &{})?;",
|
||||
i + 1,
|
||||
&name[1..]
|
||||
)),
|
||||
call_site,
|
||||
));
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
@ -93,6 +97,24 @@ fn strip_matches<'a>(s: &'a str, pattern: &str) -> &'a str {
|
||||
.unwrap_or(s)
|
||||
}
|
||||
|
||||
fn respan(ts: TokenStream, span: Span) -> TokenStream {
|
||||
let mut res = TokenStream::new();
|
||||
for tt in ts {
|
||||
let tt = match tt {
|
||||
TokenTree::Ident(mut ident) => {
|
||||
ident.set_span(ident.span().resolved_at(span).located_at(span));
|
||||
TokenTree::Ident(ident)
|
||||
}
|
||||
TokenTree::Group(group) => {
|
||||
TokenTree::Group(Group::new(group.delimiter(), respan(group.stream(), span)))
|
||||
}
|
||||
_ => tt,
|
||||
};
|
||||
res.extend(Some(tt))
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn parse_ts(s: &str) -> TokenStream {
|
||||
s.parse().unwrap()
|
||||
}
|
||||
|
25
src/lib.rs
25
src/lib.rs
@ -215,11 +215,26 @@ 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;"))
|
||||
/// }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! prepare_and_bind {
|
||||
($conn:expr, $sql:literal) => {{
|
||||
#[cfg(trick_rust_analyzer_into_highlighting_interpolated_bits)]
|
||||
format_args!($sql);
|
||||
let mut stmt = $conn.prepare($sql)?;
|
||||
$crate::__bind!(stmt $sql);
|
||||
stmt
|
||||
@ -227,11 +242,13 @@ macro_rules! prepare_and_bind {
|
||||
}
|
||||
|
||||
/// Captured identifiers in SQL
|
||||
///
|
||||
/// * only SQLite `$x` / `@x` / `:x` syntax works (Rust `&x` syntax does not
|
||||
/// work).
|
||||
/// * `$x.y` expression does not work.
|
||||
#[macro_export]
|
||||
macro_rules! prepare_cached_and_bind {
|
||||
($conn:expr, $sql:literal) => {{
|
||||
#[cfg(trick_rust_analyzer_into_highlighting_interpolated_bits)]
|
||||
format_args!($sql);
|
||||
let mut stmt = $conn.prepare_cached($sql)?;
|
||||
$crate::__bind!(stmt $sql);
|
||||
stmt
|
||||
|
Loading…
Reference in New Issue
Block a user