fix(db): fix the issue of order preservation.

-Added CTE (Common Table Expression) to first get ordered items
-Changed result collection from HashMap to Vec to preserve order
-Process rows sequentially while maintaining item order
This commit is contained in:
ryan 2025-03-10 17:39:39 +03:00
parent 47c87159ae
commit 896de305cc

View file

@ -378,43 +378,68 @@ mod db_impl {
log!("Fetching items for URL '{}' (ID: {})", url, url_id); log!("Fetching items for URL '{}' (ID: {})", url, url_id);
let mut stmt = conn.prepare( let mut stmt = conn.prepare(
"SELECT i.id, i.name, i.description, i.wikidata_id, "WITH ordered_items AS (
p.name AS prop_name, ip.value SELECT
FROM items i i.id,
LEFT JOIN item_properties ip ON i.id = ip.item_id i.name,
LEFT JOIN properties p ON ip.property_id = p.id i.description,
WHERE i.url_id = ? i.wikidata_id,
ORDER BY i.item_order ASC", i.item_order
FROM items i
WHERE i.url_id = ?
ORDER BY i.item_order ASC
)
SELECT
oi.id,
oi.name,
oi.description,
oi.wikidata_id,
p.name AS prop_name,
ip.value
FROM ordered_items oi
LEFT JOIN item_properties ip ON oi.id = ip.item_id
LEFT JOIN properties p ON ip.property_id = p.id
ORDER BY oi.item_order ASC"
)?; )?;
let mut items: HashMap<String, Item> = HashMap::new();
// Change from HashMap to Vec to preserve order
let mut items: Vec<Item> = Vec::new();
let mut current_id: Option<String> = None;
let rows = stmt.query_map([url_id], |row| { let rows = stmt.query_map([url_id], |row| {
Ok(( Ok((
row.get::<_, String>(0)?, // id row.get::<_, String>(0)?, // id
row.get::<_, String>(1)?, // name row.get::<_, String>(1)?, // name
row.get::<_, String>(2)?, // description row.get::<_, String>(2)?, // description
row.get::<_, Option<String>>(3)?, // wikidata_id row.get::<_, Option<String>>(3)?, // wikidata_id
row.get::<_, Option<String>>(4)?, // prop_name row.get::<_, Option<String>>(4)?, // prop_name
row.get::<_, Option<String>>(5)?, // value row.get::<_, Option<String>>(5)?, // value
)) ))
})?; })?;
for row in rows { for row in rows {
let (id, name, desc, wd_id, prop, val) = row?; let (id, name, desc, wd_id, prop, val) = row?;
let item = items.entry(id.clone()).or_insert(Item {
id, if current_id.as_ref() != Some(&id) {
name, // New item - push to vector
description: desc, items.push(Item {
wikidata_id: wd_id, id: id.clone(),
custom_properties: HashMap::new(), name,
}); description: desc,
wikidata_id: wd_id,
custom_properties: HashMap::new(),
});
current_id = Some(id);
}
if let (Some(p), Some(v)) = (prop, val) { if let (Some(p), Some(v)) = (prop, val) {
item.custom_properties.insert(p, v); if let Some(last_item) = items.last_mut() {
last_item.custom_properties.insert(p, v);
}
} }
} }
Ok(items.into_values().collect()) Ok(items)
} }
async fn get_or_create_property( async fn get_or_create_property(