From 0a74b16f4f4d502da6319d7eccfd1edbb38cd819 Mon Sep 17 00:00:00 2001 From: Mike Ledger Date: Fri, 3 Jul 2020 00:02:32 +1000 Subject: [PATCH] support string concatenation in query* --- sqlx-macros/src/query/input.rs | 26 +++++++++++++++++++++++--- src/macros.rs | 16 ++++++++-------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/sqlx-macros/src/query/input.rs b/sqlx-macros/src/query/input.rs index 0757f1dc..a1e814fd 100644 --- a/sqlx-macros/src/query/input.rs +++ b/sqlx-macros/src/query/input.rs @@ -4,12 +4,13 @@ use std::fs; use proc_macro2::{Ident, Span}; use quote::format_ident; use syn::parse::{Parse, ParseStream}; -use syn::{Expr, LitBool, LitStr}; +use syn::{Expr, LitBool, LitStr, Token}; use syn::{ExprArray, Type}; /// Macro input shared by `query!()` and `query_file!()` pub struct QueryMacroInput { pub(super) src: String, + #[cfg_attr(not(feature = "offline"), allow(dead_code))] pub(super) src_span: Span, @@ -51,8 +52,27 @@ impl Parse for QueryMacroInput { let _ = input.parse::()?; if key == "source" { - let lit_str = input.parse::()?; - query_src = Some((QuerySrc::String(lit_str.value()), lit_str.span())); + let mut fragments: Vec = Vec::new(); + 'source_parser: while !input.is_empty() { + if input.lookahead1().peek(LitStr) { + fragments.push(input.parse()?); + if input.lookahead1().peek(Token![+]) { + input.parse::(); + } else { + break 'source_parser; + } + } else { + break 'source_parser; + } + } + if fragments.len() == 0 { + return Err(syn::Error::new_spanned(key, "no source given")); + } + query_src = Some(( + QuerySrc::String(fragments.iter().map(LitStr::value).collect()), + input.span(), + )); + } else if key == "source_file" { let lit_str = input.parse::()?; query_src = Some((QuerySrc::File(lit_str.value()), lit_str.span())); diff --git a/src/macros.rs b/src/macros.rs index 09320646..0ea28f9c 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -257,14 +257,14 @@ macro_rules! query ( // by emitting a macro definition from our proc-macro containing the result tokens, // we no longer have a need for `proc-macro-hack` - ($query:literal) => ({ + ($query:expr) => ({ #[macro_use] mod _macro_result { $crate::sqlx_macros::expand_query!(source = $query); } macro_result!() }); - ($query:literal, $($args:expr),*$(,)?) => ({ + ($query:expr, $($args:expr),*$(,)?) => ({ #[macro_use] mod _macro_result { $crate::sqlx_macros::expand_query!(source = $query, args = [$($args),*]); @@ -278,14 +278,14 @@ macro_rules! query ( #[macro_export] #[cfg_attr(docsrs, doc(cfg(feature = "macros")))] macro_rules! query_unchecked ( - ($query:literal) => ({ + ($query:expr) => ({ #[macro_use] mod _macro_result { $crate::sqlx_macros::expand_query!(source = $query, checked = false); } macro_result!() }); - ($query:literal, $($args:expr),*$(,)?) => ({ + ($query:expr, $($args:expr),*$(,)?) => ({ #[macro_use] mod _macro_result { $crate::sqlx_macros::expand_query!(source = $query, args = [$($args),*], checked = false); @@ -461,14 +461,14 @@ macro_rules! query_file_unchecked ( #[macro_export] #[cfg_attr(docsrs, doc(cfg(feature = "macros")))] macro_rules! query_as ( - ($out_struct:path, $query:literal) => (#[allow(dead_code)] { + ($out_struct:path, $query:expr) => (#[allow(dead_code)] { #[macro_use] mod _macro_result { $crate::sqlx_macros::expand_query!(record = $out_struct, source = $query); } macro_result!() }); - ($out_struct:path, $query:literal, $($args:expr),*$(,)?) => (#[allow(dead_code)] { + ($out_struct:path, $query:expr, $($args:expr),*$(,)?) => (#[allow(dead_code)] { #[macro_use] mod _macro_result { $crate::sqlx_macros::expand_query!(record = $out_struct, source = $query, args = [$($args),*]); @@ -534,7 +534,7 @@ macro_rules! query_file_as ( #[macro_export] #[cfg_attr(docsrs, doc(cfg(feature = "macros")))] macro_rules! query_as_unchecked ( - ($out_struct:path, $query:literal) => (#[allow(dead_code)] { + ($out_struct:path, $query:expr) => (#[allow(dead_code)] { #[macro_use] mod _macro_result { $crate::sqlx_macros::expand_query!(record = $out_struct, source = $query, checked = false); @@ -542,7 +542,7 @@ macro_rules! query_as_unchecked ( macro_result!() }); - ($out_struct:path, $query:literal, $($args:expr),*$(,)?) => (#[allow(dead_code)] { + ($out_struct:path, $query:expr, $($args:expr),*$(,)?) => (#[allow(dead_code)] { #[macro_use] mod _macro_result { $crate::sqlx_macros::expand_query!(record = $out_struct, source = $query, args = [$($args),*], checked = false);