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-bench/Cargo.toml b/sqlx-bench/Cargo.toml
index 0b288ca892..167311ac53 100644
--- a/sqlx-bench/Cargo.toml
+++ b/sqlx-bench/Cargo.toml
@@ -45,3 +45,8 @@ sqlx-rt = { version = "0.5", path = "../sqlx-rt", default-features = false }
name = "pg_pool"
harness = false
required-features = ["postgres"]
+
+[[bench]]
+name = "wasm_querying"
+harness = false
+required-features = ["postgres"]
diff --git a/sqlx-bench/benches/wasm_querying.rs b/sqlx-bench/benches/wasm_querying.rs
new file mode 100644
index 0000000000..0c6e89facd
--- /dev/null
+++ b/sqlx-bench/benches/wasm_querying.rs
@@ -0,0 +1,26 @@
+use criterion::{black_box, criterion_group, criterion_main, Criterion};
+use sqlx::Row;
+use sqlx::{postgres::PgRow, Connection};
+use sqlx::{Database, PgConnection, Postgres};
+use sqlx_rt::spawn;
+
+const URL: &str = "postgresql://paul:pass123@127.0.0.1:8080/jetasap_dev";
+
+fn select() {
+ spawn(async {
+ let mut conn = ::Connection::connect(URL)
+ .await
+ .unwrap();
+
+ let airports = sqlx::query("select * from airports")
+ .fetch_all(&mut conn)
+ .await;
+ });
+}
+
+fn criterion_benchmark(c: &mut Criterion) {
+ c.bench_function("fib 20", |b| b.iter(|| select()));
+}
+
+criterion_group!(benches, criterion_benchmark);
+criterion_main!(benches);
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();
diff --git a/sqlx-rt/src/lib.rs b/sqlx-rt/src/lib.rs
index 527b66c580..9b82302d99 100644
--- a/sqlx-rt/src/lib.rs
+++ b/sqlx-rt/src/lib.rs
@@ -5,8 +5,7 @@
feature = "runtime-actix-rustls",
feature = "runtime-async-std-rustls",
feature = "runtime-tokio-rustls",
- )
-))]
+)))]
compile_error!(
"one of the features ['runtime-actix-native-tls', 'runtime-async-std-native-tls', \
'runtime-tokio-native-tls', 'runtime-actix-rustls', 'runtime-async-std-rustls', \
diff --git a/sqlx-wasm-test/src/pg_types_tests_ipnetwork.rs b/sqlx-wasm-test/src/pg_types_tests_ipnetwork.rs
index 206a15ff49..71e18bff8b 100644
--- a/sqlx-wasm-test/src/pg_types_tests_ipnetwork.rs
+++ b/sqlx-wasm-test/src/pg_types_tests_ipnetwork.rs
@@ -50,4 +50,3 @@ test_type!(ipnetwork_vec>(Postgres,
"8.8.8.8/24".parse::().unwrap()
]
));
-