{"record":{"id":"fa8916c55d7054a7","repo":"diesel-rs/diesel","slug":"expect-sql-as-abi","errorCode":null,"errorMessage":"expect `SQL` as ABI","messagePattern":"expect `SQL` as ABI","errorType":"exception","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"diesel_derives/src/sql_function.rs","lineNumber":1177,"sourceCode":"impl Parse for ExternSqlBlock {\n    fn parse(input: ParseStream) -> Result<Self> {\n        let mut error = None::<syn::Error>;\n\n        let mut combine_error = |e: syn::Error| {\n            error = Some(\n                error\n                    .take()\n                    .map(|mut o| {\n                        o.combine(e.clone());\n                        o\n                    })\n                    .unwrap_or(e),\n            )\n        };\n\n        let block = syn::ItemForeignMod::parse(input)?;\n        if block.abi.name.as_ref().map(|n| n.value()) != Some(\"SQL\".into()) {\n            return Err(syn::Error::new(block.abi.span(), \"expect `SQL` as ABI\"));\n        }\n        if let Some(unsafety) = block.unsafety {\n            return Err(syn::Error::new(\n                unsafety.span(),\n                \"expect `SQL` function blocks to be safe\",\n            ));\n        }\n\n        let parsed_block_attrs = parse_attributes(&mut combine_error, block.attrs);\n\n        let item_count = block.items.len();\n        let function_decls_input = block\n            .items\n            .into_iter()\n            .map(|i| syn::parse2::<SqlFunctionDecl>(quote! { #i }));\n\n        let mut function_decls = Vec::with_capacity(item_count);\n        for decl in function_decls_input {","sourceCodeStart":1159,"sourceCodeEnd":1195,"githubUrl":"https://github.com/diesel-rs/diesel/blob/6fa6ed01b24b24248ab2a611698d0a7c6a2e9120/diesel_derives/src/sql_function.rs#L1159-L1195","documentation":"The `sql_function!` macro parses an `extern \"SQL\" { ... }` block. The ABI string of the foreign module must be exactly `\"SQL\"`; any other ABI (e.g. `\"C\"`, missing name, or a typo) is rejected in `parse` with this error.","triggerScenarios":"Writing `extern \"C\" { ... }`, `extern { ... }`, or misspelled ABI (e.g. `extern \"sql\"`) inside a `sql_function!` invocation or a module using the `#[sql_function]` foreign-mod syntax.","commonSituations":"Copy-pasting a normal FFI extern block into `sql_function!`; IDE auto-completing `extern \"C\"`; case-sensitivity mistakes (`\"sql\"` vs `\"SQL\"`).","solutions":["Change the ABI to exactly `extern \"SQL\"`.","If you omitted the ABI string, add `\"SQL\"` after `extern`.","Check for case mistakes: it must be uppercase `SQL`."],"exampleFix":"// before\nsql_function! {\n    extern \"C\" {\n        fn lower(x: Text) -> Text;\n    }\n}\n\n// after\nsql_function! {\n    extern \"SQL\" {\n        fn lower(x: Text) -> Text;\n    }\n}","handlingStrategy":"validation","validationCode":"// Use the canonical template for sql_function blocks:\n// sql_function! { extern \"SQL\" { fn name(args...) -> Ret; } }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always copy the `extern \"SQL\"` template from diesel docs, not from FFI examples.","Remember ABI strings are case-sensitive: `SQL` not `sql` or `C`.","Do not let IDE snippets auto-complete `extern \"C\"` inside sql_function macros."],"tags":["rust","proc-macro","diesel","sql-function","abi"],"backgroundTag":"invalid-argument-value","analyzedSha":"6fa6ed01b24b24248ab2a611698d0a7c6a2e9120","analyzedAt":"2026-09-07T01:50:13.074Z","contentChangedAt":"2026-09-07T01:50:13.074Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}