Skip to content

Commit

Permalink
docs: add postgres driver and sqlx examples
Browse files Browse the repository at this point in the history
  • Loading branch information
brianheineman committed Feb 22, 2024
1 parent ee496e1 commit 5023bf6
Show file tree
Hide file tree
Showing 9 changed files with 1,124 additions and 37 deletions.
939 changes: 904 additions & 35 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion examples/embedded_async/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,3 @@ version.workspace = true
[dependencies]
postgresql_embedded = { path = "../../postgresql_embedded" }
tokio = { workspace = true }

11 changes: 11 additions & 0 deletions examples/postgres_embedded/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
edition.workspace = true
name = "postgres_embedded"
publish = false
license.workspace = true
version.workspace = true

[dependencies]
anyhow = { workspace = true }
postgres = { version = "0.19" }
postgresql_embedded = { path = "../../postgresql_embedded", features = ["blocking"] }
2 changes: 2 additions & 0 deletions examples/postgres_embedded/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
This example is based on [sqlx/example/todos](https://github.com/launchbadge/sqlx/tree/main/examples/postgres/todos)
and modified to work with the postgres driver.
95 changes: 95 additions & 0 deletions examples/postgres_embedded/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use anyhow::Result;
use postgres::{Client, NoTls};
use postgresql_embedded::blocking::PostgreSQL;

fn main() -> Result<()> {
let mut postgresql = PostgreSQL::default();
postgresql.setup()?;
postgresql.start()?;

let database_name = "test";
postgresql.create_database(database_name)?;
let settings = postgresql.settings();
let host = settings.host.to_string();
let port = settings.port.to_string();
let username = settings.username.to_string();
let password = settings.password.to_string();

let mut client = Client::connect(
format!("host={host} port={port} user={username} password={password}").as_str(),
NoTls,
)?;

println!("Creating table 'todos'");
create_table_todo(&mut client)?;

let description = "Implement embedded database with sqlx";
println!("Adding new todo with description '{description}'");
let todo_id = add_todo(&mut client, description)?;
println!("Added new todo with id {todo_id}");

println!("Marking todo {todo_id} as done");
if complete_todo(&mut client, todo_id)? {
println!("Todo {todo_id} is marked as done");
} else {
println!("Invalid id {todo_id}");
}

println!("Printing list of all todos");
list_todos(&mut client)?;

Ok(())
}

fn create_table_todo(client: &mut Client) -> Result<()> {
let _ = client.execute(
"CREATE TABLE IF NOT EXISTS todos (id BIGSERIAL PRIMARY KEY, description TEXT NOT NULL, done BOOLEAN NOT NULL DEFAULT FALSE);",
&[],
)?;

Ok(())
}

fn add_todo(client: &mut Client, description: &str) -> Result<i64> {
let row = client.query_one(
"INSERT INTO todos (description) VALUES ($1) RETURNING id",
&[&description],
)?;

let id: i64 = row.get(0);
Ok(id)
}

fn complete_todo(client: &mut Client, id: i64) -> Result<bool> {
let rows_affected = client.execute("UPDATE todos SET done = TRUE WHERE id = $1", &[&id])?;

Ok(rows_affected > 0)
}

fn list_todos(client: &mut Client) -> Result<()> {
let rows = client.query("SELECT id, description, done FROM todos ORDER BY id", &[])?;

for rec in rows {
let id: i64 = rec.get("id");
let description: String = rec.get("description");
let done: bool = rec.get("done");
println!(
"- [{}] {}: {}",
if done { "x" } else { " " },
id,
&description,
);
}

Ok(())
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn test_main() -> Result<()> {
main()
}
}
12 changes: 12 additions & 0 deletions examples/sqlx_embedded/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
edition.workspace = true
name = "sqlx_embedded"
publish = false
license.workspace = true
version.workspace = true

[dependencies]
anyhow = { workspace = true }
postgresql_embedded = { path = "../../postgresql_embedded" }
sqlx = { version = "0.7", no-default-features = true, features = ["postgres", "runtime-tokio-rustls"] }
tokio = { workspace = true }
2 changes: 2 additions & 0 deletions examples/sqlx_embedded/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
This example is taken from [sqlx/example/todos](https://github.com/launchbadge/sqlx/tree/main/examples/postgres/todos)
and modified to work with an embedded database.
96 changes: 96 additions & 0 deletions examples/sqlx_embedded/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use anyhow::Result;
use postgresql_embedded::PostgreSQL;
use sqlx::postgres::PgPool;
use sqlx::Row;

#[tokio::main]
async fn main() -> Result<()> {
let mut postgresql = PostgreSQL::default();
postgresql.setup().await?;
postgresql.start().await?;

let database_name = "test";
postgresql.create_database(database_name).await?;
let settings = postgresql.settings();
let database_url = settings.url(database_name);

let pool = PgPool::connect(database_url.as_str()).await?;

println!("Creating table 'todos'");
create_table_todo(&pool).await?;

let description = "Implement embedded database with sqlx";
println!("Adding new todo with description '{description}'");
let todo_id = add_todo(&pool, description).await?;
println!("Added new todo with id {todo_id}");

println!("Marking todo {todo_id} as done");
if complete_todo(&pool, todo_id).await? {
println!("Todo {todo_id} is marked as done");
} else {
println!("Invalid id {todo_id}");
}

println!("Printing list of all todos");
list_todos(&pool).await?;

Ok(())
}

async fn create_table_todo(pool: &PgPool) -> Result<()> {
sqlx::query(
"CREATE TABLE IF NOT EXISTS todos(id BIGSERIAL PRIMARY KEY, description TEXT NOT NULL, done BOOLEAN NOT NULL DEFAULT FALSE);"
).execute(pool).await?;

Ok(())
}

async fn add_todo(pool: &PgPool, description: &str) -> Result<i64> {
let rec = sqlx::query("INSERT INTO todos (description) VALUES ($1) RETURNING id")
.bind(description)
.fetch_one(pool)
.await?;

let id: i64 = rec.get("id");
Ok(id)
}

async fn complete_todo(pool: &PgPool, id: i64) -> Result<bool> {
let rows_affected = sqlx::query("UPDATE todos SET done = TRUE WHERE id = $1")
.bind(id)
.execute(pool)
.await?
.rows_affected();

Ok(rows_affected > 0)
}

async fn list_todos(pool: &PgPool) -> Result<()> {
let recs = sqlx::query("SELECT id, description, done FROM todos ORDER BY id")
.fetch_all(pool)
.await?;

for rec in recs {
let id: i64 = rec.get("id");
let description: String = rec.get("description");
let done: bool = rec.get("done");
println!(
"- [{}] {}: {}",
if done { "x" } else { " " },
id,
&description,
);
}

Ok(())
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn test_main() -> Result<()> {
main()
}
}
3 changes: 2 additions & 1 deletion postgresql_archive/src/archive.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Manage PostgreSQL archive
#![allow(dead_code)]

use crate::error::Error::{AssetHashNotFound, AssetNotFound, ReleaseNotFound, Unexpected};
use crate::error::Result;
use crate::github::{Asset, Release};
Expand Down Expand Up @@ -266,7 +267,7 @@ pub async fn extract(bytes: &Bytes, out_dir: &Path) -> Result<()> {
None => {
return Err(Unexpected(
"Failed to get file header path prefix".to_string(),
))
));
}
};
let stripped_entry_header_path = entry_header_path.strip_prefix(prefix)?.to_path_buf();
Expand Down

0 comments on commit 5023bf6

Please sign in to comment.