Skip to main content

khive_runtime/
sql_include.rs

1//! SQL lives beside the code as `sql/<name>.sql`: one statement per file,
2//! `?N` binds only, never string-built, loaded at compile time by `sql!`.
3//!
4//! `include_str!` resolves at compile time, so a renamed or missing file is a
5//! build error rather than a runtime one, and `scripts/lint-sql.sh` prepares
6//! every one of those files against the real schema, so a table or column that
7//! does not exist fails before a test ever runs.
8
9/// The statement text of `sql/<name>.sql`, checked in at compile time.
10///
11/// The path is built from `CARGO_MANIFEST_DIR`, which the compiler reads while it
12/// compiles the crate that invokes the macro, so each crate loads from the `sql/`
13/// directory beside its own `Cargo.toml`, never from this crate's.
14///
15/// The trailing newline every text file carries is trimmed, in a `const` block so
16/// it costs nothing at run time and the result stays a `&'static str`. A statement
17/// that used to be a Rust literal ended at its last word, and callers and tests
18/// anchored on that: leaving the newline on would change the string a reader of
19/// this file has no reason to think changed.
20#[macro_export]
21macro_rules! sql {
22    ($name:literal) => {
23        const {
24            include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/sql/", $name, ".sql"))
25                .trim_ascii_end()
26        }
27    };
28}