sqlx 1:n dependencies

This commit is contained in:
Peter Schiwy 2024-06-03 01:53:23 +02:00
parent bab592edf1
commit 6e6918e8ee
11 changed files with 114 additions and 59 deletions

View File

@ -1,5 +1,5 @@
-- Add up migration script here -- Add up migration script here
CREATE TABLE typen ( CREATE TABLE typen (
id SERIAL PRIMARY KEY, typ_id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL name VARCHAR NOT NULL
); );

View File

@ -1,5 +1,5 @@
-- Add up migration script here -- Add up migration script here
CREATE TABLE hersteller ( CREATE TABLE hersteller (
id SERIAL PRIMARY KEY, hersteller_id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL name VARCHAR NOT NULL
); );

View File

@ -1,9 +1,9 @@
-- Add up migration script here -- Add up migration script here
CREATE TABLE modelle ( CREATE TABLE modelle (
id SERIAL PRIMARY KEY, modell_id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL, name VARCHAR NOT NULL,
typ_id SERIAL, typ_id SERIAL,
hersteller_id SERIAL, hersteller_id SERIAL,
CONSTRAINT fk_typ FOREIGN KEY(typ_id) REFERENCES typen(id), CONSTRAINT fk_typ FOREIGN KEY(typ_id) REFERENCES typen(typ_id),
CONSTRAINT fk_hersteller FOREIGN KEY (hersteller_id) REFERENCES hersteller(id) CONSTRAINT fk_hersteller FOREIGN KEY (hersteller_id) REFERENCES hersteller(hersteller_id)
) )

View File

@ -43,6 +43,8 @@ async fn main() -> Result<()> {
.data(db_pool) .data(db_pool)
.finish(); .finish();
// println!("{}", &schema.sdl());
let app = Router::new() let app = Router::new()
.route("/ping", get(ping)) .route("/ping", get(ping))
.route("/", get(graphiql).post_service(GraphQL::new(schema))); .route("/", get(graphiql).post_service(GraphQL::new(schema)));

View File

@ -3,10 +3,10 @@ use async_graphql::SimpleObject;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sqlx::{FromRow, PgPool}; use sqlx::{FromRow, PgPool};
#[derive(SimpleObject, FromRow, Deserialize, Serialize)] #[derive(SimpleObject, Debug, FromRow, Deserialize, Serialize, sqlx::Type)]
pub struct Hersteller { pub struct Hersteller {
/// Die Datenbank-ID /// Die Datenbank-ID
pub id: i32, pub hersteller_id: i32,
/// Der Name eines Herstellers /// Der Name eines Herstellers
name: String, name: String,
@ -15,28 +15,32 @@ pub struct Hersteller {
impl Hersteller { impl Hersteller {
pub async fn create(pool: &PgPool, name: &str) -> Result<Hersteller> { pub async fn create(pool: &PgPool, name: &str) -> Result<Hersteller> {
let row = sqlx::query!( let row = sqlx::query!(
"INSERT INTO hersteller(name) VALUES ($1) RETURNING id", "INSERT INTO hersteller(name) VALUES ($1) RETURNING hersteller_id",
name name
) )
.fetch_one(pool) .fetch_one(pool)
.await?; .await?;
Ok(Hersteller { Ok(Hersteller {
id: row.id, hersteller_id: row.hersteller_id,
name: name.to_string(), name: name.to_string(),
}) })
} }
pub async fn read_one(pool: &PgPool, id: &i32) -> Result<Hersteller> { pub async fn read_one(pool: &PgPool, id: &i32) -> Result<Hersteller> {
let row = sqlx::query_as!(Hersteller, "SELECT * FROM hersteller WHERE id = $1", id) let row = sqlx::query_as!(
.fetch_one(pool) Hersteller,
.await?; "SELECT * FROM hersteller WHERE hersteller_id = $1",
id
)
.fetch_one(pool)
.await?;
Ok(row) Ok(row)
} }
pub async fn read_all(pool: &PgPool) -> Result<Vec<Hersteller>> { pub async fn read_all(pool: &PgPool) -> Result<Vec<Hersteller>> {
let rows = sqlx::query_as!(Hersteller, "SELECT id, name FROM hersteller") let rows = sqlx::query_as!(Hersteller, "SELECT hersteller_id, name FROM hersteller")
.fetch_all(pool) .fetch_all(pool)
.await?; .await?;
@ -44,9 +48,13 @@ impl Hersteller {
} }
pub async fn update(pool: &PgPool, id: &i32, name: &str) -> Result<Hersteller> { pub async fn update(pool: &PgPool, id: &i32, name: &str) -> Result<Hersteller> {
sqlx::query!("UPDATE hersteller SET name=$1 WHERE id = $2", name, id) sqlx::query!(
.execute(pool) "UPDATE hersteller SET name=$1 WHERE hersteller_id = $2",
.await?; name,
id
)
.execute(pool)
.await?;
let t = Hersteller::read_one(pool, id).await?; let t = Hersteller::read_one(pool, id).await?;
@ -54,7 +62,7 @@ impl Hersteller {
} }
pub async fn delete(pool: &PgPool, id: &i32) -> Result<()> { pub async fn delete(pool: &PgPool, id: &i32) -> Result<()> {
sqlx::query!("DELETE FROM hersteller WHERE id = $1", id) sqlx::query!("DELETE FROM hersteller WHERE hersteller_id = $1", id)
.execute(pool) .execute(pool)
.await?; .await?;

View File

@ -1,3 +1,4 @@
pub mod hersteller; pub mod hersteller;
pub mod modell; pub mod modell;
pub mod modell_temp;
pub mod typ; pub mod typ;

View File

@ -6,7 +6,7 @@ use sqlx::{FromRow, PgPool};
#[derive(SimpleObject, FromRow, Deserialize, Serialize)] #[derive(SimpleObject, FromRow, Deserialize, Serialize)]
pub struct Modell { pub struct Modell {
/// Die Datenbank-ID /// Die Datenbank-ID
pub id: i32, pub modell_id: i32,
/// Der Typ /// Der Typ
typ_id: i32, typ_id: i32,
@ -14,10 +14,7 @@ pub struct Modell {
/// Der Hersteller /// Der Hersteller
hersteller_id: i32, hersteller_id: i32,
/** /// Der Name eines Modells
* Der Name eines Modells
* Das ist ein Zusatz
*/
name: String, name: String,
} }
@ -29,7 +26,7 @@ impl Modell {
name: &str, name: &str,
) -> Result<Modell> { ) -> Result<Modell> {
let row = sqlx::query!( let row = sqlx::query!(
"INSERT INTO modelle(typ_id, hersteller_id, name) VALUES ($1, $2, $3) RETURNING id", "INSERT INTO modelle(typ_id, hersteller_id, name) VALUES ($1, $2, $3) RETURNING modell_id",
typ_id, typ_id,
hersteller_id, hersteller_id,
name name
@ -38,7 +35,7 @@ impl Modell {
.await?; .await?;
Ok(Modell { Ok(Modell {
id: row.id, modell_id: row.modell_id,
typ_id, typ_id,
hersteller_id, hersteller_id,
name: name.to_string(), name: name.to_string(),
@ -46,7 +43,7 @@ impl Modell {
} }
pub async fn read_one(pool: &PgPool, id: &i32) -> Result<Modell> { pub async fn read_one(pool: &PgPool, id: &i32) -> Result<Modell> {
let row = sqlx::query_as!(Modell, "SELECT * FROM modelle WHERE id = $1", id) let row = sqlx::query_as!(Modell, "SELECT * FROM modelle WHERE modell_id = $1", id)
.fetch_one(pool) .fetch_one(pool)
.await?; .await?;
@ -56,7 +53,7 @@ impl Modell {
pub async fn read_all(pool: &PgPool) -> Result<Vec<Modell>> { pub async fn read_all(pool: &PgPool) -> Result<Vec<Modell>> {
let rows = sqlx::query_as!( let rows = sqlx::query_as!(
Modell, Modell,
"SELECT id, name, hersteller_id, typ_id FROM modelle" "SELECT modell_id, name, hersteller_id, typ_id FROM modelle"
) )
.fetch_all(pool) .fetch_all(pool)
.await?; .await?;
@ -64,28 +61,8 @@ impl Modell {
Ok(rows) Ok(rows)
} }
pub async fn read_by_typ(pool: &PgPool, typ_id: &i32) -> Result<Vec<Modell>> {
let row = sqlx::query_as!(Modell, "SELECT * FROM modelle WHERE typ_id = $1", typ_id)
.fetch_all(pool)
.await?;
Ok(row)
}
pub async fn read_by_hersteller(pool: &PgPool, hersteller_id: &i32) -> Result<Vec<Modell>> {
let row = sqlx::query_as!(
Modell,
"SELECT * FROM modelle WHERE hersteller_id = $1",
hersteller_id
)
.fetch_all(pool)
.await?;
Ok(row)
}
pub async fn update(pool: &PgPool, id: &i32, name: &str) -> Result<Modell> { pub async fn update(pool: &PgPool, id: &i32, name: &str) -> Result<Modell> {
sqlx::query!("UPDATE modelle SET name=$1 WHERE id = $2", name, id) sqlx::query!("UPDATE modelle SET name=$1 WHERE modell_id = $2", name, id)
.execute(pool) .execute(pool)
.await?; .await?;
@ -95,7 +72,7 @@ impl Modell {
} }
pub async fn delete(pool: &PgPool, id: &i32) -> Result<()> { pub async fn delete(pool: &PgPool, id: &i32) -> Result<()> {
sqlx::query!("DELETE FROM modelle WHERE id = $1", id) sqlx::query!("DELETE FROM modelle WHERE modell_id = $1", id)
.execute(pool) .execute(pool)
.await?; .await?;

44
src/models/modell_temp.rs Normal file
View File

@ -0,0 +1,44 @@
use anyhow::Result;
use async_graphql::SimpleObject;
use serde::{Deserialize, Serialize};
use sqlx::{FromRow, PgPool};
use super::{hersteller::Hersteller, typ::Typ};
#[derive(SimpleObject, Debug, FromRow, Deserialize, Serialize)]
pub struct ModellTemp {
/// Die Datenbank-ID
pub modell_id: i32,
/// Der Typ
pub typ: Typ,
/// Der Hersteller
pub hersteller: Hersteller,
/// Der Name eines Modells
pub name: String,
}
impl ModellTemp {
pub async fn read_one(pool: &PgPool, id: &i32) -> Result<ModellTemp> {
let row = sqlx::query_as!(
ModellTemp,
r#"
select
m.modell_id, m.name,
(t.typ_id, t.name) as "typ!: Typ",
(h.hersteller_id, h.name) as "hersteller!: Hersteller"
from modelle as m
join typen as t using(typ_id)
join hersteller as h using(hersteller_id)
where m.modell_id = $1;
"#,
id
)
.fetch_one(pool)
.await?;
Ok(row)
}
}

View File

@ -1,31 +1,30 @@
use anyhow::Result; use anyhow::Result;
use async_graphql::SimpleObject; use async_graphql::SimpleObject;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sqlx::{FromRow, PgPool}; use sqlx::{FromRow, PgPool, Type};
#[derive(SimpleObject, FromRow, Deserialize, Serialize)] #[derive(SimpleObject, Debug, FromRow, Deserialize, Serialize, Type)]
pub struct Typ { pub struct Typ {
/// Die Datenbank-ID pub typ_id: i32,
pub id: i32,
/// Der Name eines Typs /// Der Name eines Typs
name: String, pub name: String,
} }
impl Typ { impl Typ {
pub async fn create(pool: &PgPool, name: &str) -> Result<Typ> { pub async fn create(pool: &PgPool, name: &str) -> Result<Typ> {
let row = sqlx::query!("INSERT INTO typen(name) VALUES ($1) RETURNING id", name) let row = sqlx::query!("INSERT INTO typen(name) VALUES ($1) RETURNING typ_id", name)
.fetch_one(pool) .fetch_one(pool)
.await?; .await?;
Ok(Typ { Ok(Typ {
id: row.id, typ_id: row.typ_id,
name: name.to_string(), name: name.to_string(),
}) })
} }
pub async fn read_one(pool: &PgPool, id: &i32) -> Result<Typ> { pub async fn read_one(pool: &PgPool, id: &i32) -> Result<Typ> {
let row = sqlx::query_as!(Typ, "SELECT * FROM typen WHERE id = $1", id) let row = sqlx::query_as!(Typ, "SELECT * FROM typen WHERE typ_id = $1", id)
.fetch_one(pool) .fetch_one(pool)
.await?; .await?;
@ -33,7 +32,7 @@ impl Typ {
} }
pub async fn read_all(pool: &PgPool) -> Result<Vec<Typ>> { pub async fn read_all(pool: &PgPool) -> Result<Vec<Typ>> {
let rows = sqlx::query_as!(Typ, "SELECT id, name FROM typen") let rows = sqlx::query_as!(Typ, "SELECT typ_id, name FROM typen")
.fetch_all(pool) .fetch_all(pool)
.await?; .await?;
@ -41,7 +40,7 @@ impl Typ {
} }
pub async fn update(pool: &PgPool, id: &i32, name: &str) -> Result<Typ> { pub async fn update(pool: &PgPool, id: &i32, name: &str) -> Result<Typ> {
sqlx::query!("UPDATE typen SET name=$1 WHERE id = $2", name, id) sqlx::query!("UPDATE typen SET name=$1 WHERE typ_id = $2", name, id)
.execute(pool) .execute(pool)
.await?; .await?;
@ -51,7 +50,7 @@ impl Typ {
} }
pub async fn delete(pool: &PgPool, id: &i32) -> Result<()> { pub async fn delete(pool: &PgPool, id: &i32) -> Result<()> {
sqlx::query!("DELETE FROM typen WHERE id = $1", id) sqlx::query!("DELETE FROM typen WHERE typ_id = $1", id)
.execute(pool) .execute(pool)
.await?; .await?;

View File

@ -1,5 +1,6 @@
pub mod hersteller; pub mod hersteller;
pub mod modell; pub mod modell;
pub mod modell_temp;
pub mod typ; pub mod typ;
use async_graphql::MergedObject; use async_graphql::MergedObject;
@ -8,5 +9,6 @@ use async_graphql::MergedObject;
pub struct Query( pub struct Query(
typ::TypQuery, typ::TypQuery,
modell::ModellQuery, modell::ModellQuery,
modell_temp::ModellTempQuery,
hersteller::HerstellerQuery, hersteller::HerstellerQuery,
); );

View File

@ -0,0 +1,22 @@
use async_graphql::{Context, FieldResult, Object};
use sqlx::postgres::PgPool;
use crate::models::modell_temp::ModellTemp;
#[derive(Default)]
pub struct ModellTempQuery {}
#[Object(extends)]
impl ModellTempQuery {
// async fn modelle<'a>(&self, ctx: &'a Context<'_>) -> FieldResult<Vec<ModellTemp>> {
// let pool = ctx.data::<PgPool>()?;
// let rows = ModellTemp::read_all(pool).await?;
// Ok(rows)
// }
async fn modell_temp<'a>(&self, ctx: &'a Context<'_>, id: i32) -> FieldResult<ModellTemp> {
let pool = ctx.data::<PgPool>()?;
let row = ModellTemp::read_one(pool, &id).await?;
Ok(row)
}
}