Skip to content

Commit

Permalink
Add example with external query files (#1967)
Browse files Browse the repository at this point in the history
* feat(examples): add files example for postgres

* fix(examples): add missing deps
  • Loading branch information
JoeyMckenzie committed Jul 13, 2022
1 parent 7d8ded9 commit d6c4eff
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 0 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ members = [
"sqlx-cli",
"sqlx-bench",
"examples/mysql/todos",
"examples/postgres/files",
"examples/postgres/json",
"examples/postgres/listen",
"examples/postgres/todos",
Expand Down
12 changes: 12 additions & 0 deletions examples/postgres/files/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "files"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anyhow = "1.0"
async-std = { version = "1.8.0", features = [ "attributes" ] }
sqlx = { path = "../../../", features = ["postgres", "offline", "runtime-async-std-native-tls"] }
dotenv = "0.15.0"
36 changes: 36 additions & 0 deletions examples/postgres/files/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Query files Example

## Description

This example demonstrates storing external files to use for querying data.
Encapsulating your SQL queries can be helpful in several ways, assisting with intellisense,
etc.


## Setup

1. Declare the database URL

```
export DATABASE_URL="postgres://postgres:password@localhost/files"
```

2. Create the database.

```
$ sqlx db create
```

3. Run sql migrations

```
$ sqlx migrate run
```

## Usage

Run the project

```
cargo run files
```
14 changes: 14 additions & 0 deletions examples/postgres/files/migrations/20220712221654_files.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CREATE TABLE IF NOT EXISTS users
(
id BIGSERIAL PRIMARY KEY,
username TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS posts
(
id BIGSERIAL PRIMARY KEY,
title TEXT NOT NULL,
body TEXT NOT NULL,
user_id BIGINT NOT NULL
REFERENCES users (id) ON DELETE CASCADE
);
11 changes: 11 additions & 0 deletions examples/postgres/files/queries/insert_seed_data.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-- seed some data to work with
WITH inserted_users_cte AS (
INSERT INTO users (username)
VALUES ('user1'),
('user2')
RETURNING id as "user_id"
)
INSERT INTO posts (title, body, user_id)
VALUES ('user1 post1 title', 'user1 post1 body', (SELECT user_id FROM inserted_users_cte FETCH FIRST ROW ONLY)),
('user1 post2 title', 'user1 post2 body', (SELECT user_id FROM inserted_users_cte FETCH FIRST ROW ONLY)),
('user2 post1 title', 'user2 post2 body', (SELECT user_id FROM inserted_users_cte OFFSET 1 LIMIT 1));
7 changes: 7 additions & 0 deletions examples/postgres/files/queries/list_all_posts.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
SELECT p.id as "post_id",
p.title,
p.body,
u.id as "author_id",
u.username as "author_username"
FROM users u
JOIN posts p on u.id = p.user_id;
48 changes: 48 additions & 0 deletions examples/postgres/files/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use sqlx::{query_file, query_file_as, query_file_unchecked, FromRow, PgPool};
use std::fmt::{Display, Formatter};

#[derive(FromRow)]
struct PostWithAuthorQuery {
pub post_id: i64,
pub title: String,
pub body: String,
pub author_id: i64,
pub author_username: String,
}

impl Display for PostWithAuthorQuery {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
r#"
post_id: {},
title: {},
body: {},
author_id: {},
author_username: {}
"#,
self.post_id, self.title, self.body, self.author_id, self.author_username
)
}
}

#[async_std::main]
async fn main() -> anyhow::Result<()> {
let pool = PgPool::connect(&dotenv::var("DATABASE_URL")?).await?;

// we can use a tranditional wrapper around the `query!()` macro using files
query_file!("queries/insert_seed_data.sql")
.execute(&pool)
.await?;

// we can also use `query_file_as!()` similarly to `query_as!()` to map our database models
let posts_with_authors = query_file_as!(PostWithAuthorQuery, "queries/list_all_posts.sql")
.fetch_all(&pool)
.await?;

for post_with_author in posts_with_authors {
println!("{}", post_with_author);
}

Ok(())
}

0 comments on commit d6c4eff

Please sign in to comment.