Fix recursive-any tag counting
This is bad security wise so it'll need another pass.
This commit is contained in:
70
src/tags.rs
70
src/tags.rs
@@ -6,6 +6,7 @@ use anyhow::Context;
|
||||
use chrono::Utc;
|
||||
use diesel::dsl::count_star;
|
||||
use diesel::prelude::*;
|
||||
use diesel::sql_types::*;
|
||||
use log::{debug, info, trace};
|
||||
use schema::{tagged_photo, tags};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -390,30 +391,42 @@ impl TagDao for SqliteTagDao {
|
||||
) -> anyhow::Result<Vec<FileWithTagCount>> {
|
||||
use diesel::dsl::*;
|
||||
|
||||
let exclude_subquery = tagged_photo::table
|
||||
.filter(tagged_photo::tag_id.eq_any(exclude_tag_ids.clone()))
|
||||
.select(tagged_photo::photo_name)
|
||||
.into_boxed();
|
||||
let tag_ids_str = tag_ids
|
||||
.iter()
|
||||
.map(|id| id.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(",");
|
||||
|
||||
tagged_photo::table
|
||||
.filter(tagged_photo::tag_id.eq_any(tag_ids.clone()))
|
||||
.filter(tagged_photo::photo_name.ne_all(exclude_subquery))
|
||||
.group_by(tagged_photo::photo_name)
|
||||
.select((
|
||||
tagged_photo::photo_name,
|
||||
count_distinct(tagged_photo::tag_id),
|
||||
))
|
||||
.get_results::<(String, i64)>(&mut self.connection)
|
||||
.map(|results| {
|
||||
results
|
||||
.into_iter()
|
||||
.map(|(file_name, tag_count)| FileWithTagCount {
|
||||
file_name,
|
||||
tag_count,
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.with_context(|| format!("Unable to get Tagged photos with ids: {:?}", tag_ids))
|
||||
let exclude_tag_ids_str = exclude_tag_ids
|
||||
.iter()
|
||||
.map(|id| id.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(",");
|
||||
|
||||
let query = sql_query(format!(
|
||||
r#"
|
||||
WITH filtered_photos AS (
|
||||
SELECT DISTINCT photo_name
|
||||
FROM tagged_photo tp
|
||||
WHERE tp.tag_id IN ({})
|
||||
AND tp.photo_name NOT IN (
|
||||
SELECT photo_name
|
||||
FROM tagged_photo
|
||||
WHERE tag_id IN ({})
|
||||
)
|
||||
)
|
||||
SELECT
|
||||
fp.photo_name as file_name,
|
||||
COUNT(DISTINCT tp2.tag_id) as tag_count
|
||||
FROM filtered_photos fp
|
||||
JOIN tagged_photo tp2 ON fp.photo_name = tp2.photo_name
|
||||
GROUP BY fp.photo_name"#,
|
||||
tag_ids_str, exclude_tag_ids_str
|
||||
));
|
||||
|
||||
// Execute the query:
|
||||
let results = query.load::<FileWithTagCount>(&mut self.connection)?;
|
||||
Ok(results)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -629,9 +642,10 @@ mod tests {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FileWithTagCount {
|
||||
pub file_name: String,
|
||||
pub tag_count: i64,
|
||||
#[derive(QueryableByName, Debug, Clone)]
|
||||
pub(crate) struct FileWithTagCount {
|
||||
#[diesel(sql_type = Text)]
|
||||
pub(crate) file_name: String,
|
||||
#[diesel(sql_type = BigInt)]
|
||||
pub(crate) tag_count: i64,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user