mirror of
https://github.com/launchbadge/sqlx
synced 2024-11-15 00:27:41 +00:00
doc: adjust macros documentation
Signed-off-by: Austin Bonander <austin@launchbadge.com>
This commit is contained in:
parent
94aa698581
commit
67ad43491d
1 changed files with 82 additions and 19 deletions
101
src/macros.rs
101
src/macros.rs
|
@ -1,7 +1,7 @@
|
|||
/// Statically checked SQL query with `println!()` style syntax.
|
||||
///
|
||||
/// This expands to an instance of [QueryAs][crate::QueryAs] that outputs an ad-hoc anonymous struct type,
|
||||
/// if the query has output columns, or `()` (unit) otherwise:
|
||||
/// This expands to an instance of [query::Map][crate::query::Map] that outputs an ad-hoc anonymous
|
||||
/// struct type, if the query has output columns, or `()` (unit) otherwise:
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// # use sqlx::Connect;
|
||||
|
@ -36,8 +36,9 @@
|
|||
/// * Or, `sqlx-data.json` must exist at the workspace root. See [Offline Mode](#offline-mode)
|
||||
/// below.
|
||||
///
|
||||
/// * The query must be a string literal or else it cannot be introspected (and thus cannot
|
||||
/// be dynamic or the result of another macro).
|
||||
/// * The query must be a string literal, or concatenation of string literals using `+` (useful
|
||||
/// for queries generated by macro), or else it cannot be introspected (and thus cannot be dynamic
|
||||
/// or the result of another macro).
|
||||
///
|
||||
/// * The `QueryAs` instance will be bound to the same database type as `query!()` was compiled
|
||||
/// against (e.g. you cannot build against a Postgres database and then run the query against
|
||||
|
@ -81,7 +82,7 @@
|
|||
/// Bind parameters in the SQL string are specific to the database backend:
|
||||
///
|
||||
/// * Postgres: `$N` where `N` is the 1-based positional argument index
|
||||
/// * MySQL: `?` which matches arguments in order that it appears in the query
|
||||
/// * MySQL/SQLite: `?` which matches arguments in order that it appears in the query
|
||||
///
|
||||
/// ## Nullability: Bind Parameters
|
||||
/// For a given expected type `T`, both `T` and `Option<T>` are allowed (as well as either
|
||||
|
@ -90,8 +91,11 @@
|
|||
///
|
||||
/// Note, however, if binding in a `where` clause, that equality comparisons with `NULL` may not
|
||||
/// work as expected; instead you must use `IS NOT NULL` or `IS NULL` to check if a column is not
|
||||
/// null or is null, respectively. Note that `IS [NOT] NULL` cannot be bound as a parameter either;
|
||||
/// you must modify your query string instead.
|
||||
/// null or is null, respectively.
|
||||
///
|
||||
/// In Postgres and MySQL you may also use `IS [NOT] DISTINCT FROM` to compare with a possibly
|
||||
/// `NULL` value. In MySQL `IS NOT DISTINCT FROM` can be shortened to `<=>`.
|
||||
/// In SQLite you can us `IS` or `IS NOT`. Note that operator precedence may be different.
|
||||
///
|
||||
/// ## Nullability: Output Columns
|
||||
/// In most cases, the database engine can tell us whether or not a column may be `NULL`, and
|
||||
|
@ -111,7 +115,7 @@
|
|||
/// `NULL` which then depends on the semantics of what functions are used. Consult the MySQL
|
||||
/// manual for the functions you are using to find the cases in which they return `NULL`.
|
||||
///
|
||||
/// To override the nullability of an output column, use [query_as!], or see below.
|
||||
/// To override the nullability of an output column, [see below](#type-overrides-output-columns).
|
||||
///
|
||||
/// ## Type Overrides: Bind Parameters (Postgres only)
|
||||
/// For typechecking of bind parameters, casts using `as` are treated as overrides for the inferred
|
||||
|
@ -136,7 +140,8 @@
|
|||
/// Type overrides are also available for output columns, utilizing the SQL standard's support
|
||||
/// for arbitrary text in column names:
|
||||
///
|
||||
/// * selecting a column `foo as "foo!"` (Postgres / SQLite) or `` foo as `foo!` `` (MySQL) overrides
|
||||
/// ##### Force Not-Null
|
||||
/// Selecting a column `foo as "foo!"` (Postgres / SQLite) or `` foo as `foo!` `` (MySQL) overrides
|
||||
/// inferred nullability and forces the column to be treated as `NOT NULL`; this is useful e.g. for
|
||||
/// selecting expressions in Postgres where we cannot infer nullability:
|
||||
///
|
||||
|
@ -154,7 +159,9 @@
|
|||
/// # }
|
||||
///
|
||||
/// ```
|
||||
/// * selecting a column `foo as "foo?"` (Postgres / SQLite) or `` foo as `foo?` `` (MySQL) overrides
|
||||
///
|
||||
/// ##### Force Nullable
|
||||
/// Selecting a column `foo as "foo?"` (Postgres / SQLite) or `` foo as `foo?` `` (MySQL) overrides
|
||||
/// inferred nullability and forces the column to be treated as nullable; this is provided mainly
|
||||
/// for symmetry with `!`, but also because nullability inference currently has some holes and false
|
||||
/// negatives that may not be completely fixable without doing our own complex analysis on the given
|
||||
|
@ -200,7 +207,8 @@
|
|||
///
|
||||
/// See [launchbadge/sqlx#367](https://github.com/launchbadge/sqlx/issues/367) for more details on this issue.
|
||||
///
|
||||
/// * selecting a column `foo as "foo: T"` (Postgres / SQLite) or `` foo as `foo: T` `` (MySQL)
|
||||
/// ##### Force a Different/Custom Type
|
||||
/// Selecting a column `foo as "foo: T"` (Postgres / SQLite) or `` foo as `foo: T` `` (MySQL)
|
||||
/// overrides the inferred type which is useful when selecting user-defined custom types
|
||||
/// (dynamic type checking is still done so if the types are incompatible this will be an error
|
||||
/// at runtime instead of compile-time):
|
||||
|
@ -355,7 +363,7 @@ macro_rules! query_file_unchecked (
|
|||
///
|
||||
/// This lets you return the struct from a function or add your own trait implementations.
|
||||
///
|
||||
/// No trait implementations are required; the macro maps rows using a struct literal
|
||||
/// **No trait implementations are required**; the macro maps rows using a struct literal
|
||||
/// where the names of columns in the query are expected to be the same as the fields of the struct
|
||||
/// (but the order does not need to be the same). The types of the columns are based on the
|
||||
/// query and not the corresponding fields of the struct, so this is type-safe as well.
|
||||
|
@ -363,9 +371,17 @@ macro_rules! query_file_unchecked (
|
|||
/// This enforces a few things:
|
||||
/// * The query must output at least one column.
|
||||
/// * The column names of the query must match the field names of the struct.
|
||||
/// * The field types must be the Rust equivalent of their SQL counterparts; see the corresponding
|
||||
/// module for your database for mappings:
|
||||
/// * Postgres: [crate::postgres::types]
|
||||
/// * MySQL: [crate::mysql::types]
|
||||
/// * SQLite: [crate::sqlite::types]
|
||||
/// * MSSQL: [crate::mssql::types]
|
||||
/// * If a column may be `NULL`, the corresponding field's type must be wrapped in `Option<_>`.
|
||||
/// * Neither the query nor the struct may have unused fields.
|
||||
///
|
||||
/// The only modification to the syntax is that the struct name is given before the SQL string:
|
||||
/// The only modification to the `query!()` syntax is that the struct name is given before the SQL
|
||||
/// string:
|
||||
/// ```rust,ignore
|
||||
/// # use sqlx::Connect;
|
||||
/// # #[cfg(all(feature = "mysql", feature = "runtime-async-std"))]
|
||||
|
@ -400,11 +416,7 @@ macro_rules! query_file_unchecked (
|
|||
/// # fn main() {}
|
||||
/// ```
|
||||
///
|
||||
/// ## Nullability
|
||||
/// Use `Option` for columns which may be `NULL` in order to avoid a runtime error being returned
|
||||
/// from `.fetch_*()`.
|
||||
///
|
||||
/// ### Additional Column Type Override Option
|
||||
/// ### Column Type Override: Infer from Struct Field
|
||||
/// In addition to the column type overrides supported by [query!], `query_as!()` supports an
|
||||
/// additional override option:
|
||||
///
|
||||
|
@ -427,12 +439,63 @@ macro_rules! query_file_unchecked (
|
|||
/// let my_int = MyInt4(1);
|
||||
///
|
||||
/// // Postgres/SQLite
|
||||
/// sqlx::query!(r#"select 1 as "id: _""#) // MySQL: use "select 1 as `id: _`" instead
|
||||
/// sqlx::query_as!(Record, r#"select 1 as "id: _""#) // MySQL: use "select 1 as `id: _`" instead
|
||||
/// .fetch_one(&mut conn)
|
||||
/// .await?;
|
||||
///
|
||||
/// assert_eq!(record.id, MyInt4(1));
|
||||
/// ```
|
||||
///
|
||||
/// ### Troubleshooting: "error: mismatched types"
|
||||
/// If you get a "mismatched types" error from an invocation of this macro and the error
|
||||
/// isn't pointing specifically at a parameter.
|
||||
///
|
||||
/// For example, code like this (using a Postgres database):
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// struct Account {
|
||||
/// id: i32,
|
||||
/// name: Option<String>,
|
||||
/// }
|
||||
///
|
||||
/// let account = sqlx::query_as!(
|
||||
/// Account,
|
||||
/// r#"SELECT id, name from (VALUES (1, 'Herp Derpinson')) accounts(id, name)"#,
|
||||
/// )
|
||||
/// .fetch_one(&mut conn)
|
||||
/// .await?;
|
||||
/// ```
|
||||
///
|
||||
/// Might produce an error like this:
|
||||
/// ```text,ignore
|
||||
/// error[E0308]: mismatched types
|
||||
/// --> tests/postgres/macros.rs:126:19
|
||||
/// |
|
||||
/// 126 | let account = sqlx::query_as!(
|
||||
/// | ___________________^
|
||||
/// 127 | | Account,
|
||||
/// 128 | | r#"SELECT id, name from (VALUES (1, 'Herp Derpinson')) accounts(id, name)"#,
|
||||
/// 129 | | )
|
||||
/// | |_____^ expected `i32`, found enum `std::option::Option`
|
||||
/// |
|
||||
/// = note: expected type `i32`
|
||||
/// found enum `std::option::Option<i32>`
|
||||
/// ```
|
||||
///
|
||||
/// This means that you need to check that any field of the "expected" type (here, `i32`) matches
|
||||
/// the Rust type mapping for its corresponding SQL column (see the `types` module of your database,
|
||||
/// listed above, for mappings). The "found" type is the SQL->Rust mapping that the macro chose.
|
||||
///
|
||||
/// In the above example, the returned column is inferred to be nullable because it's being
|
||||
/// returned from a `VALUES` statement in Postgres, so the macro inferred the field to be nullable
|
||||
/// and so used `Option<i32>` instead of `i32`. **In this specific case** we could use
|
||||
/// `select id as "id!"` to override the inferred nullability because we know in practice
|
||||
/// that column will never be `NULL` and it will fix the error.
|
||||
///
|
||||
/// Nullability inference and type overrides are discussed in detail in the docs for [query!].
|
||||
///
|
||||
/// It unfortunately doesn't appear to be possible right now to make the error specifically mention
|
||||
/// the field; this probably requires the `const-panic` feature (still unstable as of Rust 1.45).
|
||||
#[macro_export]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
|
||||
macro_rules! query_as (
|
||||
|
|
Loading…
Reference in a new issue