#![forbid(unsafe_code)]
extern crate proc_macro;
mod codegen;
mod connection;
mod dynamic;
mod offline;
mod parse;
mod pg_enum;
mod sql_norm;
mod stmt_name;
pub(crate) mod types;
mod validate;
use proc_macro::TokenStream;
#[proc_macro]
pub fn query(input: TokenStream) -> TokenStream {
let input2: proc_macro2::TokenStream = input.into();
match query_impl(input2) {
Ok(output) => output.into(),
Err(err) => err.to_compile_error().into(),
}
}
fn query_impl(input: proc_macro2::TokenStream) -> Result<proc_macro2::TokenStream, syn::Error> {
let sql = extract_sql(input)?;
let parsed = parse::parse_query(&sql)
.map_err(|msg| syn::Error::new(proc_macro2::Span::call_site(), msg))?;
let variants = dynamic::expand_variants(&parsed)
.map_err(|msg| syn::Error::new(proc_macro2::Span::call_site(), msg))?;
if parsed.optional_clauses.is_empty() {
let validation = if offline::is_offline() {
offline::lookup_cached_validation(&parsed)
.map_err(|msg| syn::Error::new(proc_macro2::Span::call_site(), msg))?
} else {
let result = connection::with_connection(|rt, client| {
validate::validate_query(&parsed, rt, client)
})?;
offline::write_cache(&parsed, &result);
result
};
validate::check_param_types(&parsed, &validation)
.map_err(|msg| syn::Error::new(proc_macro2::Span::call_site(), msg))?;
Ok(codegen::generate_query_code(&parsed, &validation))
} else {
let validation = if offline::is_offline() {
offline::lookup_cached_validation(&parsed)
.map_err(|msg| syn::Error::new(proc_macro2::Span::call_site(), msg))?
} else {
let result = connection::with_connection(|rt, client| {
validate::validate_variants(&variants, &parsed, rt, client)
})?;
offline::write_cache(&parsed, &result);
result
};
Ok(codegen::generate_dynamic_query_code(
&parsed,
&validation,
&variants,
))
}
}
fn extract_sql(input: proc_macro2::TokenStream) -> Result<String, syn::Error> {
let lit: syn::LitStr = syn::parse2(input)?;
Ok(lit.value())
}
#[proc_macro_attribute]
pub fn pg_enum(attr: TokenStream, item: TokenStream) -> TokenStream {
let attr2: proc_macro2::TokenStream = attr.into();
let item2: proc_macro2::TokenStream = item.into();
match pg_enum::expand_pg_enum(attr2, item2) {
Ok(output) => output.into(),
Err(err) => err.to_compile_error().into(),
}
}