let ai cleanup repositories and generated missing functions

This commit is contained in:
2025-11-06 21:22:59 +01:00
parent e5b9bb1b69
commit 734560da9a
13 changed files with 2168 additions and 228 deletions

View File

@@ -0,0 +1,263 @@
use sqlx::{sqlite::SqlitePool, FromRow, Row};
use crate::models::{db_models::exercise_db::ExerciseDb, exercise::Exercise};
pub struct ExerciseRepository<'a> {
pub pool: &'a SqlitePool,
}
impl<'a> ExerciseRepository<'a> {
pub fn new(pool: &'a SqlitePool) -> Self {
Self { pool }
}
pub async fn get_exercises_by_node_id(&self, node_id: u32) -> Result<Vec<Exercise>, String> {
let exercise_rows = sqlx::query("SELECT * FROM exercise WHERE nodeId = ?")
.bind(node_id)
.fetch_all(self.pool)
.await
.map_err(|e| format!("ERROR: Failed to query Exercise db: {}", e))?;
let exercises = self.parse_exercise_rows(exercise_rows)?;
Ok(exercises)
}
pub async fn get_exercises_by_path_id(&self, path_id: &str) -> Result<Vec<Exercise>, String> {
let exercise_rows = sqlx::query("SELECT * FROM exercise WHERE pathId = ?")
.bind(path_id)
.fetch_all(self.pool)
.await
.map_err(|e| format!("ERROR: Failed to query Exercise db: {}", e))?;
if exercise_rows.is_empty() {
return Err(format!(
"ERROR: No Exercise for path with ID {} found",
path_id
));
}
let exercises = self.parse_exercise_rows(exercise_rows)?;
Ok(exercises)
}
pub async fn get_exercise_by_id(&self, exercise_id: u32) -> Result<Exercise, String> {
let exercise_row = sqlx::query("SELECT * FROM exercise WHERE id = ?")
.bind(exercise_id)
.fetch_optional(self.pool)
.await
.map_err(|e| format!("ERROR: Failed to query Exercise db: {}", e))?;
let exercise_row = exercise_row
.ok_or_else(|| format!("ERROR: No Exercise with ID {} found", exercise_id))?;
let exercise_db = ExerciseDb::from_row(&exercise_row)
.map_err(|e| format!("ERROR: Could not parse Exercise struct: {}", e))?;
let exercise = self.convert_exercise_db_to_model(exercise_db);
Ok(exercise)
}
pub async fn get_exercises_by_type(
&self,
ex_type: &str,
path_id: Option<&str>,
) -> Result<Vec<Exercise>, String> {
let exercise_rows = if let Some(path_id) = path_id {
sqlx::query("SELECT * FROM exercise WHERE ex_type = ? AND pathId = ?")
.bind(ex_type)
.bind(path_id)
.fetch_all(self.pool)
.await
.map_err(|e| format!("ERROR: Failed to query Exercise db: {}", e))?
} else {
sqlx::query("SELECT * FROM exercise WHERE ex_type = ?")
.bind(ex_type)
.fetch_all(self.pool)
.await
.map_err(|e| format!("ERROR: Failed to query Exercise db: {}", e))?
};
let exercises = self.parse_exercise_rows(exercise_rows)?;
Ok(exercises)
}
fn parse_exercise_rows(
&self,
exercise_rows: Vec<sqlx::sqlite::SqliteRow>,
) -> Result<Vec<Exercise>, String> {
exercise_rows
.iter()
.map(|row| {
let exercise_db = ExerciseDb::from_row(row)
.map_err(|e| format!("ERROR: Could not parse Exercise struct: {}", e))?;
Ok(self.convert_exercise_db_to_model(exercise_db))
})
.collect()
}
fn convert_exercise_db_to_model(&self, exercise_db: ExerciseDb) -> Exercise {
Exercise {
id: exercise_db.id as u32,
ex_type: exercise_db.ex_type,
content: exercise_db.content,
node_id: exercise_db.node_id as u32,
}
}
pub async fn save_exercise(&self, exercise: &Exercise) -> Result<u32, String> {
let query = "INSERT INTO exercise (ex_type, content, nodeId, pathId) VALUES (?, ?, ?, (SELECT pathId FROM node WHERE id = ?)) RETURNING id";
let row = sqlx::query(query)
.bind(&exercise.ex_type)
.bind(&exercise.content)
.bind(exercise.node_id)
.bind(exercise.node_id)
.fetch_one(self.pool)
.await
.map_err(|e| format!("ERROR: Failed to save exercise: {}", e))?;
let exercise_id: i64 = row
.try_get("id")
.map_err(|e| format!("ERROR: Failed to get exercise ID: {}", e))?;
Ok(exercise_id as u32)
}
pub async fn save_multiple_exercises(
&self,
exercises: &[Exercise],
) -> Result<Vec<u32>, String> {
if exercises.is_empty() {
return Ok(Vec::new());
}
let mut transaction = self
.pool
.begin()
.await
.map_err(|e| format!("ERROR: Failed to begin transaction: {}", e))?;
let mut exercise_ids = Vec::new();
for exercise in exercises {
let row = sqlx::query("INSERT INTO exercise (ex_type, content, nodeId, pathId) VALUES (?, ?, ?, (SELECT pathId FROM node WHERE id = ?)) RETURNING id")
.bind(&exercise.ex_type)
.bind(&exercise.content)
.bind(exercise.node_id)
.bind(exercise.node_id)
.fetch_one(&mut *transaction)
.await
.map_err(|e| format!("ERROR: Failed to save exercise in transaction: {}", e))?;
let exercise_id: i64 = row
.try_get("id")
.map_err(|e| format!("ERROR: Failed to get exercise ID: {}", e))?;
exercise_ids.push(exercise_id as u32);
}
transaction
.commit()
.await
.map_err(|e| format!("ERROR: Failed to commit exercise transaction: {}", e))?;
Ok(exercise_ids)
}
pub async fn update_exercise(&self, exercise: &Exercise) -> Result<(), String> {
let query = "UPDATE exercise SET ex_type = ?, content = ? WHERE id = ?";
let result = sqlx::query(query)
.bind(&exercise.ex_type)
.bind(&exercise.content)
.bind(exercise.id)
.execute(self.pool)
.await
.map_err(|e| format!("ERROR: Failed to update exercise: {}", e))?;
if result.rows_affected() == 0 {
return Err(format!("ERROR: No exercise found with ID {}", exercise.id));
}
Ok(())
}
pub async fn delete_exercise(&self, exercise_id: u32) -> Result<(), String> {
let query = "DELETE FROM exercise WHERE id = ?";
let result = sqlx::query(query)
.bind(exercise_id)
.execute(self.pool)
.await
.map_err(|e| format!("ERROR: Failed to delete exercise: {}", e))?;
if result.rows_affected() == 0 {
return Err(format!("ERROR: No exercise found with ID {}", exercise_id));
}
Ok(())
}
pub async fn delete_exercises_by_node_id(&self, node_id: u32) -> Result<u64, String> {
let query = "DELETE FROM exercise WHERE nodeId = ?";
let result = sqlx::query(query)
.bind(node_id)
.execute(self.pool)
.await
.map_err(|e| format!("ERROR: Failed to delete exercises by node ID: {}", e))?;
Ok(result.rows_affected())
}
pub async fn delete_exercises_by_path_id(&self, path_id: &str) -> Result<u64, String> {
let query = "DELETE FROM exercise WHERE pathId = ?";
let result = sqlx::query(query)
.bind(path_id)
.execute(self.pool)
.await
.map_err(|e| format!("ERROR: Failed to delete exercises by path ID: {}", e))?;
Ok(result.rows_affected())
}
pub async fn update_exercises_for_node(
&self,
node_id: u32,
exercises: &[Exercise],
) -> Result<(), String> {
let mut transaction = self
.pool
.begin()
.await
.map_err(|e| format!("ERROR: Failed to begin transaction: {}", e))?;
// Delete existing exercises for the node
sqlx::query("DELETE FROM exercise WHERE nodeId = ?")
.bind(node_id)
.execute(&mut *transaction)
.await
.map_err(|e| format!("ERROR: Failed to delete existing exercises: {}", e))?;
// Insert new exercises
for exercise in exercises {
sqlx::query("INSERT INTO exercise (ex_type, content, nodeId, pathId) VALUES (?, ?, ?, (SELECT pathId FROM node WHERE id = ?))")
.bind(&exercise.ex_type)
.bind(&exercise.content)
.bind(node_id)
.bind(node_id)
.execute(&mut *transaction)
.await
.map_err(|e| format!("ERROR: Failed to insert exercise in transaction: {}", e))?;
}
transaction
.commit()
.await
.map_err(|e| format!("ERROR: Failed to commit exercise update transaction: {}", e))?;
Ok(())
}
}