mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-09-30 06:22:01 +00:00
strip out proc-macro-hack
This commit is contained in:
parent
28ed854b03
commit
da5c538d22
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1308,7 +1308,6 @@ dependencies = [
|
|||||||
"dotenv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"dotenv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"sqlx-core 0.1.4",
|
"sqlx-core 0.1.4",
|
||||||
"sqlx-macros 0.1.1",
|
"sqlx-macros 0.1.1",
|
||||||
]
|
]
|
||||||
@ -1368,7 +1367,6 @@ dependencies = [
|
|||||||
"async-std 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"async-std 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"dotenv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"dotenv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"sqlx-core 0.1.4",
|
"sqlx-core 0.1.4",
|
||||||
|
@ -29,7 +29,7 @@ all-features = true
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = [ "macros" ]
|
default = [ "macros" ]
|
||||||
macros = [ "sqlx-macros", "proc-macro-hack" ]
|
macros = [ "sqlx-macros" ]
|
||||||
tls = ["sqlx-core/tls"]
|
tls = ["sqlx-core/tls"]
|
||||||
|
|
||||||
# database
|
# database
|
||||||
@ -43,7 +43,6 @@ uuid = [ "sqlx-core/uuid", "sqlx-macros/uuid" ]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
sqlx-core = { version = "=0.1.4", path = "sqlx-core" }
|
sqlx-core = { version = "=0.1.4", path = "sqlx-core" }
|
||||||
sqlx-macros = { version = "0.1.1", path = "sqlx-macros", optional = true }
|
sqlx-macros = { version = "0.1.1", path = "sqlx-macros", optional = true }
|
||||||
proc-macro-hack = { version = "0.5.11", optional = true }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
anyhow = "1.0.26"
|
anyhow = "1.0.26"
|
||||||
|
@ -33,7 +33,6 @@ uuid = [ "sqlx/uuid" ]
|
|||||||
async-std = { version = "1.4.0", default-features = false }
|
async-std = { version = "1.4.0", default-features = false }
|
||||||
dotenv = { version = "0.15.0", default-features = false }
|
dotenv = { version = "0.15.0", default-features = false }
|
||||||
futures = { version = "0.3.1", default-features = false }
|
futures = { version = "0.3.1", default-features = false }
|
||||||
proc-macro-hack = { version = "0.5.11", default-features = false }
|
|
||||||
proc-macro2 = { version = "1.0.6", default-features = false }
|
proc-macro2 = { version = "1.0.6", default-features = false }
|
||||||
sqlx = { version = "0.1.1", default-features = false, path = "../sqlx-core", package = "sqlx-core" }
|
sqlx = { version = "0.1.1", default-features = false, path = "../sqlx-core", package = "sqlx-core" }
|
||||||
syn = { version = "1.0.11", default-features = false, features = [ "full" ] }
|
syn = { version = "1.0.11", default-features = false, features = [ "full" ] }
|
||||||
|
@ -6,8 +6,6 @@ extern crate proc_macro;
|
|||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
|
|
||||||
use proc_macro_hack::proc_macro_hack;
|
|
||||||
|
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
use syn::parse_macro_input;
|
use syn::parse_macro_input;
|
||||||
@ -26,8 +24,22 @@ mod query_macros;
|
|||||||
|
|
||||||
use query_macros::*;
|
use query_macros::*;
|
||||||
|
|
||||||
|
fn macro_result(tokens: proc_macro2::TokenStream) -> TokenStream {
|
||||||
|
quote!(
|
||||||
|
macro_rules! macro_result {
|
||||||
|
($($args:tt)*) => (#tokens)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! async_macro (
|
macro_rules! async_macro (
|
||||||
($db:ident => $expr:expr) => {{
|
($db:ident, $input:ident: $ty:ty => $expr:expr) => {{
|
||||||
|
let $input = match syn::parse::<$ty>($input) {
|
||||||
|
Ok(input) => input,
|
||||||
|
Err(e) => return macro_result(e.to_compile_error()),
|
||||||
|
};
|
||||||
|
|
||||||
let res: Result<proc_macro2::TokenStream> = task::block_on(async {
|
let res: Result<proc_macro2::TokenStream> = task::block_on(async {
|
||||||
use sqlx::Connection;
|
use sqlx::Connection;
|
||||||
|
|
||||||
@ -70,40 +82,36 @@ macro_rules! async_macro (
|
|||||||
Ok(ts) => ts.into(),
|
Ok(ts) => ts.into(),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if let Some(parse_err) = e.downcast_ref::<syn::Error>() {
|
if let Some(parse_err) = e.downcast_ref::<syn::Error>() {
|
||||||
return dbg!(parse_err).to_compile_error().into();
|
macro_result(parse_err.to_compile_error())
|
||||||
|
} else {
|
||||||
|
let msg = format!("{:?}", e);
|
||||||
|
macro_result(quote!(compile_error(#msg)))
|
||||||
}
|
}
|
||||||
|
|
||||||
let msg = format!("{:?}", e);
|
|
||||||
quote!(compile_error!(#msg);).into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
);
|
);
|
||||||
|
|
||||||
#[proc_macro_hack]
|
#[proc_macro]
|
||||||
pub fn query(input: TokenStream) -> TokenStream {
|
pub fn query(input: TokenStream) -> TokenStream {
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
let input = parse_macro_input!(input as QueryMacroInput);
|
async_macro!(db, input: QueryMacroInput => expand_query(input, db))
|
||||||
async_macro!(db => expand_query(input, db))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_hack]
|
#[proc_macro]
|
||||||
pub fn query_file(input: TokenStream) -> TokenStream {
|
pub fn query_file(input: TokenStream) -> TokenStream {
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
let input = parse_macro_input!(input as QueryMacroInput);
|
async_macro!(db, input: QueryMacroInput => expand_query_file(input, db))
|
||||||
async_macro!(db => expand_query_file(input, db))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_hack]
|
#[proc_macro]
|
||||||
pub fn query_as(input: TokenStream) -> TokenStream {
|
pub fn query_as(input: TokenStream) -> TokenStream {
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
let input = parse_macro_input!(input as QueryAsMacroInput);
|
async_macro!(db, input: QueryAsMacroInput => expand_query_as(input, db))
|
||||||
async_macro!(db => expand_query_as(input, db))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_hack]
|
#[proc_macro]
|
||||||
pub fn query_file_as(input: TokenStream) -> TokenStream {
|
pub fn query_file_as(input: TokenStream) -> TokenStream {
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
let input = parse_macro_input!(input as QueryAsMacroInput);
|
async_macro!(db, input: QueryAsMacroInput => expand_query_file_as(input, db))
|
||||||
async_macro!(db => expand_query_file_as(input, db))
|
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ pub fn quote_args<DB: DatabaseExt>(
|
|||||||
input: &QueryMacroInput,
|
input: &QueryMacroInput,
|
||||||
describe: &Describe<DB>,
|
describe: &Describe<DB>,
|
||||||
) -> crate::Result<TokenStream> {
|
) -> crate::Result<TokenStream> {
|
||||||
if input.args.is_empty() {
|
if input.arg_names.is_empty() {
|
||||||
return Ok(quote! {
|
return Ok(quote! {
|
||||||
let args = ();
|
let args = ();
|
||||||
});
|
});
|
||||||
@ -22,7 +22,7 @@ pub fn quote_args<DB: DatabaseExt>(
|
|||||||
let param_types = describe
|
let param_types = describe
|
||||||
.param_types
|
.param_types
|
||||||
.iter()
|
.iter()
|
||||||
.zip(&*input.args)
|
.zip(&*input.arg_exprs)
|
||||||
.map(|(type_, expr)| {
|
.map(|(type_, expr)| {
|
||||||
get_type_override(expr)
|
get_type_override(expr)
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
@ -36,7 +36,7 @@ pub fn quote_args<DB: DatabaseExt>(
|
|||||||
})
|
})
|
||||||
.collect::<crate::Result<Vec<_>>>()?;
|
.collect::<crate::Result<Vec<_>>>()?;
|
||||||
|
|
||||||
let args_ty_cons = input.args.iter().enumerate().map(|(i, expr)| {
|
let args_ty_cons = input.arg_names.iter().enumerate().map(|(i, expr)| {
|
||||||
// required or `quote!()` emits it as `Nusize`
|
// required or `quote!()` emits it as `Nusize`
|
||||||
let i = syn::Index::from(i);
|
let i = syn::Index::from(i);
|
||||||
quote_spanned!( expr.span() => {
|
quote_spanned!( expr.span() => {
|
||||||
@ -56,10 +56,10 @@ pub fn quote_args<DB: DatabaseExt>(
|
|||||||
TokenStream::new()
|
TokenStream::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
let args = input.args.iter();
|
let args = input.arg_names.iter();
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
let args = (#(&#args),*,);
|
let args = (#(&$#args),*,);
|
||||||
#args_check
|
#args_check
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
use async_std::fs;
|
use async_std::fs;
|
||||||
use proc_macro2::Span;
|
use proc_macro2::{Ident, Span, TokenStream};
|
||||||
use syn::parse::{Parse, ParseStream};
|
use syn::parse::{Parse, ParseStream};
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
use syn::Token;
|
use syn::spanned::Spanned;
|
||||||
|
use syn::token::Group;
|
||||||
use syn::{Expr, ExprLit, ExprPath, Lit};
|
use syn::{Expr, ExprLit, ExprPath, Lit};
|
||||||
|
use syn::{ExprGroup, Token};
|
||||||
|
|
||||||
|
use quote::{format_ident, quote, ToTokens};
|
||||||
|
|
||||||
use sqlx::describe::Describe;
|
use sqlx::describe::Describe;
|
||||||
use sqlx::Connection;
|
use sqlx::Connection;
|
||||||
@ -14,28 +18,55 @@ use sqlx::Connection;
|
|||||||
pub struct QueryMacroInput {
|
pub struct QueryMacroInput {
|
||||||
pub(super) source: String,
|
pub(super) source: String,
|
||||||
pub(super) source_span: Span,
|
pub(super) source_span: Span,
|
||||||
pub(super) args: Vec<Expr>,
|
// `arg0 .. argN` for N arguments
|
||||||
|
pub(super) arg_names: Vec<Ident>,
|
||||||
|
pub(super) arg_exprs: Vec<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QueryMacroInput {
|
impl QueryMacroInput {
|
||||||
fn from_exprs(input: ParseStream, mut args: impl Iterator<Item = Expr>) -> syn::Result<Self> {
|
fn from_exprs(input: ParseStream, mut args: impl Iterator<Item = Expr>) -> syn::Result<Self> {
|
||||||
let sql = match args.next() {
|
fn lit_err<T>(span: Span, unexpected: Expr) -> syn::Result<T> {
|
||||||
|
Err(syn::Error::new(
|
||||||
|
span,
|
||||||
|
format!(
|
||||||
|
"expected string literal, got {}",
|
||||||
|
unexpected.to_token_stream()
|
||||||
|
),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
let (source, source_span) = match args.next() {
|
||||||
Some(Expr::Lit(ExprLit {
|
Some(Expr::Lit(ExprLit {
|
||||||
lit: Lit::Str(sql), ..
|
lit: Lit::Str(sql), ..
|
||||||
})) => sql,
|
})) => (sql.value(), sql.span()),
|
||||||
Some(other_expr) => {
|
Some(Expr::Group(ExprGroup {
|
||||||
return Err(syn::Error::new_spanned(
|
expr,
|
||||||
other_expr,
|
group_token: Group { span },
|
||||||
"expected string literal",
|
..
|
||||||
));
|
})) => {
|
||||||
|
// this duplication with the above is necessary because `expr` is `Box<Expr>` here
|
||||||
|
// which we can't directly pattern-match without `box_patterns`
|
||||||
|
match *expr {
|
||||||
|
Expr::Lit(ExprLit {
|
||||||
|
lit: Lit::Str(sql), ..
|
||||||
|
}) => (sql.value(), span),
|
||||||
|
other_expr => return lit_err(span, other_expr),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Some(other_expr) => return lit_err(other_expr.span(), other_expr),
|
||||||
None => return Err(input.error("expected SQL string literal")),
|
None => return Err(input.error("expected SQL string literal")),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let arg_exprs: Vec<_> = args.collect();
|
||||||
|
let arg_names = (0..arg_exprs.len())
|
||||||
|
.map(|i| format_ident!("arg{}", i))
|
||||||
|
.collect();
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
source: sql.value(),
|
source,
|
||||||
source_span: sql.span(),
|
source_span,
|
||||||
args: args.collect(),
|
arg_exprs,
|
||||||
|
arg_names,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,13 +87,13 @@ impl QueryMacroInput {
|
|||||||
.await
|
.await
|
||||||
.map_err(|e| syn::Error::new(self.source_span, e))?;
|
.map_err(|e| syn::Error::new(self.source_span, e))?;
|
||||||
|
|
||||||
if self.args.len() != describe.param_types.len() {
|
if self.arg_names.len() != describe.param_types.len() {
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
Span::call_site(),
|
Span::call_site(),
|
||||||
format!(
|
format!(
|
||||||
"expected {} parameters, got {}",
|
"expected {} parameters, got {}",
|
||||||
describe.param_types.len(),
|
describe.param_types.len(),
|
||||||
self.args.len()
|
self.arg_names.len()
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.into());
|
.into());
|
||||||
@ -97,16 +128,33 @@ impl QueryAsMacroInput {
|
|||||||
|
|
||||||
impl Parse for QueryAsMacroInput {
|
impl Parse for QueryAsMacroInput {
|
||||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||||
|
fn path_err<T>(span: Span, unexpected: Expr) -> syn::Result<T> {
|
||||||
|
Err(syn::Error::new(
|
||||||
|
span,
|
||||||
|
format!(
|
||||||
|
"expected path to a type, got {}",
|
||||||
|
unexpected.to_token_stream()
|
||||||
|
),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
let mut args = Punctuated::<Expr, Token![,]>::parse_terminated(input)?.into_iter();
|
let mut args = Punctuated::<Expr, Token![,]>::parse_terminated(input)?.into_iter();
|
||||||
|
|
||||||
let as_ty = match args.next() {
|
let as_ty = match args.next() {
|
||||||
Some(Expr::Path(path)) => path,
|
Some(Expr::Path(path)) => path,
|
||||||
Some(other_expr) => {
|
Some(Expr::Group(ExprGroup {
|
||||||
return Err(syn::Error::new_spanned(
|
expr,
|
||||||
other_expr,
|
group_token: Group { span },
|
||||||
"expected path to a type",
|
..
|
||||||
));
|
})) => {
|
||||||
|
// this duplication with the above is necessary because `expr` is `Box<Expr>` here
|
||||||
|
// which we can't directly pattern-match without `box_patterns`
|
||||||
|
match *expr {
|
||||||
|
Expr::Path(path) => path,
|
||||||
|
other_expr => return path_err(span, other_expr),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Some(other_expr) => return path_err(other_expr.span(), other_expr),
|
||||||
None => return Err(input.error("expected path to SQL file")),
|
None => return Err(input.error("expected path to SQL file")),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
let args_tokens = args::quote_args(&input.query_input, &describe)?;
|
let args_tokens = args::quote_args(&input.query_input, &describe)?;
|
||||||
|
let arg_names = &input.query_input.arg_names;
|
||||||
|
|
||||||
let columns = output::columns_to_rust(&describe)?;
|
let columns = output::columns_to_rust(&describe)?;
|
||||||
let output = output::quote_query_as::<C::Database>(
|
let output = output::quote_query_as::<C::Database>(
|
||||||
@ -54,10 +55,14 @@ where
|
|||||||
&columns,
|
&columns,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(quote! {{
|
Ok(quote! {
|
||||||
#args_tokens
|
macro_rules! macro_result {
|
||||||
#output.bind_all(args)
|
(#($#arg_names:expr),*) => {{
|
||||||
}})
|
#args_tokens
|
||||||
|
#output.bind_all(args)
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn expand_query_file_as<C: Connection>(
|
pub async fn expand_query_file_as<C: Connection>(
|
||||||
|
@ -50,15 +50,20 @@ where
|
|||||||
.collect::<TokenStream>();
|
.collect::<TokenStream>();
|
||||||
|
|
||||||
let output = output::quote_query_as::<C::Database>(sql, &record_type, &columns);
|
let output = output::quote_query_as::<C::Database>(sql, &record_type, &columns);
|
||||||
|
let arg_names = &input.arg_names;
|
||||||
|
|
||||||
Ok(quote! {{
|
Ok(quote! {
|
||||||
#[derive(Debug)]
|
macro_rules! macro_result {
|
||||||
struct #record_type {
|
(#($#arg_names:expr),*) => {{
|
||||||
#record_fields
|
#[derive(Debug)]
|
||||||
}
|
struct #record_type {
|
||||||
|
#record_fields
|
||||||
|
}
|
||||||
|
|
||||||
#args
|
#args
|
||||||
|
|
||||||
#output.bind_all(args)
|
#output.bind_all(args)
|
||||||
}})
|
}
|
||||||
|
}}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
30
src/lib.rs
30
src/lib.rs
@ -20,34 +20,14 @@ pub use sqlx_core::mysql::{self, MySql, MySqlConnection, MySqlPool};
|
|||||||
#[cfg(feature = "postgres")]
|
#[cfg(feature = "postgres")]
|
||||||
pub use sqlx_core::postgres::{self, PgConnection, PgPool, Postgres};
|
pub use sqlx_core::postgres::{self, PgConnection, PgPool, Postgres};
|
||||||
|
|
||||||
#[allow(unused_attributes)]
|
#[cfg(feature = "macros")]
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub extern crate sqlx_macros;
|
||||||
|
|
||||||
|
#[cfg(feature = "macros")]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
#[cfg(feature = "macros")]
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[proc_macro_hack::proc_macro_hack(fake_call_site)]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub use sqlx_macros::query as query_;
|
|
||||||
|
|
||||||
#[cfg(feature = "macros")]
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[proc_macro_hack::proc_macro_hack(fake_call_site)]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub use sqlx_macros::query_as as query_as_;
|
|
||||||
|
|
||||||
#[cfg(feature = "macros")]
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[proc_macro_hack::proc_macro_hack(fake_call_site)]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub use sqlx_macros::query_file as query_file_;
|
|
||||||
|
|
||||||
#[cfg(feature = "macros")]
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[proc_macro_hack::proc_macro_hack(fake_call_site)]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub use sqlx_macros::query_file_as as query_file_as_;
|
|
||||||
|
|
||||||
// macro support
|
// macro support
|
||||||
#[cfg(feature = "macros")]
|
#[cfg(feature = "macros")]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -82,18 +82,23 @@
|
|||||||
/// * [query_as!] if you want to use a struct you can name,
|
/// * [query_as!] if you want to use a struct you can name,
|
||||||
/// * [query_file!] if you want to define the SQL query out-of-line,
|
/// * [query_file!] if you want to define the SQL query out-of-line,
|
||||||
/// * [query_file_as!] if you want both of the above.
|
/// * [query_file_as!] if you want both of the above.
|
||||||
#[cfg(feature = "macros")]
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! query (
|
macro_rules! query (
|
||||||
// the emitted item for `#[proc_macro_hack]` doesn't look great in docs
|
// by emitting a macro definition from our proc-macro containing the result tokens,
|
||||||
// plus this might let IDEs hint at the syntax
|
// we no longer have a need for `proc-macro-hack`
|
||||||
// `#[allow(dead_code)]` to silence the `enum ProcMacroHack` error
|
($query:literal) => ({
|
||||||
($query:literal) => (#[allow(dead_code)] {
|
#[macro_use]
|
||||||
$crate::query_!($query)
|
mod _macro_result {
|
||||||
|
$crate::sqlx_macros::query!($query);
|
||||||
|
}
|
||||||
|
macro_result!()
|
||||||
});
|
});
|
||||||
($query:literal, $($args:tt)*) => (#[allow(dead_code)]{
|
($query:literal, $($args:expr),*) => ({
|
||||||
#![allow(dead_code)]
|
#[macro_use]
|
||||||
$crate::query_!($query, $($args)*)
|
mod _macro_result {
|
||||||
|
$crate::sqlx_macros::query!($query, $($args),*);
|
||||||
|
}
|
||||||
|
macro_result!($($args),*)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -139,14 +144,21 @@ macro_rules! query (
|
|||||||
/// # #[cfg(not(feature = "mysql"))]
|
/// # #[cfg(not(feature = "mysql"))]
|
||||||
/// # fn main() {}
|
/// # fn main() {}
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(feature = "macros")]
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! query_file (
|
macro_rules! query_file (
|
||||||
($query:literal) => (#[allow(dead_code)]{
|
($query:literal) => (#[allow(dead_code)]{
|
||||||
$crate::query_file_!($query)
|
#[macro_use]
|
||||||
|
mod _macro_result {
|
||||||
|
$crate::sqlx_macros::query_file!($query);
|
||||||
|
}
|
||||||
|
macro_result!()
|
||||||
});
|
});
|
||||||
($query:literal, $($args:tt)*) => (#[allow(dead_code)]{
|
($query:literal, $($args:expr),*) => (#[allow(dead_code)]{
|
||||||
$crate::query_file_!($query, $($args)*)
|
#[macro_use]
|
||||||
|
mod _macro_result {
|
||||||
|
$crate::sqlx_macros::query_file!($query, $($args),*);
|
||||||
|
}
|
||||||
|
macro_result!($($args),*)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -197,14 +209,21 @@ macro_rules! query_file (
|
|||||||
/// # #[cfg(not(feature = "mysql"))]
|
/// # #[cfg(not(feature = "mysql"))]
|
||||||
/// # fn main() {}
|
/// # fn main() {}
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(feature = "macros")]
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! query_as (
|
macro_rules! query_as (
|
||||||
($out_struct:path, $query:literal) => (#[allow(dead_code)] {
|
($out_struct:path, $query:literal) => (#[allow(dead_code)] {
|
||||||
$crate::query_as_!($out_struct, $query)
|
#[macro_use]
|
||||||
|
mod _macro_result {
|
||||||
|
$crate::sqlx_macros::query_as!($out_struct, $query);
|
||||||
|
}
|
||||||
|
macro_result!()
|
||||||
});
|
});
|
||||||
($out_struct:path, $query:literal, $($args:tt)*) => (#[allow(dead_code)] {
|
($out_struct:path, $query:literal, $($args:expr),*) => (#[allow(dead_code)] {
|
||||||
$crate::query_as_!($out_struct, $query, $($args)*)
|
#[macro_use]
|
||||||
|
mod _macro_result {
|
||||||
|
$crate::sqlx_macros::query_as!($out_struct, $query, $($args),*);
|
||||||
|
}
|
||||||
|
macro_result!($($args),*)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -240,13 +259,20 @@ macro_rules! query_as (
|
|||||||
/// # #[cfg(not(feature = "mysql"))]
|
/// # #[cfg(not(feature = "mysql"))]
|
||||||
/// # fn main() {}
|
/// # fn main() {}
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(feature = "macros")]
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! query_file_as (
|
macro_rules! query_file_as (
|
||||||
($out_struct:path, $query:literal) => (#[allow(dead_code)] {
|
($out_struct:path, $query:literal) => (#[allow(dead_code)] {
|
||||||
$crate::query_file_as_!($out_struct, $query)
|
#[macro_use]
|
||||||
|
mod _macro_result {
|
||||||
|
$crate::sqlx_macros::query_file_as!($out_struct, $query);
|
||||||
|
}
|
||||||
|
macro_result!()
|
||||||
});
|
});
|
||||||
($out_struct:path, $query:literal, $($args:tt)*) => (#[allow(dead_code)] {
|
($out_struct:path, $query:literal, $($args:expr),*) => (#[allow(dead_code)] {
|
||||||
$crate::query_file_as_!($out_struct, $query, $($args)*)
|
#[macro_use]
|
||||||
|
mod _macro_result {
|
||||||
|
$crate::sqlx_macros::query_file_as!($out_struct, $query, $($args),*);
|
||||||
|
}
|
||||||
|
macro_result!($($args),*)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -73,6 +73,21 @@ async fn pool_immediately_fails_with_db_error() -> anyhow::Result<()> {
|
|||||||
#[cfg(feature = "macros")]
|
#[cfg(feature = "macros")]
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
async fn macro_select_from_cte() -> anyhow::Result<()> {
|
async fn macro_select_from_cte() -> anyhow::Result<()> {
|
||||||
|
let mut conn = connect().await?;
|
||||||
|
let account =
|
||||||
|
sqlx::query!("select * from (select (1) as id, 'Herp Derpinson' as name) accounts")
|
||||||
|
.fetch_one(&mut conn)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
println!("{:?}", account);
|
||||||
|
println!("{}: {}", account.id, account.name);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "macros")]
|
||||||
|
#[async_std::test]
|
||||||
|
async fn macro_select_from_cte_bind() -> anyhow::Result<()> {
|
||||||
let mut conn = connect().await?;
|
let mut conn = connect().await?;
|
||||||
let account = sqlx::query!(
|
let account = sqlx::query!(
|
||||||
"select * from (select (1) as id, 'Herp Derpinson' as name) accounts where id = ?",
|
"select * from (select (1) as id, 'Herp Derpinson' as name) accounts where id = ?",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user