post_archiver/manager/
tag.rs1use crate::{
2 error::Result,
3 manager::{binded::Binded, PostArchiverConnection},
4 query::FromQuery,
5 PlatformId, PostId, Tag, TagId,
6};
7
8#[derive(Debug, Clone, Default)]
13pub struct UpdateTag {
14 pub name: Option<String>,
15 pub platform: Option<Option<PlatformId>>,
16}
17
18impl UpdateTag {
19 pub fn name(mut self, name: String) -> Self {
21 self.name = Some(name);
22 self
23 }
24 pub fn platform(mut self, platform: Option<PlatformId>) -> Self {
26 self.platform = Some(platform);
27 self
28 }
29}
30
31pub trait FindTag {
35 fn name(&self) -> &str;
36 fn platform(&self) -> Option<PlatformId> {
37 None
38 }
39}
40
41impl FindTag for &str {
42 fn name(&self) -> &str {
43 self
44 }
45}
46
47impl FindTag for (&str, PlatformId) {
48 fn name(&self) -> &str {
49 self.0
50 }
51 fn platform(&self) -> Option<PlatformId> {
52 Some(self.1)
53 }
54}
55
56impl FindTag for (&str, Option<PlatformId>) {
57 fn name(&self) -> &str {
58 self.0
59 }
60 fn platform(&self) -> Option<PlatformId> {
61 self.1
62 }
63}
64
65impl<'a, C: PostArchiverConnection> Binded<'a, TagId, C> {
69 pub fn value(&self) -> Result<Tag> {
71 let mut stmt = self
72 .conn()
73 .prepare_cached("SELECT * FROM tags WHERE id = ?")?;
74 Ok(stmt.query_row([self.id()], Tag::from_row)?)
75 }
76
77 pub fn delete(self) -> Result<()> {
81 let mut stmt = self
82 .conn()
83 .prepare_cached("DELETE FROM tags WHERE id = ?")?;
84 stmt.execute([self.id()])?;
85 Ok(())
86 }
87
88 pub fn update(&self, update: UpdateTag) -> Result<()> {
92 use rusqlite::types::ToSql;
93
94 let mut sets: Vec<&str> = Vec::new();
95 let mut params: Vec<&dyn ToSql> = Vec::new();
96
97 macro_rules! push {
98 ($field:expr, $col:expr) => {
99 if let Some(ref v) = $field {
100 sets.push($col);
101 params.push(v);
102 }
103 };
104 }
105
106 push!(update.name, "name = ?");
107 push!(update.platform, "platform = ?");
108
109 if sets.is_empty() {
110 return Ok(());
111 }
112
113 let id = self.id();
114 params.push(&id);
115
116 let sql = format!("UPDATE tags SET {} WHERE id = ?", sets.join(", "));
117 self.conn().execute(&sql, params.as_slice())?;
118 Ok(())
119 }
120}
121
122impl<'a, C: PostArchiverConnection> Binded<'a, TagId, C> {
126 pub fn list_posts(&self) -> Result<Vec<PostId>> {
128 let mut stmt = self
129 .conn()
130 .prepare_cached("SELECT post FROM post_tags WHERE tag = ?")?;
131 let rows = stmt.query_map([self.id()], |row| row.get(0))?;
132 rows.collect::<std::result::Result<_, _>>()
133 .map_err(Into::into)
134 }
135}