|
130 | 130 | /// * MySQL/SQLite: `?` which matches arguments in order that it appears in the query |
131 | 131 | /// |
132 | 132 | /// ## Nullability: Bind Parameters |
133 | | -/// For a given expected type `T`, both `T` and `Option<T>` are allowed (as well as either |
134 | | -/// behind references). `Option::None` will be bound as `NULL`, so if binding a type behind `Option` |
135 | | -/// be sure your query can support it. |
| 133 | +/// **The nullability of bind parameters is _not_ verified at compile time.** Unlike output |
| 134 | +/// columns (see the [next section](#nullability-output-columns)), the `query!()` family of |
| 135 | +/// macros does not check whether an `Option<T>` bound to a parameter is compatible with the |
| 136 | +/// nullability of the target column. This is a fundamental limitation, not an oversight: |
| 137 | +/// determining which parameter maps to which column would require the macros to parse and |
| 138 | +/// analyze the SQL themselves, which SQLx explicitly does not do |
| 139 | +/// (see [the FAQ][faq-parse-sql] for the reasoning). |
| 140 | +/// |
| 141 | +/// For any bind parameter, both `T` and `Option<T>` are accepted (as well as either behind |
| 142 | +/// references). `Option::None` is bound as SQL `NULL`. If the target column has a `NOT NULL` |
| 143 | +/// constraint, binding `None` will compile successfully but fail **at runtime** with a |
| 144 | +/// database error, for example: |
136 | 145 | /// |
137 | | -/// Note, however, if binding in a `where` clause, that equality comparisons with `NULL` may not |
138 | | -/// work as expected; instead you must use `IS NOT NULL` or `IS NULL` to check if a column is not |
| 146 | +/// ```rust,ignore |
| 147 | +/// // Schema: `CREATE TABLE foo (data TEXT NOT NULL);` |
| 148 | +/// // Compiles fine, fails at runtime: |
| 149 | +/// sqlx::query!("INSERT INTO foo (data) VALUES ($1)", None::<String>) |
| 150 | +/// .execute(&pool) |
| 151 | +/// .await?; |
| 152 | +/// ``` |
| 153 | +/// |
| 154 | +/// If you need this kind of safety, encode the constraint in your Rust types (e.g. use `String` |
| 155 | +/// instead of `Option<String>` for the field that feeds the bind parameter) or cover the |
| 156 | +/// invariant with an integration test against a real database. |
| 157 | +/// |
| 158 | +/// ### Bind parameters in `WHERE` clauses |
| 159 | +/// If binding in a `WHERE` clause, note that equality comparisons with `NULL` may not work |
| 160 | +/// as expected; instead you must use `IS NOT NULL` or `IS NULL` to check if a column is not |
139 | 161 | /// null or is null, respectively. |
140 | 162 | /// |
141 | 163 | /// In Postgres and MySQL you may also use `IS [NOT] DISTINCT FROM` to compare with a possibly |
142 | 164 | /// `NULL` value. In MySQL `IS NOT DISTINCT FROM` can be shortened to `<=>`. |
143 | 165 | /// In SQLite you can use `IS` or `IS NOT`. Note that operator precedence may be different. |
144 | 166 | /// |
| 167 | +/// [faq-parse-sql]: https://github.com/transact-rs/sqlx/blob/main/FAQ.md#why-cant-sqlx-just-look-at-my-database-schemamigrations-and-parse-the-sql-itself |
| 168 | +/// |
145 | 169 | /// ## Nullability: Output Columns |
146 | 170 | /// In most cases, the database engine can tell us whether or not a column may be `NULL`, and |
147 | 171 | /// the `query!()` macro adjusts the field types of the returned struct accordingly. |
|
0 commit comments