{"record":{"id":"ff5a5c9aab4337f8","repo":"PRQL/prql","slug":"prql-to-sql-proc-macro-expected-a-string","errorCode":null,"errorMessage":"prql_to_sql! proc macro expected a string","messagePattern":"prql_to_sql! proc macro expected a string","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"prqlc/prqlc-macros/src/lib.rs","lineNumber":24,"sourceCode":"//! let sql: &str = prql_to_sql!(\"from albums | select {title, artist_id}\");\n//! assert_eq!(sql, \"SELECT title, artist_id FROM albums\");\n//! ```\n//!\n//! \"at build time\" means that PRQL will be compiled during Rust compilation,\n//! producing errors alongside Rust errors. Limited to string literals.\nuse proc_macro::{Literal, TokenStream, TokenTree};\nuse syn::{Expr, ExprLit, Lit};\n\n#[proc_macro]\npub fn prql_to_sql(input: TokenStream) -> TokenStream {\n    let input: Expr = syn::parse(input).unwrap();\n\n    let prql_string = match input {\n        Expr::Lit(ExprLit {\n            lit: Lit::Str(lit_str),\n            ..\n        }) => lit_str.value(),\n        _ => panic!(\"prql_to_sql! proc macro expected a string\"),\n    };\n\n    let opts = prqlc::Options::default().no_format().no_signature();\n\n    let sql_string = match prqlc::compile(&prql_string, &opts) {\n        Ok(r) => r,\n        Err(err) => {\n            panic!(\"{}\", err);\n        }\n    };\n\n    TokenStream::from_iter(vec![TokenTree::Literal(Literal::string(&sql_string))])\n}\n","sourceCodeStart":6,"sourceCodeEnd":38,"githubUrl":"https://github.com/PRQL/prql/blob/e164e249b99485890036eb60f57c37520379b240/prqlc/prqlc-macros/src/lib.rs#L6-L38","documentation":"prql_to_sql! is a proc macro that compiles a PRQL string literal to SQL at compile time. It only accepts a single string literal argument; any other token (identifiers, non-string literals, expressions, concatenation) panics with this message. Because it is a proc macro, the panic surfaces as a compile-time error in the calling crate.","triggerScenarios":"Invoking prql_to_sql! with a non-string-literal argument: a variable (prql_to_sql!(my_query)), a numeric/bool literal, concat!(...), format!(...), or an empty/no argument at all.","commonSituations":"Developers trying to reuse the PRQL query stored in a const/variable, building the query dynamically, or passing include_str! output concatenated with other strings; also typos like double-nesting prql_to_sql!(prql_to_sql!(...)).","solutions":["Pass a plain string literal directly inside prql_to_sql!(\"...\")","If the query must be dynamic, call prqlc::compile at runtime instead of the macro","Use include_str! to load a .prql file as the literal argument, which is accepted since it expands to a string literal","Check that you are not wrapping the argument in extra macros like concat! or format!"],"exampleFix":"// before\nlet q = \"from employees | filter age > 21\";\nlet sql = prql_to_sql!(q);\n// after\nlet sql = prql_to_sql!(\"from employees | filter age > 21\");","handlingStrategy":"validation","validationCode":"// Only string literals are accepted\nconst QUERY: &str = \"from employees | take 5\"; // literal itself, not a variable\nlet sql = prql_to_sql!(QUERY); // WRONG\nlet sql = prql_to_sql!(\"from employees | take 5\"); // correct","typeGuard":"macro_rules! ensure_str { ($l:literal) => {}; ($e:expr) => { compile_error!(\"prql_to_sql! requires a string literal\") }; }","tryCatchPattern":null,"preventionTips":["Always inline the PRQL as a string literal directly in the macro","Use include_str!(\"query.prql\") for large queries instead of variables","Reserve prqlc::compile (runtime) for dynamic queries"],"tags":["rust","proc-macro","compile-time"],"backgroundTag":"invalid-argument-value","analyzedSha":"e164e249b99485890036eb60f57c37520379b240","analyzedAt":"2026-09-09T12:18:38.727Z","contentChangedAt":"2026-09-09T12:18:38.727Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}