/ src / profile / proxy / ignore / 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 clean(&self, keep_id: Vec<i64>) -> Result<()> {
 33          let mut c = self.pool.get()?;
 34          let tx = c.transaction()?;
 35          clean(&tx, keep_id)?;
 36          tx.commit()?;
 37          Ok(())
 38      }
 39  
 40      pub fn persist(
 41          &self,
 42          id: Option<i64>,
 43          time: i64,
 44          is_enabled: bool,
 45          host: String,
 46      ) -> Result<i64> {
 47          let mut c = self.pool.get()?;
 48          let tx = c.transaction()?;
 49          let id = match id {
 50              Some(id) => {
 51                  update(&tx, id, time, is_enabled, host)?;
 52                  id
 53              }
 54              None => insert(&tx, self.profile_id, time, is_enabled, host)?,
 55          };
 56          tx.commit()?;
 57          Ok(id)
 58      }
 59  }
 60  
 61  // Low-level DB API
 62  
 63  pub fn init(tx: &Transaction) -> Result<usize> {
 64      Ok(tx.execute(
 65          "CREATE TABLE IF NOT EXISTS `profile_proxy_ignore`
 66          (
 67              `id`         INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
 68              `profile_id` INTEGER NOT NULL,
 69              `time`       INTEGER NOT NULL,
 70              `is_enabled` INTEGER NOT NULL,
 71              `host`       VARCHAR(255) NOT NULL,
 72  
 73              FOREIGN KEY (`profile_id`) REFERENCES `profile` (`id`)
 74          )",
 75          [],
 76      )?)
 77  }
 78  
 79  fn clean(tx: &Transaction, keep_id: Vec<i64>) -> Result<usize> {
 80      if keep_id.is_empty() {
 81          return Ok(0);
 82      }
 83      Ok(tx.execute(
 84          &format!(
 85              "DELETE FROM `profile_proxy_ignore` WHERE `id` NOT IN ({})",
 86              keep_id
 87                  .into_iter()
 88                  .map(|id| id.to_string())
 89                  .collect::<Vec<String>>()
 90                  .join(",")
 91          ),
 92          [],
 93      )?)
 94  }
 95  
 96  fn insert(
 97      tx: &Transaction,
 98      profile_id: i64,
 99      time: i64,
100      is_enabled: bool,
101      host: String,
102  ) -> Result<i64> {
103      tx.execute(
104          "INSERT INTO `profile_proxy_ignore` (
105              `profile_id`,
106              `time`,
107              `is_enabled`,
108              `host`
109          ) VALUES (?, ?, ?, ?)",
110          (profile_id, time, is_enabled, host),
111      )?;
112      Ok(tx.last_insert_rowid())
113  }
114  
115  fn update(tx: &Transaction, id: i64, time: i64, is_enabled: bool, host: String) -> Result<usize> {
116      Ok(tx.execute(
117          "UPDATE `profile_proxy_ignore`
118              SET `time` = ?,
119                  `is_enabled` = ?,
120                  `host` = ?
121  
122              WHERE `id` = ?",
123          (time, is_enabled, host, id),
124      )?)
125  }
126  
127  fn rows(tx: &Transaction, profile_id: i64) -> Result<Vec<Row>> {
128      let mut stmt = tx.prepare(
129          "SELECT `id`,
130                  `profile_id`,
131                  `time`,
132                  `host`,
133                  `is_enabled`
134  
135                  FROM `profile_proxy_ignore`
136                  WHERE `profile_id` = ?",
137      )?;
138  
139      let result = stmt.query_map([profile_id], |row| {
140          Ok(Row {
141              id: row.get(0)?,
142              //profile_id: row.get(1)?,
143              time: row.get(2)?,
144              host: row.get(3)?,
145              is_enabled: row.get(4)?,
146          })
147      })?;
148  
149      let mut rows = Vec::new();
150  
151      for r in result {
152          let row = r?;
153          rows.push(row);
154      }
155  
156      Ok(rows)
157  }