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| {
100 row.try_into()
101 })
102 }
103
104 pub fn find_optional(
106 &self,
107 account_id: i64,
108 url: &Url,
109 ) -> std::result::Result<Option<ServerRow>, SqlError> {
110 let mut stmt = self
111 .conn
112 .prepare_cached(&self.find_server_select(true).as_string())?;
113 stmt
114 .query_row((account_id, url.to_string()), |row| {
115 row.try_into()
116 })
117 .optional()
118 }
119
120 pub fn load_servers(&self, account_id: i64) -> Result<Vec<ServerRow>> {
122 let query = self.find_server_select(false);
123 let mut stmt = self.conn.prepare_cached(&query.as_string())?;
124
125 fn convert_row(row: &Row<'_>) -> Result<ServerRow> {
126 Ok(row.try_into()?)
127 }
128
129 let rows = stmt.query_and_then([account_id], |row| {
130 convert_row(row)
131 })?;
132 let mut servers = Vec::new();
133 for row in rows {
134 servers.push(row?);
135 }
136 Ok(servers)
137 }
138
139 pub fn delete_server(
141 &self,
142 server_id: i64,
143 ) -> std::result::Result<(), SqlError> {
144 let query = sql::Delete::new()
145 .delete_from("servers")
146 .where_clause("server_id = ?1");
147 let mut stmt = self.conn.prepare_cached(&query.as_string())?;
148 stmt.execute([server_id])?;
149 Ok(())
150 }
151
152 pub fn insert_server(
154 &self,
155 account_id: i64,
156 server: &ServerRow,
157 ) -> std::result::Result<(), SqlError> {
158 let query = sql::Insert::new()
159 .insert_into(
160 "servers (account_id, created_at, modified_at, name, url)",
161 )
162 .values("(?1, ?2, ?3, ?4, ?5)");
163 let mut stmt = self.conn.prepare_cached(&query.as_string())?;
164 stmt.execute((
165 account_id,
166 &server.created_at,
167 &server.modified_at,
168 &server.name,
169 &server.url,
170 ))?;
171
172 Ok(())
173 }
174
175 pub fn insert_servers(
177 &self,
178 account_id: i64,
179 servers: &[ServerRow],
180 ) -> std::result::Result<(), SqlError> {
181 for server in servers {
182 self.insert_server(account_id, server)?;
183 }
184 Ok(())
185 }
186}