use std::ops::DerefMut; use sqlx::pool::PoolConnection; use sqlx::Sqlite; use crate::db::{DbRelay, DbSchedule}; use crate::errors::DatabaseError; use crate::types::Weekday; pub struct DbJunctionRelaySchedule { pub id: i64, pub weekday: Weekday, pub relay_id: i64, pub schedule_id: i64, } impl DbJunctionRelaySchedule { pub async fn get( conn: &mut PoolConnection<Sqlite>, id: i64, ) -> Result<Option<DbJunctionRelaySchedule>, DatabaseError> { sqlx::query_as!( DbJunctionRelaySchedule, "SELECT * FROM junction_relay_schedule WHERE id = ?", id ) .fetch_optional(conn.deref_mut()) .await .map_err(DatabaseError::from) } pub async fn get_junction_by_relay_and_weekday( conn: &mut PoolConnection<Sqlite>, relay: &DbRelay, weekday: Weekday, ) -> Result<Option<DbJunctionRelaySchedule>, DatabaseError> { sqlx::query_as!( DbJunctionRelaySchedule, "SELECT * FROM junction_relay_schedule WHERE relay_id = ? AND weekday = ?", relay.id, weekday ) .fetch_optional(conn.deref_mut()) .await .map_err(DatabaseError::from) } pub async fn get_schedule( conn: &mut PoolConnection<Sqlite>, relay: &DbRelay, weekday: Weekday, ) -> Result<Option<DbSchedule>, DatabaseError> { sqlx::query_as!( DbSchedule, r#"SELECT schedules.* FROM schedules INNER JOIN junction_relay_schedule ON junction_relay_schedule.schedule_id = schedules.id WHERE junction_relay_schedule.relay_id = ? AND junction_relay_schedule.weekday = ?"#, relay.id, weekday ) .fetch_optional(conn.deref_mut()) .await .map_err(DatabaseError::from) } pub async fn get_schedules( conn: &mut PoolConnection<Sqlite>, relay: &DbRelay, ) -> Result<Vec<DbSchedule>, DatabaseError> { sqlx::query_as!( DbSchedule, r#"SELECT schedules.* FROM schedules INNER JOIN junction_relay_schedule ON junction_relay_schedule.schedule_id = schedules.id WHERE junction_relay_schedule.relay_id = ? ORDER BY junction_relay_schedule.weekday"#, relay.id ) .fetch_all(conn.deref_mut()) .await .map_err(DatabaseError::from) } pub async fn set_schedule( conn: &mut PoolConnection<Sqlite>, relay: &DbRelay, schedule: &DbSchedule, weekday: Weekday, ) -> Result<DbJunctionRelaySchedule, DatabaseError> { match Self::get_junction_by_relay_and_weekday(conn, relay, weekday).await? { None => sqlx::query_as!( DbJunctionRelaySchedule, "INSERT INTO junction_relay_schedule (weekday, relay_id, schedule_id) VALUES (?, ?, ?) RETURNING *", weekday, relay.id, schedule.id ) .fetch_optional(conn.deref_mut()) .await? .ok_or(DatabaseError::InsertGetError), Some(junction) => { sqlx::query!( "UPDATE junction_relay_schedule SET weekday = ?, relay_id = ?, schedule_id= ? WHERE id = ?", weekday, relay.id, schedule.id, junction.id ) .execute(conn.deref_mut()) .await?; Self::get(conn, junction.id) .await? .ok_or(DatabaseError::UpdateGetError) } } } pub async fn set_schedules( conn: &mut PoolConnection<Sqlite>, relay: &DbRelay, schedules: Vec<&DbSchedule>, ) -> Result<(), DatabaseError> { for (weekday, schedule) in schedules.iter().enumerate() { Self::set_schedule(conn, relay, schedule, weekday as Weekday).await?; } Ok(()) } }