1use std::collections::HashMap;
2
3use crate::Config;
4use crate::Database;
5use crate::Error;
6use crate::Map;
7use crate::Version;
8use log::info;
9use rusqlite::{params, Connection};
10
11const INIT_CONFIGS: &str =
12 "CREATE TABLE configs (id TEXT, subset TEXT, family TEXT, map_path TEXT)";
13const INIT_VERSIONS: &str = "CREATE TABLE versions (id TEXT, ver INTEGER, tag TEXT, owner TEXT)";
14const INIT_MAPPED: &str = "CREATE TABLE maps (id TEXT, ver INTEGER, nhash TEXT, tag TEXT)";
15
16impl Database {
17 pub(crate) fn is_valid(&self) -> bool {
19 true
20 }
21
22 pub(crate) fn create_db_schema(&self) -> Result<(), Error> {
24 info!("Creating {:?}", self.path);
25 let con = match Connection::open(&self.path) {
26 Ok(c) => c,
27 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
28 };
29
30 match con.execute(INIT_CONFIGS, params![]) {
31 Ok(c) => c,
32 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
33 };
34
35 match con.execute(INIT_VERSIONS, params![]) {
36 Ok(c) => c,
37 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
38 };
39
40 match con.execute(INIT_MAPPED, params![]) {
41 Ok(c) => c,
42 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
43 };
44
45 return Ok(());
46 }
47
48 pub fn get_versions(&self, owner: &String) -> Result<HashMap<String, Version>, Error> {
50 info!("Finding all versions with owner {}", &owner);
51
52 let mut versions: HashMap<String, Version> = HashMap::new();
53
54 let con = match Connection::open(&self.path) {
55 Ok(c) => c,
56 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
57 };
58
59 let mut stmt = match con.prepare("SELECT * FROM versions where owner = ? ") {
61 Ok(c) => c,
62 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
63 };
64
65 let versions_iter = match stmt.query_map(params![owner], |row| {
67 Ok(Version {
68 data_hash: row.get(0)?,
69 ver: row.get(1)?,
70 tag: row.get(2)?,
71 owner: row.get(3)?,
72 })
73 }) {
74 Ok(i) => i,
75 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
76 };
77
78 for version in versions_iter {
80 match version {
81 Ok(v) => versions.insert(v.data_hash.clone(), v),
82 _ => None,
83 };
84 }
85
86 return Ok(versions);
87 }
88
89 pub fn get_current_version(&self, owner: &String) -> Result<Option<Version>, Error> {
91 info!("Finding the current version with owner {}", &owner);
92
93 let con = match Connection::open(&self.path) {
94 Ok(c) => c,
95 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
96 };
97
98 let mut stmt = match con.prepare("SELECT * FROM versions where owner = ? ORDER BY ver DESC")
100 {
101 Ok(c) => c,
102 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
103 };
104
105 let mut versions_iter = match stmt.query_map(params![owner], |row| {
107 Ok(Version {
108 data_hash: row.get(0)?,
109 ver: row.get(1)?,
110 tag: row.get(2)?,
111 owner: row.get(3)?,
112 })
113 }) {
114 Ok(i) => i,
115 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
116 };
117
118 return match versions_iter.next() {
119 Some(v) => match v {
120 Ok(v) => Ok(Some(v)),
121 Err(e) => Err(Error::SQLError { msg: e.to_string() }),
122 },
123 None => Ok(None),
124 };
125 }
126
127 pub fn get_current_map(&self, blob: &String) -> Result<Option<Map>, Error> {
129 info!("Finding the current map with id {}", &blob);
130
131 let con = match Connection::open(&self.path) {
132 Ok(c) => c,
133 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
134 };
135
136 let mut stmt = match con.prepare("SELECT * FROM maps where id = ? ORDER BY ver DESC") {
138 Ok(c) => c,
139 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
140 };
141
142 let mut maps_iter = match stmt.query_map(params![blob], |row| {
144 Ok(Map {
145 blob: row.get(0)?,
146 ver: row.get(1)?,
147 hash: row.get(2)?,
148 tag: row.get(3)?,
149 configs: Vec::new(),
150 })
151 }) {
152 Ok(i) => i,
153 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
154 };
155
156 return match maps_iter.next() {
157 Some(v) => match v {
158 Ok(v) => Ok(Some(v)),
159 Err(e) => Err(Error::SQLError { msg: e.to_string() }),
160 },
161 None => Ok(None),
162 };
163 }
164
165 pub fn get_mapped_path(&self, config_blob: &String) -> Result<Option<String>, Error> {
168 info!("Checking DB for map_path {}", config_blob);
169
170 let con = match Connection::open(&self.path) {
171 Ok(c) => c,
172 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
173 };
174
175 let mut stmt = match con.prepare("SELECT map_path FROM configs WHERE id = ?") {
177 Ok(c) => c,
178 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
179 };
180
181 let mut blobs_iter = match stmt.query_map(params![config_blob], |row| Ok(row.get(0)?)) {
183 Ok(i) => i,
184 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
185 };
186
187 return match blobs_iter.next() {
188 Some(v) => match v {
189 Ok(blob) => Ok(Some(blob)),
190 Err(e) => Err(Error::SQLError { msg: e.to_string() }),
191 },
192 None => Ok(None),
193 };
194 }
195
196 pub fn add_config(&self, c: &Config) -> Result<(), Error> {
198 info!("Adding config {}", c.get_blob());
199
200 let con = match Connection::open(&self.path) {
201 Ok(c) => c,
202 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
203 };
204
205 match con.execute(
207 "INSERT INTO configs (id, subset, family, map_path) VALUES (?1, ?2, ?3, ?4)",
208 params![c.blob, c.subset, c.family, c.map_path,],
209 ) {
210 Ok(c) => c,
211 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
212 };
213
214 return Ok(());
215 }
216
217 pub fn config_exists(&self, config_map_path: &String) -> Result<Option<String>, Error> {
219 info!("Checking DB for config {}", config_map_path);
220
221 let con = match Connection::open(&self.path) {
222 Ok(c) => c,
223 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
224 };
225
226 let mut stmt = match con.prepare("SELECT id FROM configs WHERE map_path = ?") {
228 Ok(c) => c,
229 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
230 };
231
232 let mut blobs_iter = match stmt.query_map(params![config_map_path], |row| Ok(row.get(0)?)) {
234 Ok(i) => i,
235 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
236 };
237
238 return match blobs_iter.next() {
239 Some(v) => match v {
240 Ok(blob) => Ok(Some(blob)),
241 Err(e) => Err(Error::SQLError { msg: e.to_string() }),
242 },
243 None => Ok(None),
244 };
245 }
246
247 pub fn add_version(&self, v: &Version) -> Result<(), Error> {
249 info!("Adding version {}", v.data_hash);
250
251 let con = match Connection::open(&self.path) {
252 Ok(c) => c,
253 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
254 };
255
256 match con.execute(
258 "INSERT INTO versions (id, ver, tag, owner) VALUES (?1, ?2, ?3, ?4)",
259 params![v.data_hash, v.ver, v.tag, v.owner],
260 ) {
261 Ok(c) => c,
262 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
263 };
264
265 return Ok(());
266 }
267
268 pub fn add_map(&self, m: &Map) -> Result<(), Error> {
270 info!("Adding map {}", m.get_blob());
271
272 let con = match Connection::open(&self.path) {
273 Ok(c) => c,
274 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
275 };
276
277 match con.execute(
279 "INSERT INTO maps (id, ver, nhash, tag) VALUES (?1, ?2, ?3, ?4)",
280 params![m.blob, m.ver, m.hash, m.tag],
281 ) {
282 Ok(c) => c,
283 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
284 };
285
286 return Ok(());
287 }
288
289 pub fn update_version_tag(&self, v: &Version, tag: &String) -> Result<(), Error> {
291 info!("Updating version tag '{}' -> '{}'", v.tag, tag);
292
293 let con = match Connection::open(&self.path) {
294 Ok(c) => c,
295 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
296 };
297
298 match con.execute(
300 "UPDATE versions SET tag=?1 WHERE owner = ?2 AND ver = ?3",
301 params![tag, v.owner, v.ver],
302 ) {
303 Ok(c) => c,
304 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
305 };
306
307 return Ok(());
308 }
309
310 pub fn update_subset(&self, blob: &String, subset: &String) -> Result<(), Error> {
312 info!("Updating blobs subset '{}'", subset);
313
314 let con = match Connection::open(&self.path) {
315 Ok(c) => c,
316 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
317 };
318
319 match con.execute(
321 "UPDATE configs SET subset=?1 WHERE id = ?2",
322 params![subset, blob],
323 ) {
324 Ok(c) => c,
325 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
326 };
327
328 return Ok(());
329 }
330
331 pub fn update_family(&self, blob: &String, family: &String) -> Result<(), Error> {
333 info!("Updating blobs family '{}'", family);
334
335 let con = match Connection::open(&self.path) {
336 Ok(c) => c,
337 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
338 };
339
340 match con.execute(
342 "UPDATE configs SET family=?1 WHERE id = ?2",
343 params![family, blob],
344 ) {
345 Ok(c) => c,
346 Err(e) => return Err(Error::SQLError { msg: e.to_string() }),
347 };
348
349 return Ok(());
350 }
351}