post_archiver/query/
tag.rs1use rusqlite::OptionalExtension;
4
5use crate::{
6 manager::{PostArchiverConnection, PostArchiverManager},
7 PlatformId, Tag, TagId,
8};
9
10use super::{
11 filter::{IdFilter, TextFilter},
12 sortable::impl_sortable,
13 BaseFilter, FromQuery, Query, Queryer, RawSql,
14};
15
16#[derive(Debug)]
24pub struct TagQuery<'a, C> {
25 queryer: Queryer<'a, C>,
26 pub ids: IdFilter<TagId>,
27 pub name: TextFilter,
28 pub source: TextFilter,
29 pub platforms: IdFilter<PlatformId>,
30}
31
32impl<'a, C: PostArchiverConnection> TagQuery<'a, C> {
33 pub fn new(manager: &'a PostArchiverManager<C>) -> Self {
34 TagQuery {
35 queryer: Queryer::new(manager),
36 ids: IdFilter::new("id"),
37 name: TextFilter::new("name"),
38 source: TextFilter::new("source"),
39 platforms: IdFilter::new("platform"),
40 }
41 }
42}
43
44impl_sortable!(TagQuery(TagSort) {
45 Id: "id",
46 Name: "name",
47 Source: "source"
48});
49
50impl<C: PostArchiverConnection> BaseFilter for TagQuery<'_, C> {
51 type Based = Tag;
52
53 fn update_sql<T: FromQuery<Based = Self::Based>>(&self, mut sql: RawSql<T>) -> RawSql<T> {
54 sql = self.ids.build_sql(sql);
55 sql = self.name.build_sql(sql);
56 sql = self.source.build_sql(sql);
57 sql = self.platforms.build_sql(sql);
58
59 sql
60 }
61
62 fn queryer(&self) -> &Queryer<'_, impl PostArchiverConnection> {
63 &self.queryer
64 }
65}
66
67impl<C: PostArchiverConnection> Query for TagQuery<'_, C> {
68 type Wrapper<T> = Vec<T>;
69 type Based = Tag;
70
71 fn query_with_context<T: FromQuery<Based = Self::Based>>(
72 self,
73 sql: RawSql<T>,
74 ) -> crate::error::Result<Self::Wrapper<T>> {
75 let sql = self.update_sql(sql);
76 let (sql, params) = sql.build_sql();
77 self.queryer.fetch(&sql, params)
78 }
79}
80
81impl<C: PostArchiverConnection> PostArchiverManager<C> {
82 pub fn tags(&self) -> TagQuery<'_, C> {
84 TagQuery::new(self)
85 }
86
87 pub fn get_tag(&self, id: TagId) -> crate::error::Result<Option<Tag>> {
89 let mut stmt = self
90 .conn()
91 .prepare_cached("SELECT * FROM tags WHERE id = ?")?;
92 Ok(stmt.query_row([id], Tag::from_row).optional()?)
93 }
94
95 pub fn find_tag(
97 &self,
98 name: &str,
99 platform: Option<PlatformId>,
100 ) -> crate::error::Result<Option<TagId>> {
101 let mut stmt = self
102 .conn()
103 .prepare_cached("SELECT id FROM tags WHERE platform IS ? AND name = ?")?;
104 Ok(stmt
105 .query_row(rusqlite::params![platform, name], |row| row.get(0))
106 .optional()?)
107 }
108}