sqlx_conditional_queries_macros/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use proc_macro_error2::abort;
4use sqlx_conditional_queries_core::{AnalyzeError, DatabaseType, Error, ExpandError};
5
6const DATABASE_TYPE: DatabaseType = if cfg!(feature = "postgres") {
7    DatabaseType::PostgreSql
8} else if cfg!(feature = "mysql") {
9    DatabaseType::MySql
10} else if cfg!(feature = "sqlite") {
11    DatabaseType::Sqlite
12} else {
13    panic!("No database feature was enabled")
14};
15
16// The public docs for this macro live in the sql-conditional-queries crate.
17#[proc_macro_error2::proc_macro_error]
18#[proc_macro]
19pub fn conditional_query_as(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
20    let input: proc_macro2::TokenStream = input.into();
21
22    let ts = match sqlx_conditional_queries_core::conditional_query_as(DATABASE_TYPE, input) {
23        Ok(ts) => ts,
24        Err(Error::SynError(err)) => {
25            return err.to_compile_error().into();
26        }
27        Err(Error::AnalyzeError(err)) => match err {
28            AnalyzeError::ExpectedStringLiteral(span) => abort!(
29                span,
30                "expected string literal";
31                help = "only string literals or tuples of string literals are supported in compile-time bindings";
32            ),
33            AnalyzeError::BindingNameValueLengthMismatch {
34                names,
35                names_span,
36                values,
37                values_span,
38            } => abort!(
39                names_span,
40                "mismatch between number of names and values";
41                names = names_span => "number of names: {}", names;
42                values = values_span => "number of values: {}", values;
43            ),
44            AnalyzeError::DuplicatedCompileTimeBindingsFound { first: _, second } => {
45                abort!(second.span(), "found duplicate compile-time binding")
46            }
47            AnalyzeError::CompileTimeBindingCycleDetected { root_ident, path } => abort!(
48                root_ident.span(),
49                "detected compile-time binding cycle: {}",
50                path
51            ),
52        },
53        Err(Error::ExpandError(err)) => match err {
54            // TODO: Make this span point at the binding reference.  Requires https://github.com/rust-lang/rust/issues/54725
55            ExpandError::MissingCompileTimeBinding(binding, span) => abort!(
56                span,
57                "missing compile-time binding";
58                help = "found no compile-time binding with the specified name: {}", binding;
59            ),
60            // TODO: Make this span point at the opening brace.  Requires https://github.com/rust-lang/rust/issues/54725
61            ExpandError::MissingBindingClosingBrace(span) => abort!(
62                span,
63                "missing closing brace for compile-time binding reference"
64            ),
65            ExpandError::BindingReferenceTypeOverrideParseError(err, span) => abort!(
66                span,
67                "failed to parse type override in binding reference: {}",
68                err
69            ),
70        },
71    };
72
73    let output: proc_macro::TokenStream = ts.into();
74    output
75}