gunnhildr/src/db/mod.rs
2024-12-07 12:27:48 +01:00

150 lines
4.6 KiB
Rust

#![allow(unused)]
use log::{info, warn};
use sqlx::{migrate::MigrateDatabase, PgPool, Postgres, Sqlite, SqlitePool};
pub mod models;
mod postgres;
mod sqlite;
/// Utility for interacting with the database
#[derive(Clone)]
pub enum DataBase {
/// Used for Sqlite database
Sqlite(sqlx::Pool<Sqlite>),
/// Used for Postgres database
Postgres(sqlx::Pool<Postgres>),
}
/// Error type for handling DB related errors
pub enum DbError {
/// No such entry found
NotFound,
/// Database related error
SqlxError(sqlx::Error),
}
impl From<sqlx::Error> for DbError {
fn from(value: sqlx::Error) -> Self {
match value {
sqlx::Error::RowNotFound => DbError::NotFound,
_ => DbError::SqlxError(value),
}
}
}
type DbResult<T> = Result<T, DbError>;
impl DataBase {
/// Database backed by SQLite
pub async fn sqlite() -> Self {
// Check if db exists, if not create it.
if !sqlx::Sqlite::database_exists("sqlite:gunnhildr.db")
.await
.expect("failed to connect to db")
{
warn!("No SQLite database found, if this is the first time you are starting Gunnhildr, you can safely ignore this.");
sqlx::Sqlite::create_database("sqlite:gunnhildr.db")
.await
.expect("failed to create SQLite Database");
info!("Created new SQLite Database");
}
let pool = SqlitePool::connect("sqlite:gunnhildr.db").await.unwrap();
// run migrations
sqlx::migrate!("migrations/sqlite")
.run(&pool)
.await
.expect("Failed to apply migration!");
info!("Applied migrations.");
Self::Sqlite(pool)
}
/// Database backed by Postgres
pub async fn postgres(url: &str) -> Self {
// check if database exists and create one if not
if !sqlx::Postgres::database_exists(url)
.await
.expect("failed to connect to db")
{
warn!("No Postgres database found, if this is the first time you are starting Gunnhildr, you can safely ignore this.");
sqlx::Postgres::create_database(url)
.await
.expect("failed to create Postgres Database!");
info!("Created new Postgres Database");
}
let pool = PgPool::connect("url").await.unwrap();
// run migrations
sqlx::migrate!("migrations/postgres")
.run(&pool)
.await
.expect("Failed to apply migration!");
Self::Postgres(pool)
}
/// Tries to fetch a book from the database
pub async fn get_book(&self, id: u32) -> DbResult<models::Book> {
match self {
DataBase::Sqlite(pool) => sqlite::sqlite_book(pool, id).await,
DataBase::Postgres(pool) => todo!(),
}
}
/// Tries to create a book and returns the book's id if successful
pub async fn create_book(
&self,
title: String,
description: String,
author_id: u32,
) -> DbResult<u32> {
match self {
DataBase::Sqlite(pool) => {
sqlite::sqlite_book_create(pool, title, description, author_id).await
}
DataBase::Postgres(pool) => todo!(),
}
}
/// Tries to fetch a chapter from the database
pub async fn get_chapter(&self, id: u32) -> DbResult<models::Chapter> {
match self {
DataBase::Sqlite(pool) => sqlite::sqlite_chapter(pool, id).await,
DataBase::Postgres(pool) => todo!(),
}
}
/// Tries to create a chapter and returns the chapter's id if successfu
pub async fn create_chapter(
&self,
title: String,
text: String,
book_id: u32,
author_id: u32,
) -> DbResult<u32> {
match self {
DataBase::Sqlite(pool) => {
sqlite::sqlite_chapter_create(pool, title, text, book_id, author_id).await
}
DataBase::Postgres(pool) => todo!(),
}
}
/// Tries to fetch a user from the database
pub async fn get_user(&self, id: u32) -> DbResult<models::User> {
match self {
DataBase::Sqlite(pool) => sqlite::sqlite_user(pool, id).await,
DataBase::Postgres(pool) => todo!(),
}
}
/// Tries to create a user and returns the user's id if successful
pub async fn create_user(&self, name: String) -> DbResult<u32> {
match self {
DataBase::Sqlite(pool) => sqlite::sqlite_user_create(pool, name).await,
DataBase::Postgres(pool) => todo!(),
}
}
}