Skip to main content

trailbase_refinery/drivers/
rusqlite.rs

1use crate::Migration;
2use crate::traits::sync::{Migrate, Query, Transaction};
3use rusqlite::{Connection as RqlConnection, Error as RqlError};
4use time::OffsetDateTime;
5use time::format_description::well_known::Rfc3339;
6
7fn query_applied_migrations(
8  transaction: &RqlConnection,
9  query: &str,
10) -> Result<Vec<Migration>, RqlError> {
11  let mut stmt = transaction.prepare(query)?;
12  let mut rows = stmt.query([])?;
13  let mut applied = Vec::new();
14  while let Some(row) = rows.next()? {
15    let version = row.get(0)?;
16    let applied_on: String = row.get(2)?;
17    // Safe to call unwrap, as we stored it in RFC3339 format on the database
18    let applied_on = OffsetDateTime::parse(&applied_on, &Rfc3339).unwrap();
19
20    let checksum: String = row.get(3)?;
21    applied.push(Migration::applied(
22      version,
23      row.get(1)?,
24      applied_on,
25      checksum
26        .parse::<u64>()
27        .expect("checksum must be a valid u64"),
28    ));
29  }
30  Ok(applied)
31}
32
33impl Transaction for RqlConnection {
34  type Error = RqlError;
35  fn execute<'a, T: Iterator<Item = &'a str>>(&mut self, queries: T) -> Result<usize, Self::Error> {
36    let transaction = self.transaction()?;
37    let mut count = 0;
38    for query in queries {
39      transaction.execute_batch(query)?;
40      count += 1;
41    }
42    transaction.commit()?;
43    Ok(count)
44  }
45}
46
47impl Query<Vec<Migration>> for RqlConnection {
48  fn query(&mut self, query: &str) -> Result<Vec<Migration>, Self::Error> {
49    let transaction = self.transaction()?;
50    let applied = query_applied_migrations(&transaction, query)?;
51    transaction.commit()?;
52    Ok(applied)
53  }
54}
55
56impl Migrate for RqlConnection {}