Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

44 linesCodeBlameRaw
1//! The events database as the migrations make it, for tests: SQLite (which
2//! D1 is), each migration in a transaction of its own as D1 applies it.
3
4use rusqlite::Connection;
5
6/// The migrations, in order: each file's name and SQL.
7pub(crate) fn migrations() -> Vec<(String, String)> {
8 let dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("migrations");
9 let mut names: Vec<String> = std::fs::read_dir(&dir)
10 .unwrap()
11 .map(|entry| entry.unwrap().file_name().into_string().unwrap())
12 .filter(|name| name.ends_with(".sql"))
13 .collect();
14 names.sort();
15 names.into_iter().map(|name| (name.clone(), std::fs::read_to_string(dir.join(&name)).unwrap())).collect()
16}
17
18/// Applies one migration as D1 does: in one transaction.
19pub(crate) fn apply(db: &Connection, name: &str, sql: &str) {
20 db.execute_batch(&format!("BEGIN;\n{sql}\nCOMMIT;")).unwrap_or_else(|error| panic!("{name}: {error}"));
21}
22
23/// An in-memory database with the migrations before `name` applied, for
24/// filling with what that migration then moves.
25pub(crate) fn database_before(name: &str) -> Connection {
26 let db = Connection::open_in_memory().unwrap();
27 db.execute_batch("PRAGMA foreign_keys = ON;").unwrap();
28 for (file, sql) in migrations() {
29 if file.as_str() >= name {
30 break;
31 }
32 apply(&db, &file, &sql);
33 }
34 db
35}
36
37/// Applies the migrations from `name` on.
38pub(crate) fn migrate_from(db: &Connection, name: &str) {
39 for (file, sql) in migrations() {
40 if file.as_str() >= name {
41 apply(db, &file, &sql);
42 }
43 }
44}