post_archiver/query/
author.rs1use rusqlite::OptionalExtension;
4
5use crate::{
6 manager::{PostArchiverConnection, PostArchiverManager},
7 Alias, Author, AuthorId, PlatformId,
8};
9
10use super::{
11 filter::{DateFilter, IdFilter, TextFilter},
12 sortable::impl_sortable,
13 BaseFilter, FromQuery, Query, Queryer, RawSql,
14};
15
16#[derive(Debug)]
23pub struct AuthorQuery<'a, C> {
24 queryer: Queryer<'a, C>,
25 pub ids: IdFilter<AuthorId>,
26 pub name: TextFilter,
27 pub updated: DateFilter,
28}
29
30impl<'a, C: PostArchiverConnection> AuthorQuery<'a, C> {
31 pub fn new(manager: &'a PostArchiverManager<C>) -> Self {
32 AuthorQuery {
33 queryer: Queryer::new(manager),
34 ids: IdFilter::new("id"),
35 name: TextFilter::new("name"),
36 updated: DateFilter::new("updated"),
37 }
38 }
39}
40
41impl_sortable!(AuthorQuery(AuthorSort) {
42 Id: "id",
43 Name: "name",
44 Updated: "updated"
45});
46
47impl<C: PostArchiverConnection> BaseFilter for AuthorQuery<'_, C> {
48 type Based = Author;
49
50 fn update_sql<T: FromQuery<Based = Self::Based>>(&self, mut sql: RawSql<T>) -> RawSql<T> {
51 sql = self.ids.build_sql(sql);
52 sql = self.name.build_sql(sql);
53 sql = self.updated.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 AuthorQuery<'_, C> {
64 type Wrapper<U> = Vec<U>;
65 type Based = Author;
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
77impl<C: PostArchiverConnection> PostArchiverManager<C> {
80 pub fn authors(&self) -> AuthorQuery<'_, C> {
82 AuthorQuery::new(self)
83 }
84
85 pub fn get_author(&self, id: AuthorId) -> crate::error::Result<Option<Author>> {
87 let mut stmt = self
88 .conn()
89 .prepare_cached("SELECT * FROM authors WHERE id = ?")?;
90 Ok(stmt.query_row([id], Author::from_row).optional()?)
91 }
92
93 pub fn find_author_by_alias(
95 &self,
96 source: &str,
97 platform: PlatformId,
98 ) -> crate::error::Result<Option<AuthorId>> {
99 let mut stmt = self.conn().prepare_cached(
100 "SELECT target FROM author_aliases WHERE platform = ? AND source = ?",
101 )?;
102 Ok(stmt
103 .query_row(rusqlite::params![platform, source], |row| row.get(0))
104 .optional()?)
105 }
106
107 pub fn list_author_aliases(&self, author: AuthorId) -> crate::error::Result<Vec<Alias>> {
109 let mut stmt = self
110 .conn()
111 .prepare_cached("SELECT * FROM author_aliases WHERE target = ?")?;
112 let rows = stmt.query_map([author], Alias::from_row)?;
113 rows.collect::<Result<_, _>>().map_err(Into::into)
114 }
115}