sos_database/entity/
server.rs1use 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#[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
54pub 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 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 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 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 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 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 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 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}