mirror of https://github.com/rwf2/Rocket.git
Update 'databases' example README.
The README now more completely documents the example. All implementations now make use of 'RETURNING'.
This commit is contained in:
parent
e581e3f98e
commit
7790e363b1
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "INSERT INTO posts (title, text) VALUES (?, ?)",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "3c289da9873097a11191dbedc5c78d86afd6a6d36771bfeb12f331abca6279cf"
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "INSERT INTO posts (title, text) VALUES (?, ?) RETURNING id",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"ordinal": 0,
|
||||
"type_info": "Int64"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "bea4ef6e25064f6b383e854f8bc2770d89cfaf9859d0bfca78b2ca24627675b7"
|
||||
}
|
|
@ -7,7 +7,7 @@ publish = false
|
|||
|
||||
[dependencies]
|
||||
rocket = { path = "../../core/lib", features = ["json"] }
|
||||
diesel = "2"
|
||||
diesel = { version = "2", features = ["returning_clauses_for_sqlite_3_35"] }
|
||||
diesel_migrations = "2"
|
||||
|
||||
[dependencies.sqlx]
|
||||
|
|
|
@ -1,8 +1,69 @@
|
|||
# Databases Example
|
||||
|
||||
This example makes use of SQLite. You'll need `sqlite3` and its development
|
||||
headers installed:
|
||||
This example makes use of SQLite and MySQL. You'll need `sqlite3` and a MySQL
|
||||
client installed:
|
||||
|
||||
* **macOS:** `brew install sqlite`
|
||||
* **Debian**, **Ubuntu:** `apt-get install libsqlite3-dev`
|
||||
* **Arch:** `pacman -S sqlite`
|
||||
* **macOS:** `brew install sqlite mysql-client`
|
||||
* **Debian**, **Ubuntu:** `apt-get install libsqlite3-dev libmysqlclient-dev`
|
||||
* **Arch:** `pacman -S sqlite libmysqlclient`
|
||||
|
||||
## API Implementation
|
||||
|
||||
This example implements a JSON-based HTTP API for a "blog" using several database drivers:
|
||||
|
||||
* `sqlx` (`/sqlx`, `sqlx.rs`)
|
||||
* `rusqlite` (`/rusqlite`, `rusqlite.rs`)
|
||||
* `diesel` (sqlite) (`/diesel`, `diesel_sqlite.rs`)
|
||||
* `diesel-async` (mysql) (`/diesel-async`, `diesel_mysql.rs`)
|
||||
|
||||
The exposed API is succinctly described as follows, with
|
||||
[`httpie`](https://httpie.io/) CLI examples:
|
||||
|
||||
* `POST /driver`: create post via JSON with `title` and `text`; returns new
|
||||
post JSON with new `id`
|
||||
|
||||
http http://127.0.0.1:8000/sqlx title="Title" text="Hello, world."
|
||||
> { "id": 2128, "text": "Hello, world.", "title": "Title" }
|
||||
|
||||
* `GET /driver`: returns JSON array of IDs for blog posts
|
||||
|
||||
http http://127.0.0.1:8000/sqlx
|
||||
> [ 2128, 2129, 2130, 2131 ]
|
||||
|
||||
* `GET /driver/<id>`: returns a JSON object for the post with id `<id>`
|
||||
|
||||
http http://127.0.0.1:8000/sqlx/2128
|
||||
> { "id": 2128, "text": "Hello, world.", "title": "Title" }
|
||||
|
||||
* `DELETE /driver`: delete all posts
|
||||
|
||||
http delete http://127.0.0.1:8000/sqlx
|
||||
|
||||
* `DELETE /driver/<id>`: delete post with id `<id>`
|
||||
|
||||
http delete http://127.0.0.1:8000/sqlx/4
|
||||
|
||||
## Migrations
|
||||
|
||||
Database migrations are stored in the respective `db/${driver}` directory.
|
||||
|
||||
### `diesel`
|
||||
|
||||
Diesel migrations are found in `db/diesel/migrations`. They are run
|
||||
automatically. They can be run manually as well:
|
||||
|
||||
```sh
|
||||
cargo install diesel_cli --no-default-features --features sqlite
|
||||
DATABASE_URL="db/diesel/db.sqlite" diesel migration --migration-dir db/diesel/migrations redo
|
||||
```
|
||||
|
||||
### `sqlx`
|
||||
|
||||
sqlx migrations are found in `db/sqlx/migrations`. They are run automatically.
|
||||
|
||||
Query metadata for offline checking was prepared with the following commands:
|
||||
|
||||
```sh
|
||||
cargo install sqlx-cli --no-default-features --features sqlite
|
||||
DATABASE_URL="sqlite:$(pwd)/db/sqlx/db.sqlite" cargo sqlx prepare
|
||||
```
|
||||
|
|
|
@ -92,6 +92,6 @@ async fn destroy(mut db: Connection<Db>) -> Result<()> {
|
|||
pub fn stage() -> AdHoc {
|
||||
AdHoc::on_ignite("Diesel SQLite Stage", |rocket| async {
|
||||
rocket.attach(Db::init())
|
||||
.mount("/diesel-async/", routes![list, read, create, delete, destroy])
|
||||
.mount("/diesel-async", routes![list, read, create, delete, destroy])
|
||||
})
|
||||
}
|
||||
|
|
|
@ -32,14 +32,16 @@ table! {
|
|||
}
|
||||
|
||||
#[post("/", data = "<post>")]
|
||||
async fn create(db: Db, post: Json<Post>) -> Result<Created<Json<Post>>> {
|
||||
async fn create(db: Db, mut post: Json<Post>) -> Result<Created<Json<Post>>> {
|
||||
let post_value = post.clone();
|
||||
db.run(move |conn| {
|
||||
let id: Option<i32> = db.run(move |conn| {
|
||||
diesel::insert_into(posts::table)
|
||||
.values(&*post_value)
|
||||
.execute(conn)
|
||||
.returning(posts::id)
|
||||
.get_result(conn)
|
||||
}).await?;
|
||||
|
||||
post.id = Some(id.expect("returning guarantees id present"));
|
||||
Ok(Created::new("/").body(post))
|
||||
}
|
||||
|
||||
|
|
|
@ -22,13 +22,15 @@ struct Post {
|
|||
type Result<T, E = Debug<rusqlite::Error>> = std::result::Result<T, E>;
|
||||
|
||||
#[post("/", data = "<post>")]
|
||||
async fn create(db: Db, post: Json<Post>) -> Result<Created<Json<Post>>> {
|
||||
async fn create(db: Db, mut post: Json<Post>) -> Result<Created<Json<Post>>> {
|
||||
let item = post.clone();
|
||||
db.run(move |conn| {
|
||||
conn.execute("INSERT INTO posts (title, text) VALUES (?1, ?2)",
|
||||
params![item.title, item.text])
|
||||
let id = db.run(move |conn| {
|
||||
conn.query_row("INSERT INTO posts (title, text) VALUES (?1, ?2) RETURNING id",
|
||||
params![item.title, item.text],
|
||||
|r| r.get(0))
|
||||
}).await?;
|
||||
|
||||
post.id = Some(id);
|
||||
Ok(Created::new("/").body(post))
|
||||
}
|
||||
|
||||
|
|
|
@ -23,12 +23,13 @@ struct Post {
|
|||
}
|
||||
|
||||
#[post("/", data = "<post>")]
|
||||
async fn create(mut db: Connection<Db>, post: Json<Post>) -> Result<Created<Json<Post>>> {
|
||||
// There is no support for `RETURNING`.
|
||||
sqlx::query!("INSERT INTO posts (title, text) VALUES (?, ?)", post.title, post.text)
|
||||
.execute(&mut **db)
|
||||
.await?;
|
||||
async fn create(mut db: Connection<Db>, mut post: Json<Post>) -> Result<Created<Json<Post>>> {
|
||||
let query = sqlx::query! {
|
||||
"INSERT INTO posts (title, text) VALUES (?, ?) RETURNING id",
|
||||
post.title, post.text
|
||||
};
|
||||
|
||||
post.id = Some(query.fetch_one(&mut **db).await?.id);
|
||||
Ok(Created::new("/").body(post))
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue