Skip to main content

post_archiver/manager/
platform.rs

1use crate::{
2    error::Result,
3    manager::{binded::Binded, PostArchiverConnection},
4    query::FromQuery,
5    Platform, PlatformId, PostId, TagId,
6};
7
8/// Builder for updating a platform's fields.
9///
10/// Fields left as `None` are not modified.
11#[derive(Debug, Clone, Default)]
12pub struct UpdatePlatform {
13    pub name: Option<String>,
14}
15
16impl UpdatePlatform {
17    /// Set the platform's name.
18    pub fn name(mut self, name: String) -> Self {
19        self.name = Some(name);
20        self
21    }
22}
23
24//=============================================================
25// Update / Delete
26//=============================================================
27impl<'a, C: PostArchiverConnection> Binded<'a, PlatformId, C> {
28    /// Get this platform's current data from the database.
29    pub fn value(&self) -> Result<Platform> {
30        let mut stmt = self
31            .conn()
32            .prepare_cached("SELECT * FROM platforms WHERE id = ?")?;
33        Ok(stmt.query_row([self.id()], Platform::from_row)?)
34    }
35
36    /// Remove this platform from the archive.
37    ///
38    /// This operation will also set the platform to UNKNOWN for all author aliases and posts.
39    /// Tags associated with the platform will be deleted.
40    pub fn delete(self) -> Result<()> {
41        let mut stmt = self
42            .conn()
43            .prepare_cached("DELETE FROM platforms WHERE id = ?")?;
44        stmt.execute([self.id()])?;
45        Ok(())
46    }
47
48    /// Apply a batch of field updates to this platform in a single SQL statement.
49    ///
50    /// Only fields set on `update` (i.e. `Some(...)`) are written to the database.
51    pub fn update(&self, update: UpdatePlatform) -> Result<()> {
52        use rusqlite::types::ToSql;
53
54        let mut sets: Vec<&str> = Vec::new();
55        let mut params: Vec<&dyn ToSql> = Vec::new();
56
57        macro_rules! push {
58            ($field:expr, $col:expr) => {
59                if let Some(ref v) = $field {
60                    sets.push($col);
61                    params.push(v);
62                }
63            };
64        }
65
66        push!(update.name, "name = ?");
67
68        if sets.is_empty() {
69            return Ok(());
70        }
71
72        let id = self.id();
73        params.push(&id);
74
75        let sql = format!("UPDATE platforms SET {} WHERE id = ?", sets.join(", "));
76        self.conn().execute(&sql, params.as_slice())?;
77        Ok(())
78    }
79}
80
81//=============================================================
82// Relations: Tags / Posts
83//=============================================================
84impl<'a, C: PostArchiverConnection> Binded<'a, PlatformId, C> {
85    /// List all tag IDs associated with this platform.
86    pub fn list_tags(&self) -> Result<Vec<TagId>> {
87        let mut stmt = self
88            .conn()
89            .prepare_cached("SELECT id FROM tags WHERE platform = ?")?;
90        let rows = stmt.query_map([self.id()], |row| row.get(0))?;
91        rows.collect::<std::result::Result<_, _>>()
92            .map_err(Into::into)
93    }
94
95    /// List all post IDs associated with this platform.
96    pub fn list_posts(&self) -> Result<Vec<PostId>> {
97        let mut stmt = self
98            .conn()
99            .prepare_cached("SELECT id FROM posts WHERE platform = ?")?;
100        let rows = stmt.query_map([self.id()], |row| row.get(0))?;
101        rows.collect::<std::result::Result<_, _>>()
102            .map_err(Into::into)
103    }
104}