Skip to main content

post_archiver/query/
platform.rs

1//! Platform query builder and related point-query helpers.
2
3use rusqlite::OptionalExtension;
4
5use crate::{
6    manager::{PostArchiverConnection, PostArchiverManager},
7    Platform, PlatformId,
8};
9
10use super::{
11    filter::{IdFilter, TextFilter},
12    sortable::impl_sortable,
13    BaseFilter, FromQuery, Query, Queryer, RawSql,
14};
15
16// ── Builder ───────────────────────────────────────────────────────────────────
17
18/// Query builder for platforms.  Obtained via [`PostArchiverManager::platforms()`].
19///
20/// Platforms are typically few in number, so this builder is intentionally simple—no
21/// pagination or total-count is provided.  `.query()` always returns `Vec<Platform>`.
22///
23/// # Available filter fields
24/// - `ids`: filter by a set of [`PlatformId`] values.
25/// - `name`: `LIKE` fuzzy match on the platform name.
26#[derive(Debug)]
27pub struct PlatformQuery<'a, C> {
28    queryer: Queryer<'a, C>,
29    pub ids: IdFilter<PlatformId>,
30    pub name: TextFilter,
31}
32
33impl_sortable!(PlatformQuery(PlatformSort) {
34    Id: "id",
35    Name: "name"
36});
37
38impl<'a, C: PostArchiverConnection> PlatformQuery<'a, C> {
39    pub fn new(manager: &'a PostArchiverManager<C>) -> Self {
40        PlatformQuery {
41            queryer: Queryer::new(manager),
42            ids: IdFilter::new("id"),
43            name: TextFilter::new("name"),
44        }
45    }
46}
47
48impl<C: PostArchiverConnection> BaseFilter for PlatformQuery<'_, C> {
49    type Based = Platform;
50
51    fn update_sql<T: FromQuery<Based = Self::Based>>(&self, mut sql: RawSql<T>) -> RawSql<T> {
52        sql = self.ids.build_sql(sql);
53        sql = self.name.build_sql(sql);
54
55        sql
56    }
57
58    fn queryer(&self) -> &Queryer<'_, impl PostArchiverConnection> {
59        &self.queryer
60    }
61}
62
63impl<C: PostArchiverConnection> Query for PlatformQuery<'_, C> {
64    type Wrapper<T> = Vec<T>;
65    type Based = Platform;
66
67    fn query_with_context<T: FromQuery<Based = Self::Based>>(
68        self,
69        sql: RawSql<T>,
70    ) -> crate::error::Result<Self::Wrapper<T>> {
71        let sql = self.update_sql(sql);
72        let (sql, params) = sql.build_sql();
73        self.queryer.fetch(&sql, params)
74    }
75}
76
77// ── Point-query helpers on PostArchiverManager ────────────────────────────────
78
79impl<C: PostArchiverConnection> PostArchiverManager<C> {
80    /// Entry point for the platform query builder.
81    pub fn platforms(&self) -> PlatformQuery<'_, C> {
82        PlatformQuery::new(self)
83    }
84
85    /// Fetch a single platform by primary key. Returns `None` if not found.
86    pub fn get_platform(&self, id: PlatformId) -> crate::error::Result<Option<Platform>> {
87        let mut stmt = self
88            .conn()
89            .prepare_cached("SELECT * FROM platforms WHERE id = ?")?;
90        Ok(stmt.query_row([id], Platform::from_row).optional()?)
91    }
92
93    /// Find a platform ID by name (exact match, case-sensitive).
94    pub fn find_platform(&self, name: &str) -> crate::error::Result<Option<PlatformId>> {
95        let mut stmt = self
96            .conn()
97            .prepare_cached("SELECT id FROM platforms WHERE name = ?")?;
98        Ok(stmt.query_row([name], |row| row.get(0)).optional()?)
99    }
100}