SQLx’sDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/launchbadge/sqlx/llms.txt
Use this file to discover all available pages before exploring further.
query!() family of macros verifies your SQL queries at compile time. During cargo build, the macros connect to your development database, prepare each query, and use the information returned by the database server to check that your SQL is syntactically valid, that the bound parameters are the correct type, and that the result columns map to appropriate Rust types. Type errors and missing columns become compiler errors rather than runtime panics.
How it works
When the compiler expands aquery!() macro, it reads the DATABASE_URL environment variable and opens a connection to that database. It sends the SQL string to the database as a prepared statement and receives metadata about:
- The number and expected types of bind parameters
- The names, types, and nullability of result columns
The database used at compile time must be the same flavor (PostgreSQL, MySQL, SQLite) and have the same schema as the database used at runtime. It does not need to contain any data.
Setting DATABASE_URL
Set DATABASE_URL before running cargo build or cargo check:
.env file at the root of your project. SQLx reads this file automatically using the dotenvy crate:
The query!() macro
query!() returns a value whose fields correspond to the SQL result columns. The output type is anonymous — it cannot be named in your code, but the fields are directly accessible:
The query_as!() macro
query_as!() maps results into a named struct. Unlike query_as() (the function), no FromRow implementation is required — the macro generates the mapping code directly:
The query_scalar!() macro
query_scalar!() is for queries that return a single column. It decodes the first column of the first result row directly into the specified Rust type:
How nullability is inferred
The macros must determine whether each result column can beNULL to choose between T and Option<T> in the generated code.
PostgreSQL
PostgreSQL
After preparing the query, the driver looks up each result column in its source table and checks for a
NOT NULL constraint. It then runs EXPLAIN (VERBOSE, FORMAT JSON) on your query to detect columns that come from half-open joins (LEFT JOIN, RIGHT JOIN), which can make a normally NOT NULL column nullable.The inference errs on the side of false positives — marking a column as Option<T> when it is actually NOT NULL — to avoid unexpected runtime errors.MySQL / MariaDB
MySQL / MariaDB
MySQL returns a
NOT NULL flag directly in the prepared statement response, so nullability inference is straightforward.SQLite
SQLite
The SQLite driver steps through the bytecode of the prepared statement to find instructions that can produce a
NULL value for any output column.Type override syntax
When the inferred type does not match what you want — for example, when passingVec<Option<String>> as a parameter — you can override the type SQLx uses for a bind parameter using an as cast:
Differences from query()
query!() macro | query() function | |
|---|---|---|
| SQL verified at | Compile time | Runtime |
| Output type | Anonymous record (or named struct with query_as!()) | Row — columns accessed dynamically |
| Parameter count and types | Verified at compile time | Verified at runtime |
DATABASE_URL required | Yes, at build time | No |
| Works without database at build time | Only in offline mode | Always |
Offline mode
In CI environments or on machines without a database, the macros can use a cached.sqlx/ directory generated by cargo sqlx prepare. This directory stores the query metadata so the macros do not need a live database connection.
See the offline mode page for setup instructions.
Build speed optimization
Thequery!() macros do significant work at compile time. You can speed up incremental builds by compiling sqlx-macros with optimizations even in dev builds: