refactor: clean up db stuff; start comments stuff
This commit is contained in:
parent
f980115d45
commit
fed9c01370
9 changed files with 174 additions and 118 deletions
19
src/db/comment.rs
Normal file
19
src/db/comment.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
use r2d2_sqlite::rusqlite::{self, Row};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Comment {
|
||||
id: i32,
|
||||
plant_id: i32,
|
||||
comment: String,
|
||||
}
|
||||
|
||||
impl Comment {
|
||||
pub fn from_row(row: &Row<'_>) -> Result<Self, rusqlite::Error> {
|
||||
Ok(Self {
|
||||
id: row.get(0)?,
|
||||
plant_id: row.get(1)?,
|
||||
comment: row.get(2)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
47
src/db/mod.rs
Normal file
47
src/db/mod.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
mod comment;
|
||||
mod plant;
|
||||
|
||||
use r2d2_sqlite::{rusqlite, SqliteConnectionManager};
|
||||
|
||||
use std::{error::Error, fmt};
|
||||
|
||||
pub use comment::Comment;
|
||||
pub use plant::{NewPlant, Plant};
|
||||
|
||||
pub type DbPool = r2d2::Pool<SqliteConnectionManager>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DbError {
|
||||
Pool(r2d2::Error),
|
||||
Db(rusqlite::Error),
|
||||
}
|
||||
|
||||
impl fmt::Display for DbError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Pool(_) => write!(f, "failed to acquire connection from pool"),
|
||||
Self::Db(_) => write!(f, "error while accessing the database"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for DbError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
Self::Pool(err) => Some(err),
|
||||
Self::Db(err) => Some(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<r2d2::Error> for DbError {
|
||||
fn from(value: r2d2::Error) -> Self {
|
||||
Self::Pool(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<rusqlite::Error> for DbError {
|
||||
fn from(value: rusqlite::Error) -> Self {
|
||||
Self::Db(value)
|
||||
}
|
||||
}
|
||||
73
src/db/plant.rs
Normal file
73
src/db/plant.rs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
use r2d2_sqlite::rusqlite::{self, Row};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{Comment, DbError, DbPool};
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct Plant {
|
||||
id: i32,
|
||||
name: String,
|
||||
species: String,
|
||||
description: String,
|
||||
}
|
||||
|
||||
impl Plant {
|
||||
pub fn from_row(row: &Row<'_>) -> Result<Self, rusqlite::Error> {
|
||||
Ok(Self {
|
||||
id: row.get(0)?,
|
||||
name: row.get(1)?,
|
||||
species: row.get(2)?,
|
||||
description: row.get(3)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn all(pool: &DbPool) -> Result<Vec<Self>, DbError> {
|
||||
let conn = pool.get()?;
|
||||
|
||||
let mut stmt = conn.prepare("select * from plants")?;
|
||||
let plants: Result<Vec<_>, _> = stmt.query_map((), Self::from_row)?.collect();
|
||||
|
||||
Ok(plants?)
|
||||
}
|
||||
|
||||
pub fn with_id(pool: &DbPool, id: i32) -> Result<Option<Self>, DbError> {
|
||||
let conn = pool.get()?;
|
||||
|
||||
let mut stmt = conn.prepare("select * from plants where id = $1")?;
|
||||
match stmt.query_row((id,), |row| Plant::from_row(row)) {
|
||||
Ok(plant) => Ok(Some(plant)),
|
||||
Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None),
|
||||
Err(err) => Err(DbError::Db(err)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn comments(&self, pool: &DbPool) -> Result<Vec<Comment>, DbError> {
|
||||
let conn = pool.get()?;
|
||||
let mut stmt = conn.prepare("select * from plant_comments where plant_id = $1")?;
|
||||
|
||||
let comments: Result<Vec<_>, _> = stmt.query_map((self.id,), Comment::from_row)?.collect();
|
||||
Ok(comments?)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct NewPlant {
|
||||
name: String,
|
||||
species: String,
|
||||
description: String,
|
||||
}
|
||||
|
||||
impl NewPlant {
|
||||
pub fn insert(self, pool: &DbPool) -> Result<Plant, DbError> {
|
||||
let conn = pool.get()?;
|
||||
|
||||
let mut stmt = conn.prepare(
|
||||
"insert into plants (name, species, description) values ($1, $2, $3) returning *",
|
||||
)?;
|
||||
|
||||
Ok(stmt.query_row(
|
||||
(&self.name, &self.species, &self.description),
|
||||
Plant::from_row,
|
||||
)?)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue