added database crate, "settings" with migrations and queries, running migrations on web startup
This commit is contained in:
parent
f60eb616d3
commit
9c2b43ec3c
16 changed files with 357 additions and 1 deletions
45
crates/database/src/error.rs
Normal file
45
crates/database/src/error.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
// error
|
||||
#[derive(thiserror::Error)]
|
||||
// the rest
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
#[error("Unique constraint on primary key")]
|
||||
UniqueConstraintPrimaryKey,
|
||||
|
||||
#[error("Unique constraint on key {0}")]
|
||||
UniqueConstraint(String),
|
||||
|
||||
#[error("{0}")]
|
||||
Database(#[from] sqlx::Error),
|
||||
}
|
||||
|
||||
fn parse_unique_constraint(msg: &str) -> Option<String> {
|
||||
// Format will be "table.column"
|
||||
let mut constraint = msg.strip_prefix("UNIQUE constraint failed: ")?.split('.');
|
||||
|
||||
// Extract "column" (which is the second value)
|
||||
let _table = constraint.next()?;
|
||||
let column = constraint.next()?;
|
||||
|
||||
Some(column.to_string())
|
||||
}
|
||||
|
||||
pub fn handle_error(e: sqlx::Error) -> Error {
|
||||
match e.as_database_error() {
|
||||
Some(database_error) => match database_error.code() {
|
||||
// List of all codes: https://www.sqlite.org/rescode.html
|
||||
Some(code) => match code.as_ref() {
|
||||
"1555" => Error::UniqueConstraintPrimaryKey,
|
||||
|
||||
// Attempt to extract unique constraint column
|
||||
"2067" => match parse_unique_constraint(database_error.message()) {
|
||||
Some(column) => Error::UniqueConstraint(column),
|
||||
None => Error::Database(e),
|
||||
},
|
||||
_ => Error::Database(e),
|
||||
},
|
||||
None => Error::Database(e),
|
||||
},
|
||||
None => Error::Database(e),
|
||||
}
|
||||
}
|
||||
11
crates/database/src/lib.rs
Normal file
11
crates/database/src/lib.rs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
pub(crate) mod error;
|
||||
mod tables;
|
||||
|
||||
/// Re-export sqlx
|
||||
pub use sqlx;
|
||||
|
||||
/// Error
|
||||
pub use self::error::Error;
|
||||
|
||||
/// Export tables
|
||||
pub use self::tables::*;
|
||||
3
crates/database/src/tables/mod.rs
Normal file
3
crates/database/src/tables/mod.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
mod settings;
|
||||
|
||||
pub use settings::Settings;
|
||||
57
crates/database/src/tables/settings.rs
Normal file
57
crates/database/src/tables/settings.rs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
use crate::error::{handle_error, Error};
|
||||
use sqlx::sqlite::SqliteQueryResult;
|
||||
use sqlx::types::chrono::{DateTime, Utc};
|
||||
use sqlx::{FromRow, SqliteExecutor};
|
||||
|
||||
#[derive(FromRow)]
|
||||
pub struct Settings {
|
||||
pub id: i64,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub business_name: Option<String>,
|
||||
pub business_logo: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
pub async fn init(conn: impl SqliteExecutor<'_>) -> Result<Option<()>, Error> {
|
||||
let query: SqliteQueryResult = sqlx::query_file!("queries/settings/init.sql")
|
||||
.execute(conn)
|
||||
.await
|
||||
.map_err(handle_error)?;
|
||||
|
||||
Ok((query.rows_affected() == 1).then_some(()))
|
||||
}
|
||||
|
||||
pub async fn get(conn: impl SqliteExecutor<'_>) -> Result<Self, Error> {
|
||||
sqlx::query_file_as!(Self, "queries/settings/get.sql")
|
||||
.fetch_one(conn)
|
||||
.await
|
||||
.map_err(handle_error)
|
||||
}
|
||||
|
||||
pub async fn set_business_name(
|
||||
conn: impl SqliteExecutor<'_>,
|
||||
value: Option<&str>,
|
||||
) -> Result<Option<()>, Error> {
|
||||
let query: SqliteQueryResult =
|
||||
sqlx::query_file!("queries/settings/set_business_name.sql", value)
|
||||
.execute(conn)
|
||||
.await
|
||||
.map_err(handle_error)?;
|
||||
|
||||
Ok((query.rows_affected() == 1).then_some(()))
|
||||
}
|
||||
|
||||
pub async fn set_business_logo(
|
||||
conn: impl SqliteExecutor<'_>,
|
||||
value: Option<&[u8]>,
|
||||
) -> Result<Option<()>, Error> {
|
||||
let query: SqliteQueryResult =
|
||||
sqlx::query_file!("queries/settings/set_business_logo.sql", value)
|
||||
.execute(conn)
|
||||
.await
|
||||
.map_err(handle_error)?;
|
||||
|
||||
Ok((query.rows_affected() == 1).then_some(()))
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue