assembly_fdb/
sqlite.rs

1//! # SQLite conversions and tooling
2
3use std::fmt::Write;
4
5use rusqlite::params_from_iter;
6pub use rusqlite::{Connection, Error, Result};
7
8use super::mem::Database;
9
10/// Try to export a database to a SQL connection
11///
12/// This function does the following:
13///
14/// 1. `BEGIN`s a transaction
15/// 2. For every table:
16///   a. Run `CREATE TABLE IF NOT EXISTS`
17///   b. Prepares an `INSERT` statement
18///   c. Runs the insert with data from every row
19/// 3. `COMMIT`s the transaction
20pub fn try_export_db(conn: &mut Connection, db: Database) -> rusqlite::Result<()> {
21    conn.execute("BEGIN", rusqlite::params![])?;
22
23    let tables = db.tables().unwrap();
24    for table in tables.iter() {
25        let table = table.unwrap();
26        let mut create_query = format!("CREATE TABLE IF NOT EXISTS \"{}\"\n(\n", table.name());
27        let mut insert_query = format!("INSERT INTO \"{}\" (", table.name());
28        let mut first = true;
29        for col in table.column_iter() {
30            if first {
31                first = false;
32            } else {
33                writeln!(create_query, ",").unwrap();
34                write!(insert_query, ", ").unwrap();
35            }
36            let typ = col.value_type().to_sqlite_type();
37            write!(create_query, "    [{}] {}", col.name(), typ).unwrap();
38            write!(insert_query, "[{}]", col.name()).unwrap();
39        }
40        create_query.push_str(");");
41        insert_query.push_str(") VALUES (?1");
42        for i in 2..=table.column_count() {
43            write!(insert_query, ", ?{}", i).unwrap();
44        }
45        insert_query.push_str(");");
46        conn.execute(&create_query, rusqlite::params![])?;
47
48        let mut stmt = conn.prepare(&insert_query)?;
49        for row in table.row_iter() {
50            stmt.execute(params_from_iter(row.field_iter()))?;
51        }
52    }
53
54    conn.execute("COMMIT", rusqlite::params![])?;
55    Ok(())
56}