2019-12-28 01:31:01 +00:00
< h1 align = "center" > SQLx< / h1 >
< div align = "center" >
< strong >
🧰 The Rust SQL Toolkit
< / strong >
< / div >
< br / >
< div align = "center" >
2020-03-28 00:42:23 +00:00
<!-- Github Actions -->
2020-06-07 09:41:39 +00:00
< img src = "https://img.shields.io/github/workflow/status/launchbadge/sqlx/SQLx?style=flat-square" alt = "actions status" / >
2019-12-30 10:29:56 +00:00
<!-- Version -->
2019-12-28 01:31:01 +00:00
< a href = "https://crates.io/crates/sqlx" >
< img src = "https://img.shields.io/crates/v/sqlx.svg?style=flat-square"
alt="Crates.io version" />
< / a >
2020-01-12 18:22:12 +00:00
<!-- Discord -->
2020-01-12 22:02:52 +00:00
< a href = "https://discord.gg/uuruzJ7" >
< img src = "https://img.shields.io/discord/665528275556106240?style=flat-square" alt = "chat" / >
< / a >
2019-12-30 10:29:56 +00:00
<!-- Docs -->
2019-12-28 01:31:01 +00:00
< a href = "https://docs.rs/sqlx" >
< img src = "https://img.shields.io/badge/docs-latest-blue.svg?style=flat-square"
alt="docs.rs docs" />
< / a >
2020-03-28 00:42:23 +00:00
<!-- Downloads -->
< a href = "https://crates.io/crates/sqlx" >
< img src = "https://img.shields.io/crates/d/sqlx.svg?style=flat-square"
alt="Download" />
< / a >
< / div >
< div align = "center" >
< h4 >
< a href = "#install" >
Install
< / a >
< span > | < / span >
< a href = "#usage" >
Usage
< / a >
< span > | < / span >
< a href = "https://docs.rs/sqlx" >
Docs
< / a >
< / h4 >
2019-12-28 01:31:01 +00:00
< / div >
2019-12-28 09:37:02 +00:00
< br / >
2019-12-28 01:31:01 +00:00
< div align = "center" >
2020-03-28 00:42:23 +00:00
< sub > Built with ❤️ by < a href = "https://launchbadge.com" > The LaunchBadge team< / a > < / sub >
2019-12-28 01:31:01 +00:00
< / div >
< br / >
2020-07-14 13:33:36 +00:00
SQLx is an async, pure Rust< sub > †< / sub > SQL crate featuring compile-time checked queries without a DSL.
2019-12-28 01:31:01 +00:00
2020-01-15 09:27:19 +00:00
* **Truly Asynchronous**. Built from the ground-up using async/await for maximum concurrency.
2019-12-28 01:31:01 +00:00
2020-07-14 13:33:36 +00:00
* **Type-safe SQL** (if you want it) without DSLs. Use the `query!()` macro to check your SQL and bind parameters at
2019-12-30 15:11:43 +00:00
compile time. (You can still use dynamic SQL queries if you like.)
2019-12-28 09:37:02 +00:00
2020-07-27 09:11:46 +00:00
* **Database Agnostic**. Support for [PostgreSQL], [MySQL], [SQLite], and [MSSQL].
2020-03-28 00:42:23 +00:00
* **Pure Rust**. The Postgres and MySQL/MariaDB drivers are written in pure Rust using **zero** unsafe< sub > ††</ sub > code.
2020-07-14 13:33:36 +00:00
2020-01-15 09:27:19 +00:00
* **Runtime Agnostic**. Works on [async-std ](https://crates.io/crates/async-std ) or [tokio ](https://crates.io/crates/tokio ) with the `runtime-async-std` or `runtime-tokio` cargo feature flag.
2020-07-14 13:33:36 +00:00
< sub > < sup > † The SQLite driver uses the libsqlite3 C library as SQLite is an embedded database (the only way
2020-03-28 00:42:23 +00:00
we could be pure Rust for SQLite is by porting _all_ of SQLite to Rust).</ sup ></ sub >
< 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 >
[PostgreSQL]: http://postgresql.org/
[SQLite]: https://sqlite.org/
[MySQL]: https://www.mysql.com/
2020-07-27 09:11:46 +00:00
[MSSQL]: https://www.microsoft.com/en-us/sql-server
2020-03-28 00:42:23 +00:00
---
* Cross-platform. Being native Rust, SQLx will compile anywhere Rust is supported.
* Built-in connection pooling with `sqlx::Pool` .
2020-07-14 13:33:36 +00:00
2020-03-28 00:42:23 +00:00
* Row streaming. Data is read asynchronously from the database and decoded on-demand.
2020-07-14 13:33:36 +00:00
* Automatic statement preparation and caching. When using the high-level query API (`sqlx::query`), statements are
prepared and cached per-connection.
* Simple (unprepared) query execution including fetching results into the same `Row` types used by
2020-03-28 00:42:23 +00:00
the high-level API. Supports batch execution and returning results from all statements.
2020-07-14 13:33:36 +00:00
2020-04-05 11:34:43 +00:00
* Transport Layer Security (TLS) where supported ([MySQL] and [PostgreSQL]).
2020-07-14 13:33:36 +00:00
2020-03-28 00:42:23 +00:00
* Asynchronous notifications using `LISTEN` and `NOTIFY` for [PostgreSQL].
2020-07-14 13:33:36 +00:00
2020-03-28 00:42:23 +00:00
* Nested transactions with support for save points.
2020-07-27 09:11:46 +00:00
* `Any` database driver for changing the database driver at runtime. An `AnyPool` connects to the driver indicated by the URI scheme.
2020-01-15 09:27:19 +00:00
## Install
2020-03-28 00:42:23 +00:00
SQLx is compatible with the [`async-std`] and [`tokio`] runtimes.
[`async-std`]: https://github.com/async-rs/async-std
[`tokio`]: https://github.com/tokio-rs/tokio
2020-01-15 09:27:19 +00:00
**async-std**
```toml
# Cargo.toml
[dependencies]
2020-07-28 14:01:19 +00:00
sqlx = "0.4.0-beta.1"
2020-01-15 09:27:19 +00:00
```
**tokio**
```toml
# Cargo.toml
[dependencies]
2020-07-28 14:01:19 +00:00
sqlx = { version = "0.4.0-beta.1", default-features = false, features = [ "runtime-tokio", "macros" ] }
2020-01-15 09:27:19 +00:00
```
2020-11-02 01:37:19 +00:00
**actix**
```toml
# Cargo.toml
[dependencies]
sqlx = { version = "0.4.0-beta.1", default-features = false, features = [ "runtime-actix", "macros" ] }
```
2020-01-15 09:27:19 +00:00
#### Cargo Feature Flags
* `runtime-async-std` (on by default): Use the `async-std` runtime.
2020-07-14 13:33:36 +00:00
2020-11-02 01:38:41 +00:00
* `runtime-tokio` : Use the `tokio` runtime. Mutually exclusive to all other runtimes.
2020-11-02 01:37:19 +00:00
2020-11-02 01:38:41 +00:00
* `runtime-actix` : Use the `actix_rt` runtime. Mutually exclusive to all other runtimes.
2020-07-14 13:33:36 +00:00
2020-01-15 09:27:19 +00:00
* `postgres` : Add support for the Postgres database server.
2020-07-14 13:33:36 +00:00
2020-01-15 09:27:19 +00:00
* `mysql` : Add support for the MySQL (and MariaDB) database server.
2020-07-14 13:33:36 +00:00
2020-07-27 09:11:46 +00:00
* `mssql` : Add support for the MSSQL database server.
2020-03-19 05:51:31 +00:00
* `sqlite` : Add support for the self-contained [SQLite ](https://sqlite.org/ ) database engine.
2020-07-14 13:33:36 +00:00
2020-07-27 09:11:46 +00:00
* `any` : Add support for the `Any` database driver, which can proxy to a database driver at runtime.
2020-10-14 13:53:20 +00:00
* `macros` : Add support for the `query*!` macros, which allow compile-time checked queries.
2020-11-02 01:37:19 +00:00
* `migrate` : Add support for the migration management and `migrate!` macro, which allow compile-time embedded migrations.
2020-10-14 13:53:20 +00:00
2020-01-15 09:27:19 +00:00
* `uuid` : Add support for UUID (in Postgres).
2020-07-14 13:33:36 +00:00
2020-01-15 09:27:19 +00:00
* `chrono` : Add support for date and time types from `chrono` .
2020-07-14 13:33:36 +00:00
2020-03-04 19:11:46 +00:00
* `time` : Add support for date and time types from `time` crate (alternative to `chrono` , prefered by `query!` macro, if both enabled)
2020-07-14 13:33:36 +00:00
2020-03-28 00:42:23 +00:00
* `bigdecimal` : Add support for `NUMERIC` using the `bigdecimal` crate.
2020-07-14 13:33:36 +00:00
2020-07-30 03:57:18 +00:00
* `decimal` : Add support for `NUMERIC` using the `rust_decimal` crate.
2020-03-28 00:42:23 +00:00
* `ipnetwork` : Add support for `INET` and `CIDR` (in postgres) using the `ipnetwork` crate.
2020-07-14 13:33:36 +00:00
2020-03-28 00:42:23 +00:00
* `json` : Add support for `JSON` and `JSONB` (in postgres) using the `serde_json` crate.
2020-02-29 19:38:48 +00:00
2020-01-15 09:27:19 +00:00
* `tls` : Add support for TLS connections.
2020-07-14 13:33:36 +00:00
2020-03-28 00:42:23 +00:00
## Usage
2019-12-28 09:37:02 +00:00
2020-03-28 00:42:23 +00:00
### Quickstart
2019-12-28 09:37:02 +00:00
2020-03-28 00:42:23 +00:00
```rust
use std::env;
2020-07-27 09:11:46 +00:00
use sqlx::postgres::PgPoolOptions;
// use sqlx::mysql::MySqlPoolOptions;
2020-03-28 00:42:23 +00:00
// etc.
#[async_std::main] // or #[tokio::main]
async fn main() -> Result< (), sqlx::Error> {
// Create a connection pool
2020-07-14 13:33:36 +00:00
let pool = PgPoolOptions::new()
2020-07-12 11:42:48 +00:00
.max_connections(5)
2020-07-14 13:33:36 +00:00
.connect(&env::var("DATABASE_URL")?).await?;
2020-03-28 00:42:23 +00:00
// Make a simple query to return the given parameter
let row: (i64,) = sqlx::query_as("SELECT $1")
.bind(150_i64)
.fetch_one(&pool).await?;
2020-07-14 13:33:36 +00:00
2020-03-28 00:42:23 +00:00
assert_eq!(row.0, 150);
Ok(())
}
```
2020-01-15 09:27:19 +00:00
2020-03-28 00:42:23 +00:00
### Connecting
2020-07-14 13:33:36 +00:00
A single connection can be established using any of the database connection types and calling `connect()` .
2020-01-15 09:27:19 +00:00
```rust
2020-07-27 09:11:46 +00:00
use sqlx::Connection;
2020-03-28 00:42:23 +00:00
let conn = SqliteConnection::connect("sqlite::memory:").await?;
2020-01-15 09:27:19 +00:00
```
2020-07-14 13:33:36 +00:00
Generally, you will want to instead create a connection pool (`sqlx::Pool`) in order for your application to
2020-03-28 00:42:23 +00:00
regulate how many server-side connections it's using.
```rust
2020-07-27 09:11:46 +00:00
let pool = MySqlPool::connect("mysql://user:pass@host/database").await?;
2020-07-14 13:33:36 +00:00
```
2020-03-28 00:42:23 +00:00
### Querying
2020-01-15 09:27:19 +00:00
2020-03-28 00:42:23 +00:00
In SQL, queries can be separated into prepared (parameterized) or unprepared (simple). Prepared queries have their
query plan _cached_ , use a binary mode of communication (lower bandwidth and faster decoding), and utilize parameters
to avoid SQL injection. Unprepared queries are simple and intended only for use case where a prepared statement
2020-07-14 13:33:36 +00:00
will not work, such as various database commands (e.g., `PRAGMA` or `SET` or `BEGIN` ).
2020-03-28 00:42:23 +00:00
2020-07-14 13:33:36 +00:00
SQLx supports all operations with both types of queries. In SQLx, a `&str` is treated as an unprepared query
2020-03-28 00:42:23 +00:00
and a `Query` or `QueryAs` struct is treated as a prepared query.
2019-12-28 09:37:02 +00:00
```rust
2020-03-28 00:42:23 +00:00
// low-level, Executor trait
conn.execute("BEGIN").await?; // unprepared, simple query
conn.execute(sqlx::query("DELETE FROM table")).await?; // prepared, cached query
```
We should prefer to use the high level, `query` interface whenever possible. To make this easier, there are finalizers
on the type to avoid the need to wrap with an executor.
```rust
sqlx::query("DELETE FROM table").execute(& mut conn).await?;
sqlx::query("DELETE FROM table").execute(&pool).await?;
```
2020-07-14 13:33:36 +00:00
The `execute` query finalizer returns the number of affected rows, if any, and drops all received results.
2020-03-28 00:42:23 +00:00
In addition, there are `fetch` , `fetch_one` , `fetch_optional` , `fetch_all` , and `fetch_scalar` to receive results.
The `Query` type returned from `sqlx::query` will return `Row<'conn>` from the database. Column values can be accessed
2020-07-14 13:33:36 +00:00
by ordinal or by name with `row.get()` . As the `Row` retains an immutable borrow on the connection, only one
2020-03-28 00:42:23 +00:00
`Row` may exist at a time.
The `fetch` query finalizer returns a stream-like type that iterates through the rows in the result sets.
```rust
2020-07-27 09:11:46 +00:00
// provides `try_next`
use futures::TryStreamExt;
let mut rows = sqlx::query("SELECT * FROM users WHERE email = ?")
2020-03-28 00:42:23 +00:00
.bind(email)
2020-05-28 16:48:08 +00:00
.fetch(& mut conn);
2020-03-28 00:42:23 +00:00
2020-07-27 09:11:46 +00:00
while let Some(row) = rows.try_next().await? {
2020-07-14 13:33:36 +00:00
// map the row into a user-defined domain type
2020-07-27 09:11:46 +00:00
let email: & str = row.try_get("email")?;
2020-03-28 00:42:23 +00:00
}
```
To assist with mapping the row into a domain type, there are two idioms that may be used:
```rust
let mut stream = sqlx::query("SELECT * FROM users")
.map(|row: PgRow| {
// map the row into a user-defined domain type
})
.fetch(& mut conn);
```
```rust
2020-04-13 19:15:12 +00:00
#[derive(sqlx::FromRow)]
2020-03-28 00:42:23 +00:00
struct User { name: String, id: i64 }
let mut stream = sqlx::query_as::< _ , User > ("SELECT * FROM users WHERE email = ? OR name = ?")
.bind(user_email)
.bind(user_name)
.fetch(& mut conn);
2019-12-28 09:37:02 +00:00
```
2020-07-14 13:33:36 +00:00
Instead of a stream of results, we can use `fetch_one` or `fetch_optional` to request one required or optional result
2020-03-28 00:42:23 +00:00
from the database.
### Compile-time verification
2020-01-15 09:27:19 +00:00
2020-07-14 13:33:36 +00:00
We can use the macro, `sqlx::query!` to achieve compile-time syntactic and semantic verification of the SQL, with
2020-03-28 00:42:23 +00:00
an output to an anonymous record type where each SQL column is a Rust field (using raw identifiers where needed).
2019-12-28 09:37:02 +00:00
```rust
let countries = sqlx::query!(
2020-03-28 00:42:23 +00:00
"
2020-07-14 13:33:36 +00:00
SELECT country, COUNT(*) as count
FROM users
GROUP BY country
2020-03-28 00:42:23 +00:00
WHERE organization = ?
2020-07-14 13:33:36 +00:00
",
2019-12-28 09:37:02 +00:00
organization
)
2020-04-11 11:17:36 +00:00
.fetch_all(& pool) // -> Vec< { country: String, count: i64 }>
2019-12-28 09:37:02 +00:00
.await?;
2020-03-28 00:42:23 +00:00
// countries[0].country
// countries[0].count
2019-12-28 09:37:02 +00:00
```
2020-03-28 00:42:23 +00:00
Differences from `query()` :
2020-07-14 13:33:36 +00:00
* The input (or bind) parameters must be given all at once (and they are compile-time validated to be
2020-03-28 00:42:23 +00:00
the right number and the right type).
2020-07-14 13:33:36 +00:00
2020-03-28 00:42:23 +00:00
* The output type is an anonymous record. In the above example the type would be similar to:
2020-07-14 13:33:36 +00:00
2020-03-28 00:42:23 +00:00
```rust
{ country: String, count: i64 }
2020-07-14 13:33:36 +00:00
```
* The `DATABASE_URL` environment variable must be set at build time to a database which it can prepare
queries against; the database does not have to contain any data but must be the same
2020-03-28 00:42:23 +00:00
kind (MySQL, Postgres, etc.) and have the same schema as the database you will be connecting to at runtime.
2020-07-14 13:33:36 +00:00
2020-03-28 00:42:23 +00:00
For convenience, you can use a .env file to set DATABASE_URL so that you don't have to pass it every time:
2020-07-14 13:33:36 +00:00
2020-03-28 00:42:23 +00:00
```
DATABASE_URL=mysql://localhost/my_database
2020-07-14 13:33:36 +00:00
```
2020-03-28 00:42:23 +00:00
2020-07-14 13:33:36 +00:00
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
2020-03-28 00:42:23 +00:00
except that you can name the output type.
2020-01-30 11:34:09 +00:00
2020-03-28 00:42:23 +00:00
```rust
// no traits are needed
struct Country { country: String, count: i64 }
let countries = sqlx::query_as!(Country,
"
2020-07-14 13:33:36 +00:00
SELECT country, COUNT(*) as count
FROM users
GROUP BY country
2020-03-28 00:42:23 +00:00
WHERE organization = ?
2020-07-14 13:33:36 +00:00
",
2020-03-28 00:42:23 +00:00
organization
)
2020-10-29 20:46:05 +00:00
.fetch_all(& pool) // -> Vec< Country >
2020-03-28 00:42:23 +00:00
.await?;
2020-01-30 11:34:09 +00:00
2020-03-28 00:42:23 +00:00
// countries[0].country
// countries[0].count
```
2019-12-28 09:41:07 +00:00
2019-12-28 01:31:01 +00:00
## Safety
2019-08-07 05:47:32 +00:00
2020-07-14 13:33:36 +00:00
This crate uses `#![forbid(unsafe_code)]` to ensure everything is implemented in 100% Safe Rust.
2020-03-28 00:42:23 +00:00
2020-07-14 13:33:36 +00:00
If the `sqlite` feature is enabled, this is downgraded to `#![deny(unsafe_code)]` with `#![allow(unsafe_code)]` on the
2020-03-30 23:39:59 +00:00
`sqlx::sqlite` module. There are several places where we interact with the C SQLite API. We try to document each call for the invariants we're assuming. We absolutely welcome auditing of, and feedback on, our unsafe code usage.
2019-06-09 16:38:10 +00:00
2019-06-06 13:02:55 +00:00
## License
Licensed under either of
* Apache License, Version 2.0
([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license
([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
## Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.