Skip to content

Commit

Permalink
Merge branch 'master' into ws-support
Browse files Browse the repository at this point in the history
  • Loading branch information
vbeffa committed Jul 9, 2021
2 parents 38d57b5 + 358b80f commit e20ab8d
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 21 deletions.
50 changes: 39 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
<br />

<div align="center">
<sub>Built with ❤️ by <a href="https://launchbadge.com">The LaunchBadge team</a></sub>
<small>Built with ❤️ by <a href="https://launchbadge.com">The LaunchBadge team</a></small>
</div>

<br />
Expand All @@ -59,20 +59,23 @@ SQLx is an async, pure Rust<sub>†</sub> 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<sub>††</sub> 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`]).

<sub><sup>† 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).</sup></sub>
<small><small>

<sub><sup>†† SQLx uses `#![forbid(unsafe_code)]` unless the `sqlite` feature is enabled. As the SQLite driver interacts
with C, those interactions are `unsafe`.</sup></sub>
† 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`.

</small></small>

[postgresql]: http://postgresql.org/
[sqlite]: https://sqlite.org/
Expand Down Expand Up @@ -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
Expand All @@ -118,7 +123,7 @@ sqlx = { version = "0.5", features = [ "runtime-tokio-rustls" ] }
sqlx = { version = "0.5", features = [ "runtime-async-std-native-tls" ] }
```

<sub><sup>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).</sup></sub>
<small><small>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).</small></small>

#### Cargo Feature Flags

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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.
Expand Down
17 changes: 12 additions & 5 deletions sqlx-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,28 +49,32 @@ $ 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
{
"database": "PostgreSQL"
}
```

----
---

```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.

Expand All @@ -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.
10 changes: 5 additions & 5 deletions sqlx-macros/src/query/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@ pub fn quote_args<DB: DatabaseExt>(
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<T>`, get `Option<$ty>`, otherwise `$ty`
let ty_check = ::sqlx::ty_match::WrapSame::<#param_ty, _>::new(&_expr).wrap_same();
// if `expr` is `Option<T>`, 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();

Expand Down

0 comments on commit e20ab8d

Please sign in to comment.