post_archiver/manager/
platform.rs

1use rusqlite::{params, OptionalExtension};
2
3use crate::{Platform, PlatformId, Post, Tag};
4
5use super::{PostArchiverConnection, PostArchiverManager};
6
7//=============================================================
8// Querying
9//=============================================================
10impl<T> PostArchiverManager<T>
11where
12    T: PostArchiverConnection,
13{
14    /// Retrieve all platforms in the archive.
15    ///
16    /// # Errors
17    ///
18    /// Returns `rusqlite::Error` if there was an error accessing the database.
19    pub fn list_platforms(&self) -> Result<Vec<Platform>, rusqlite::Error> {
20        let mut stmt = self.conn().prepare_cached("SELECT * FROM platforms")?;
21        let platforms = stmt.query_map([], Platform::from_row)?;
22        platforms.collect()
23    }
24
25    /// Find a platform by its name.
26    ///
27    /// # Errors
28    ///
29    /// Returns `rusqlite::Error` if there was an error accessing the database.
30    pub fn find_platform(&self, name: &str) -> Result<Option<PlatformId>, rusqlite::Error> {
31        if let Some(platform) = self.cache.platforms.get(name) {
32            return Ok(Some(*platform));
33        }
34
35        let query = "SELECT id FROM platforms WHERE name = ?";
36        let mut stmt = self.conn().prepare_cached(query)?;
37        let id = stmt.query_row([name], |row| row.get(0)).optional();
38
39        if let Ok(Some(id)) = id {
40            self.cache.platforms.insert(name.to_string(), id);
41        }
42
43        id
44    }
45    /// Retrieve a platform by its ID.
46    ///
47    /// # Errors
48    ///
49    /// Returns `rusqlite::Error` if:
50    /// * The platform ID does not exist
51    /// * There was an error accessing the database
52    pub fn get_platform(&self, id: &PlatformId) -> Result<Platform, rusqlite::Error> {
53        let query = "SELECT * FROM platforms WHERE id = ?";
54        let mut stmt = self.conn().prepare_cached(query)?;
55        stmt.query_row([id], Platform::from_row)
56    }
57}
58
59//=============================================================
60// Modifying
61//=============================================================
62impl<T> PostArchiverManager<T>
63where
64    T: PostArchiverConnection,
65{
66    /// Add a new platform to the archive.
67    ///
68    /// # Errors
69    ///
70    /// Returns `rusqlite::Error` if:
71    /// * The platform already exists
72    /// * There was an error accessing the database
73    pub fn add_platform(&self, platform: String) -> Result<PlatformId, rusqlite::Error> {
74        let mut stmt = self
75            .conn()
76            .prepare_cached("INSERT INTO platforms (name) VALUES (?) RETURNING id")?;
77        let id = stmt.query_row([&platform], |row| row.get(0));
78
79        if let Ok(id) = id {
80            self.cache.platforms.insert(platform, id);
81        }
82
83        id
84    }
85
86    /// Remove a platform from the archive.
87    ///
88    /// This operation will also set the platform to UNKNOWN for all author aliases and posts with the platform.
89    /// But it will delete tags associated with the platform.
90    ///
91    /// # Errors
92    ///
93    /// Returns `rusqlite::Error` if there was an error accessing the database.
94    pub fn remove_platform(&self, id: &PlatformId) -> Result<(), rusqlite::Error> {
95        let mut stmt = self
96            .conn()
97            .prepare_cached("DELETE FROM platforms WHERE id = ?")?;
98        stmt.execute([id])?;
99        Ok(())
100    }
101
102    /// Set the name of a platform.
103    ///
104    /// # Errors
105    ///
106    /// Returns `rusqlite::Error` if there was an error accessing the database.
107    pub fn set_platform_name(&self, id: &PlatformId, name: String) -> Result<(), rusqlite::Error> {
108        let mut stmt = self
109            .conn()
110            .prepare_cached("UPDATE platforms SET name = ? WHERE id = ?")?;
111        stmt.execute(params![name, id])?;
112        self.cache.platforms.insert(name.clone(), *id);
113        Ok(())
114    }
115}
116
117//=============================================================
118// Relationships
119//=============================================================
120impl<T> PostArchiverManager<T>
121where
122    T: PostArchiverConnection,
123{
124    /// List all tags associated with a platform.
125    ///
126    /// # Errors
127    ///
128    /// Returns `rusqlite::Error` if there was an error accessing the database.
129    pub fn list_platform_tags(
130        &self,
131        platform: &Option<PlatformId>,
132    ) -> Result<Vec<Tag>, rusqlite::Error> {
133        let mut stmt = self
134            .conn()
135            .prepare_cached("SELECT * FROM tags WHERE platform = ?")?;
136        let tags = stmt.query_map([platform], Tag::from_row)?;
137        tags.collect()
138    }
139    /// List all posts associated with a platform.
140    ///
141    /// # Errors
142    ///
143    /// Returns `rusqlite::Error` if there was an error accessing the database.
144    pub fn list_platform_posts(
145        &self,
146        platform: &Option<PlatformId>,
147    ) -> Result<Vec<Post>, rusqlite::Error> {
148        let mut stmt = self
149            .conn()
150            .prepare_cached("SELECT * FROM posts WHERE platform = ?")?;
151        let posts = stmt.query_map([platform], Post::from_row)?;
152        posts.collect()
153    }
154}
155
156impl Platform {
157    /// Retrieve all tags associated with this platform.
158    ///
159    /// # Errors
160    ///
161    /// Returns `rusqlite::Error` if there was an error accessing the database.
162    pub fn tags(&self, manager: &PostArchiverManager) -> Result<Vec<Tag>, rusqlite::Error> {
163        manager.list_platform_tags(&Some(self.id))
164    }
165    /// Retrieve all posts associated with this platform.
166    ///
167    /// # Errors
168    ///
169    /// Returns `rusqlite::Error` if there was an error accessing the database.
170    pub fn posts(&self, manager: &PostArchiverManager) -> Result<Vec<Post>, rusqlite::Error> {
171        manager.list_platform_posts(&Some(self.id))
172    }
173}