prql_compiler_macros/
lib.rs

1//! Macros for PRQL compilation at build time.
2//!
3//! ```
4//! use prql_compiler_macros::prql_to_sql;
5//!
6//! let sql: &str = prql_to_sql!("from albums | select {title, artist_id}");
7//! assert_eq!(sql, "SELECT title, artist_id FROM albums");
8//! ```
9//!
10//! "at build time" means that PRQL will be compiled during Rust compilation,
11//! producing errors alongside Rust errors. Limited to string literals.
12use proc_macro::{Literal, TokenStream, TokenTree};
13use syn::{Expr, ExprLit, Lit};
14
15#[proc_macro]
16pub fn prql_to_sql(input: TokenStream) -> TokenStream {
17    let input: Expr = syn::parse(input).unwrap();
18
19    let prql_string = match input {
20        Expr::Lit(ExprLit {
21            lit: Lit::Str(lit_str),
22            ..
23        }) => lit_str.value(),
24        _ => panic!("prql! proc macro expected a string"),
25    };
26
27    let opts = prqlc::Options::default().no_format().no_signature();
28
29    let sql_string = match prqlc::compile(&prql_string, &opts) {
30        Ok(r) => r,
31        Err(err) => {
32            panic!("{}", err);
33        }
34    };
35
36    TokenStream::from_iter(vec![TokenTree::Literal(Literal::string(&sql_string))])
37}