sos_database/entity/
server.rs

1use crate::Result;
2use async_sqlite::rusqlite::{
3    Connection, Error as SqlError, OptionalExtension, Row,
4};
5use sos_core::{Origin, UtcDateTime};
6use sql_query_builder as sql;
7use std::ops::Deref;
8use url::Url;
9
10/// Server row from the database.
11#[doc(hidden)]
12#[derive(Debug, Default)]
13pub struct ServerRow {
14    pub row_id: i64,
15    created_at: String,
16    modified_at: String,
17    name: String,
18    url: String,
19}
20
21impl<'a> TryFrom<&Row<'a>> for ServerRow {
22    type Error = SqlError;
23    fn try_from(row: &Row<'a>) -> std::result::Result<Self, Self::Error> {
24        Ok(ServerRow {
25            row_id: row.get(0)?,
26            created_at: row.get(1)?,
27            modified_at: row.get(2)?,
28            name: row.get(3)?,
29            url: row.get(4)?,
30        })
31    }
32}
33
34impl TryFrom<ServerRow> for Origin {
35    type Error = crate::Error;
36    fn try_from(row: ServerRow) -> std::result::Result<Self, Self::Error> {
37        Ok(Origin::new(row.name, row.url.parse()?))
38    }
39}
40
41impl TryFrom<Origin> for ServerRow {
42    type Error = crate::Error;
43    fn try_from(value: Origin) -> std::result::Result<Self, Self::Error> {
44        Ok(Self {
45            created_at: UtcDateTime::default().to_rfc3339()?,
46            modified_at: UtcDateTime::default().to_rfc3339()?,
47            name: value.name().to_string(),
48            url: value.url().to_string(),
49            ..Default::default()
50        })
51    }
52}
53
54/// Server entity.
55pub struct ServerEntity<'conn, C>
56where
57    C: Deref<Target = Connection>,
58{
59    conn: &'conn C,
60}
61
62impl<'conn, C> ServerEntity<'conn, C>
63where
64    C: Deref<Target = Connection>,
65{
66    /// Create a new server entity.
67    pub fn new(conn: &'conn C) -> Self {
68        Self { conn }
69    }
70
71    fn find_server_select(&self, select_one: bool) -> sql::Select {
72        let mut query = sql::Select::new()
73            .select(
74                r#"
75                    server_id,
76                    created_at,
77                    modified_at,
78                    name,
79                    url
80                "#,
81            )
82            .from("servers")
83            .where_clause("account_id=?1");
84        if select_one {
85            query = query.where_and("url=?2");
86        }
87        query
88    }
89
90    /// Find a server in the database.
91    pub fn find_one(
92        &self,
93        account_id: i64,
94        url: &Url,
95    ) -> std::result::Result<ServerRow, SqlError> {
96        let mut stmt = self
97            .conn
98            .prepare_cached(&self.find_server_select(true).as_string())?;
99        stmt.query_row((account_id, url.to_string()), |row| row.try_into())
100    }
101
102    /// Find an optional server in the database.
103    pub fn find_optional(
104        &self,
105        account_id: i64,
106        url: &Url,
107    ) -> std::result::Result<Option<ServerRow>, SqlError> {
108        let mut stmt = self
109            .conn
110            .prepare_cached(&self.find_server_select(true).as_string())?;
111        stmt.query_row((account_id, url.to_string()), |row| row.try_into())
112            .optional()
113    }
114
115    /// Load servers for an account.
116    pub fn load_servers(&self, account_id: i64) -> Result<Vec<ServerRow>> {
117        let query = self.find_server_select(false);
118        let mut stmt = self.conn.prepare_cached(&query.as_string())?;
119
120        fn convert_row(row: &Row<'_>) -> Result<ServerRow> {
121            Ok(row.try_into()?)
122        }
123
124        let rows = stmt.query_and_then([account_id], convert_row)?;
125        let mut servers = Vec::new();
126        for row in rows {
127            servers.push(row?);
128        }
129        Ok(servers)
130    }
131
132    /// Delete server origin from the database.
133    pub fn delete_server(
134        &self,
135        server_id: i64,
136    ) -> std::result::Result<(), SqlError> {
137        let query = sql::Delete::new()
138            .delete_from("servers")
139            .where_clause("server_id = ?1");
140        let mut stmt = self.conn.prepare_cached(&query.as_string())?;
141        stmt.execute([server_id])?;
142        Ok(())
143    }
144
145    /// Create server origin in the database.
146    pub fn insert_server(
147        &self,
148        account_id: i64,
149        server: &ServerRow,
150    ) -> std::result::Result<(), SqlError> {
151        let query = sql::Insert::new()
152            .insert_into(
153                "servers (account_id, created_at, modified_at, name, url)",
154            )
155            .values("(?1, ?2, ?3, ?4, ?5)");
156        let mut stmt = self.conn.prepare_cached(&query.as_string())?;
157        stmt.execute((
158            account_id,
159            &server.created_at,
160            &server.modified_at,
161            &server.name,
162            &server.url,
163        ))?;
164
165        Ok(())
166    }
167
168    /// Create server origins in the database.
169    pub fn insert_servers(
170        &self,
171        account_id: i64,
172        servers: &[ServerRow],
173    ) -> std::result::Result<(), SqlError> {
174        for server in servers {
175            self.insert_server(account_id, server)?;
176        }
177        Ok(())
178    }
179}