diff --git a/README.md b/README.md
index df8a0e056d..7b14e4574b 100644
--- a/README.md
+++ b/README.md
@@ -50,7 +50,7 @@
@@ -59,20 +59,23 @@ SQLx is an async, pure Rust† SQL crate featuring compile-time check
- **Truly Asynchronous**. Built from the ground-up using async/await for maximum concurrency.
-- **Type-safe SQL** (if you want it) without DSLs. Use the `query!()` macro to check your SQL and bind parameters at
- compile time. (You can still use dynamic SQL queries if you like.)
+- **Compile-time checked queries** (if you want). See [SQLx is not an ORM](#sqlx-is-not-an-orm).
- **Database Agnostic**. Support for [PostgreSQL], [MySQL], [SQLite], and [MSSQL].
- **Pure Rust**. The Postgres and MySQL/MariaDB drivers are written in pure Rust using **zero** unsafe†† code.
-* **Runtime Agnostic**. Works on different runtimes ([async-std](https://crates.io/crates/async-std) / [tokio](https://crates.io/crates/tokio) / [actix](https://crates.io/crates/actix-rt)) and TLS backends ([native-tls](https://crates.io/crates/native-tls), [rustls](https://crates.io/crates/rustls)).
+- **Runtime Agnostic**. Works on different runtimes ([`async-std`] / [`tokio`] / [`actix`]) and TLS backends ([`native-tls`], [`rustls`]).
-† The SQLite driver uses the libsqlite3 C library as SQLite is an embedded database (the only way
-we could be pure Rust for SQLite is by porting _all_ of SQLite to Rust).
+
-†† SQLx uses `#![forbid(unsafe_code)]` unless the `sqlite` feature is enabled. As the SQLite driver interacts
-with C, those interactions are `unsafe`.
+† The SQLite driver uses the libsqlite3 C library as SQLite is an embedded database (the only way
+we could be pure Rust for SQLite is by porting _all_ of SQLite to Rust).
+
+†† SQLx uses `#![forbid(unsafe_code)]` unless the `sqlite` feature is enabled. As the SQLite driver interacts
+with C, those interactions are `unsafe`.
+
+
[postgresql]: http://postgresql.org/
[sqlite]: https://sqlite.org/
@@ -108,6 +111,8 @@ SQLx is compatible with the [`async-std`], [`tokio`] and [`actix`] runtimes; and
[`async-std`]: https://github.com/async-rs/async-std
[`tokio`]: https://github.com/tokio-rs/tokio
[`actix`]: https://github.com/actix/actix-net
+[`native-tls`]: https://crates.io/crates/native-tls
+[`rustls`]: https://crates.io/crates/rustls
```toml
# Cargo.toml
@@ -118,7 +123,7 @@ sqlx = { version = "0.5", features = [ "runtime-tokio-rustls" ] }
sqlx = { version = "0.5", features = [ "runtime-async-std-native-tls" ] }
```
-The runtime and TLS backend not being separate feature sets to select is a workaround for a [Cargo issue](https://github.com/rust-lang/cargo/issues/3494).
+The runtime and TLS backend not being separate feature sets to select is a workaround for a [Cargo issue](https://github.com/rust-lang/cargo/issues/3494).
#### Cargo Feature Flags
@@ -168,6 +173,24 @@ sqlx = { version = "0.5", features = [ "runtime-async-std-native-tls" ] }
- `tls`: Add support for TLS connections.
+## SQLx is not an ORM!
+
+SQLx supports **compile-time checked queries**. It does not, however, do this by providing a Rust
+API or DSL (domain-specific language) for building queries. Instead, it provides macros that take
+regular SQL as an input and ensure that it is valid for your database. The way this works is that
+SQLx connects to your development DB at compile time to have the database itself verify (and return
+some info on) your SQL queries. This has some potentially surprising implications:
+
+- Since SQLx never has to parse the SQL string itself, any syntax that the development DB accepts
+ can be used (including things added by database extensions)
+- Due to the different amount of information databases let you retrieve about queries, the extent of
+ SQL verification you get from the query macros depends on the database
+
+**If you are looking for an (asynchronous) ORM,** you can check out [`ormx`], which is built on top
+of SQLx.
+
+[`ormx`]: https://crates.io/crates/ormx
+
## Usage
### Quickstart
@@ -336,8 +359,8 @@ Differences from `query()`:
```
The biggest downside to `query!()` is that the output type cannot be named (due to Rust not
-officially supporting anonymous records). To address that, there is a `query_as!()` macro that is identical
-except that you can name the output type.
+officially supporting anonymous records). To address that, there is a `query_as!()` macro that is
+mostly identical except that you can name the output type.
```rust
// no traits are needed
@@ -359,6 +382,11 @@ WHERE organization = ?
// countries[0].count
```
+To avoid the need of having a development database around to compile the project even when no
+modifications (to the database-accessing parts of the code) are done, you can enable "offline mode"
+to cache the results of the SQL query analysis using the `sqlx` command-line tool. See
+[sqlx-cli/README.md](./sqlx-cli/README.md#enable-building-in-offline-mode-with-query).
+
## Safety
This crate uses `#![forbid(unsafe_code)]` to ensure everything is implemented in 100% Safe Rust.
diff --git a/sqlx-cli/README.md b/sqlx-cli/README.md
index 0c47941c4e..f098dad8ab 100644
--- a/sqlx-cli/README.md
+++ b/sqlx-cli/README.md
@@ -49,17 +49,19 @@ $ sqlx migrate run
Compares the migration history of the running database against the `migrations/` folder and runs
any scripts that are still pending.
-#### Enable building in "offline" mode with `query!()`
+#### Enable building in "offline mode" with `query!()`
Note: must be run as `cargo sqlx`.
```bash
cargo sqlx prepare
```
-Saves query data to `sqlx-data.json` in the current directory; check this file into version control
-and an active database connection will no longer be needed to build your project.
-Has no effect unless the `offline` feature of `sqlx` is enabled in your project. Omitting that feature is the most likely cause if you get a `sqlx-data.json` file that looks like this:
+Saves query metadata to `sqlx-data.json` in the current directory; check this file into version
+control and an active database connection will no longer be needed to build your project.
+
+Has no effect unless the `offline` feature of `sqlx` is enabled in your project. Omitting that
+feature is the most likely cause if you get a `sqlx-data.json` file that looks like this:
```json
{
@@ -67,10 +69,12 @@ Has no effect unless the `offline` feature of `sqlx` is enabled in your project.
}
```
-----
+---
+
```bash
cargo sqlx prepare --check
```
+
Exits with a nonzero exit status if the data in `sqlx-data.json` is out of date with the current
database schema and queries in the project. Intended for use in Continuous Integration.
@@ -79,3 +83,6 @@ database schema and queries in the project. Intended for use in Continuous Integ
To make sure an accidentally-present `DATABASE_URL` environment variable or `.env` file does not
result in `cargo build` (trying to) access the database, you can set the `SQLX_OFFLINE` environment
variable to `true`.
+
+If you want to make this the default, just add it to your `.env` file. `cargo sqlx prepare` will
+still do the right thing and connect to the database.
diff --git a/sqlx-macros/src/query/args.rs b/sqlx-macros/src/query/args.rs
index b46b7f664e..71094a67d2 100644
--- a/sqlx-macros/src/query/args.rs
+++ b/sqlx-macros/src/query/args.rs
@@ -79,13 +79,13 @@ pub fn quote_args(
use ::sqlx::ty_match::{WrapSameExt as _, MatchBorrowExt as _};
// evaluate the expression only once in case it contains moves
- let _expr = ::sqlx::ty_match::dupe_value(#name);
+ let expr = ::sqlx::ty_match::dupe_value(#name);
- // if `_expr` is `Option`, get `Option<$ty>`, otherwise `$ty`
- let ty_check = ::sqlx::ty_match::WrapSame::<#param_ty, _>::new(&_expr).wrap_same();
+ // if `expr` is `Option`, get `Option<$ty>`, otherwise `$ty`
+ let ty_check = ::sqlx::ty_match::WrapSame::<#param_ty, _>::new(&expr).wrap_same();
- // if `_expr` is `&str`, convert `String` to `&str`
- let (mut _ty_check, match_borrow) = ::sqlx::ty_match::MatchBorrow::new(ty_check, &_expr);
+ // if `expr` is `&str`, convert `String` to `&str`
+ let (mut _ty_check, match_borrow) = ::sqlx::ty_match::MatchBorrow::new(ty_check, &expr);
_ty_check = match_borrow.match_borrow();