Adjusted the tale summary retrieval.

The SQL was not properly searching the tales. It had been searching and
finding all the tags that matched the search criteria, but it was
dropping all the other tag information. Now it properly keeps all the
tag information. This fixed an issue where the tags of a post were
disapearing and reapearing as the TagSelector was toggled.
This commit is contained in:
2025-09-24 19:36:29 -04:00
parent 2ffe20254c
commit 01dacabc03

View File

@ -299,70 +299,82 @@ impl Database
pub async fn get_tales_summary(&self, categories: &[String])
-> Result<Vec<Lore>>
{
let mut tales = Vec::new();
let mut tales = Vec::new();
// Start a read-only transaction.
let mut tx = self.pool.begin().await?;
// Start a read-only transaction.
let mut tx = self.pool.begin().await?;
// Dynamically build the query.
let mut query = String::from(
"SELECT
t.title,
t.slug,
t.summary,
t.author,
t.publish_date,
GROUP_CONCAT(tg.name, ',') AS tags
FROM tales AS t
LEFT JOIN tale_tags AS tt ON t.slug = tt.tale_slug
LEFT JOIN tags AS tg ON tt.tag_id = tg.id"
);
// Build the base query string with placeholders for categories in the EXISTS clause.
// We add a parameter for categories length to check if filtering is needed.
let mut query = String::from(
"SELECT
t.title,
t.slug,
t.summary,
t.author,
t.publish_date,
GROUP_CONCAT(tg_all.name, ',') AS tags
FROM tales AS t
LEFT JOIN tale_tags AS tt_all ON t.slug = tt_all.tale_slug
LEFT JOIN tags AS tg_all ON tt_all.tag_id = tg_all.id
WHERE (? = 0 OR EXISTS (
SELECT 1 FROM tale_tags tt_filter
JOIN tags tg_filter ON tt_filter.tag_id = tg_filter.id
WHERE tt_filter.tale_slug = t.slug
AND tg_filter.name IN ("
);
if !categories.is_empty()
{
query.push_str(" WHERE tg.name IN (");
let placeholders: Vec<_> =
(0..categories.len()).map(|_| "?").collect();
query.push_str(&placeholders.join(", "));
query.push(')');
}
// Add placeholders for category names in EXISTS IN clause
if !categories.is_empty() {
let placeholders: Vec<_> = (0..categories.len()).map(|_| "?").collect();
query.push_str(&placeholders.join(", "));
} else {
// No categories, so dummy placeholder to satisfy SQL syntax
query.push_str("NULL");
}
query.push_str("))) GROUP BY t.slug ORDER BY t.publish_date DESC");
query.push_str(" GROUP BY t.slug ORDER BY t.publish_date DESC");
// Prepare query with sqlx
let mut q = sqlx::query(&query);
let mut q = sqlx::query(&query);
for cat in categories
{
q = q.bind(cat);
}
// Bind the length of categories for the (? = 0) check
q = q.bind(categories.len() as i64);
let rows = q.fetch_all(&mut *tx).await?;
let current_time = chrono::Utc::now().naive_utc();
// Bind the category names if any
for cat in categories {
q = q.bind(cat);
}
for row in rows
{
let date_str: String = row.try_get("publish_date")?;
let publish_date = chrono::NaiveDateTime::parse_from_str(&date_str, "%Y-%m-%d %H:%M:%S")
.map_err(|e| sqlx::Error::Decode(e.into()))?;
// Execute the query
let rows = q.fetch_all(&mut *tx).await?;
let current_time = chrono::Utc::now().naive_utc();
// Only give tales that are ready to be published.
if current_time >= publish_date
{
let tags_str: Option<String> = row.try_get("tags")?;
let tags = tags_str.map(|s| s.split(',').map(String::from).collect())
.unwrap_or_default();
for row in rows {
let date_str: String = row.try_get("publish_date")?;
let publish_date = chrono::NaiveDateTime::parse_from_str(&date_str, "%Y-%m-%d %H:%M:%S")
.map_err(|e| sqlx::Error::Decode(e.into()))?;
tales.push(Lore { title: row.try_get("title")?,
slug: row.try_get("slug")?,
summary: row.try_get("summary")?,
author: row.try_get("author")?,
publish_date,
tags });
}
}
// Only include tales that are ready to be published.
if current_time >= publish_date {
let tags_str: Option<String> = row.try_get("tags")?;
let tags = tags_str
.map(|s| s.split(',').map(String::from).collect())
.unwrap_or_default();
tx.commit().await?; // Explicit commit, even for read transactions.
tales.push(Lore {
title: row.try_get("title")?,
slug: row.try_get("slug")?,
summary: row.try_get("summary")?,
author: row.try_get("author")?,
publish_date,
tags,
});
}
}
Ok(tales)
tx.commit().await?; // Explicit commit, even for read transactions.
Ok(tales)
}
#[cfg(any(not(feature = "publisher"), feature = "tester"))]