Compare commits

..
4 Commits
Author SHA1 Message Date
Florian THIERRY c3806f49ba WIP4 2026-07-19 21:43:29 +02:00
Florian THIERRY 59b7164007 WIP3 2026-07-19 21:30:12 +02:00
Florian THIERRY 35ef389bb8 WIP2 2026-07-19 21:14:15 +02:00
Florian THIERRY 360df2c5f4 WIP 2026-07-19 20:47:25 +02:00
2 changed files with 115 additions and 1 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ pub struct LibraryItemEntity {
pub id: Uuid, pub id: Uuid,
pub name: String, pub name: String,
pub r#type: i8, pub r#type: i8,
pub parent_folder_id: Option<Uuid> pub parent_folder_id: Option<Box<LibraryItemEntity>>
} }
impl LibraryItemEntity { impl LibraryItemEntity {
@@ -4,6 +4,13 @@ use rusqlite::fallible_iterator::FallibleIterator;
use uuid::Uuid; use uuid::Uuid;
use crate::video::model::LibraryItemEntity; use crate::video::model::LibraryItemEntity;
struct LibraryItemRawEntity {
pub id: Uuid,
pub name: String,
pub r#type: i8,
pub parent_item_id: Option<Uuid>,
}
#[derive(Clone)] #[derive(Clone)]
pub struct LibraryItemSqliteRepository { pub struct LibraryItemSqliteRepository {
pub database_connection: Arc<Mutex<Connection>>, pub database_connection: Arc<Mutex<Connection>>,
@@ -85,4 +92,111 @@ impl LibraryItemSqliteRepository {
prepared_statement.execute(rusqlite::params_from_iter(params))?; prepared_statement.execute(rusqlite::params_from_iter(params))?;
Ok(()) Ok(())
} }
pub fn get_by_id_with_all_hierarchy(&self, library_item_id: &Uuid) -> Result<Option<LibraryItemEntity>, Error> {
let database_connection = self.get_connection();
/*
Given a LibraryItem item_1:
LibraryItemEntity {
id: <id1>,
name: "item_1",
type: 0,
parent_item_id: <id2>
}
Its parent item is item_2:
LibraryItemEntity {
id: <id2>,
name: "item_2",
type: 1,
parent_item_id: <id3>
}
item_2 has a parent which is item_3:
LibraryItemEntity {
id: <id3>,
name: "item_3",
type: 0,
parent_item_id: NULL
}
TODO: Write a SQL query to retrieve all LibraryItemEntity objects. It should filter on id with a parameter.
This query should return something like:
| id | name | type | parent_item_id |
| ----- | -------- | ---- | -------------- |
| <id1> | 'item_1' | 0 | <id2> |
| <id2> | 'item_2' | 1 | <id3> |
| <id3> | 'item_3' | 1 | NULL |
Take example on the following query and adapt it.
*/
let mut prepared_statement = database_connection.prepare(
"WITH RECURSIVE library_item_hierarchy AS (
-- Base case: start with the requested item
SELECT id, name, type, parent_folder_id
FROM library_item
WHERE id = ?1
UNION ALL
-- Recursive case: get all ancestors
SELECT li.id, li.name, li.type, li.parent_folder_id
FROM library_item li
INNER JOIN library_item_hierarchy lh ON li.id = lh.parent_folder_id
)
SELECT id, name, type, parent_folder_id
FROM library_item_hierarchy
ORDER BY id;"
)?;
let mut rows = prepared_statement.query([library_item_id.to_string()])?;
let raw_data = rows.map(Self::map_to_raw_entity).collect::<Vec<LibraryItemRawEntity>>()?;
// Build a map of id to LibraryItemEntity for quick lookup
let mut entity_map: std::collections::HashMap<Uuid, LibraryItemEntity> = std::collections::HashMap::new();
// First pass: create all entities without parent relationships
for raw_entity in &raw_data {
let entity = LibraryItemEntity {
id: raw_entity.id.clone(),
name: raw_entity.name.clone(),
r#type: raw_entity.r#type,
parent_folder_id: None, // Will be set in second pass
};
entity_map.insert(raw_entity.id.clone(), entity);
}
// Second pass: set up parent-child relationships
for raw_entity in &raw_data {
if let Some(parent_id) = &raw_entity.parent_item_id {
if let Some(child_entity) = entity_map.get_mut(&raw_entity.id) {
if let Some(parent_entity) = entity_map.get(parent_id) {
child_entity.parent_folder_id = Some(Box::new(parent_entity.clone()));
}
}
}
}
// Find the requested item and return it with its full hierarchy
if let Some(entity) = entity_map.get(library_item_id) {
Ok(Some(entity.clone()))
} else {
Ok(None)
}
}
fn map_to_raw_entity(row: &Row) -> Result<LibraryItemRawEntity, Error> {
let id_text: String = row.get(0)?;
let type_as_number: i8 = row.get(2)?;
let parent_item_id_text: Option<String> = row.get(3)?;
let raw_entity = LibraryItemRawEntity {
id: Uuid::parse_str(&id_text).unwrap(),
name: row.get(1)?,
r#type: type_as_number,
parent_item_id: parent_item_id_text.map(|id| Uuid::parse_str(id.as_str()).unwrap())
};
Ok(raw_entity)
}
} }