/ src / profile / proxy / misc / database.rs
database.rs
 1  mod row;
 2  
 3  use anyhow::Result;
 4  use r2d2::Pool;
 5  use r2d2_sqlite::SqliteConnectionManager;
 6  use row::Row;
 7  use sqlite::Transaction;
 8  
 9  pub struct Database {
10      pool: Pool<SqliteConnectionManager>,
11      profile_id: i64,
12  }
13  
14  impl Database {
15      // Constructors
16  
17      pub fn init(pool: &Pool<SqliteConnectionManager>, profile_id: i64) -> Self {
18          Self {
19              pool: pool.clone(),
20              profile_id,
21          }
22      }
23  
24      // Getters
25  
26      pub fn rows(&self) -> Result<Vec<Row>> {
27          rows(&self.pool.get()?.unchecked_transaction()?, self.profile_id)
28      }
29  
30      // Setters
31  
32      pub fn set(&self, (key, value): (String, String)) -> Result<i64> {
33          let mut c = self.pool.get()?;
34          let tx = c.transaction()?;
35          let id = set(&tx, self.profile_id, key, value)?;
36          tx.commit()?;
37          Ok(id)
38      }
39  }
40  
41  // Low-level DB API
42  
43  pub fn init(tx: &Transaction) -> Result<usize> {
44      Ok(tx.execute(
45          "CREATE TABLE IF NOT EXISTS `profile_proxy_misc`
46          (
47              `id`         INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
48              `profile_id` INTEGER NOT NULL,
49              `key`        VARCHAR(255) NOT NULL,
50              `value`      TEXT NULL,
51  
52              FOREIGN KEY (`profile_id`) REFERENCES `profile` (`id`),
53              UNIQUE (`key`)
54          )",
55          [],
56      )?)
57  }
58  
59  fn set(tx: &Transaction, profile_id: i64, key: String, value: String) -> Result<i64> {
60      tx.execute(
61          "INSERT INTO `profile_proxy_misc` (
62              `profile_id`,
63              `key`,
64              `value`
65          ) VALUES (?, ?, ?) ON CONFLICT (`key`) DO UPDATE SET `value` = `excluded`.`value`",
66          (profile_id, key, value),
67      )?;
68      Ok(tx.last_insert_rowid())
69  }
70  
71  fn rows(tx: &Transaction, profile_id: i64) -> Result<Vec<Row>> {
72      let mut stmt = tx.prepare(
73          "SELECT `id`,
74                  `profile_id`,
75                  `key`,
76                  `value`
77  
78                  FROM `profile_proxy_misc`
79                  WHERE `profile_id` = ?",
80      )?;
81  
82      let result = stmt.query_map([profile_id], |row| {
83          Ok(Row {
84              //id: row.get(0)?,
85              //profile_id: row.get(1)?,
86              key: row.get(2)?,
87              value: row.get(3)?,
88          })
89      })?;
90  
91      let mut rows = Vec::new();
92  
93      for r in result {
94          let row = r?;
95          rows.push(row);
96      }
97  
98      Ok(rows)
99  }