Skip to content

Commit

Permalink
Write migrate bin.
Browse files Browse the repository at this point in the history
  • Loading branch information
kirkbyers committed Apr 14, 2024
1 parent 90a5d88 commit 82400b8
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 40 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ path = "src/bin/sm_scraper.rs"
name = "embed_scrapes"
path = "src/bin/embed_scrapes.rs"

[[bin]]
name = "migrate"
path = "src/bin/migrate.rs"

[dependencies]
actix-web = "4"
bytes = "1.5.0"
Expand Down
1 change: 1 addition & 0 deletions migrations/000_test.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT Count(*) from jobs;
1 change: 1 addition & 0 deletions migrations/001_test.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT Count(*) from jobs;
37 changes: 37 additions & 0 deletions src/bin/migrate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use std::{env, fs};

use zero2prod::{db, jobs};

#[tokio::main]
async fn main() {
let args: Vec<String> = env::args().collect();
assert!(args.len() > 1);

let db = db::start_db().await.unwrap();
let conn = db.connect().unwrap();

let current_dir = env::current_dir().unwrap();
for file_path in &args[1..] {
let mut migration_files: Vec<String> = vec![];
let path_res = current_dir.join(file_path);

if path_res.is_dir() {
for entry in fs::read_dir(path_res).unwrap() {
let entry = entry.unwrap();
let entry_path = entry.path();
if entry_path.is_file() {
migration_files.push(entry_path.to_str().unwrap().to_string())
}
}
} else {
migration_files.push(path_res.to_str().unwrap().to_string());
}

for migration_file in migration_files {
let file_content = fs::read_to_string(&migration_file).unwrap();
jobs::migrations::run_up(&conn, &migration_file, &file_content)
.await
.unwrap();
}
}
}
74 changes: 34 additions & 40 deletions src/jobs/migrations.rs
Original file line number Diff line number Diff line change
@@ -1,78 +1,72 @@
use libsql::{Connection, Error, Rows};
use libsql::{Connection, Error};

const MIGRATION_TABLE_NAME: &str = "migrations";

/// Sets up the migration table if it doesn't exist.
///
///
/// # Arguments
///
///
/// * `conn` - A reference to the database connection.
///
///
/// # Returns
///
///
/// Returns `Ok(())` if the setup is successful, otherwise returns an `Error`.
async fn setup(conn: &Connection) -> Result<(), Error> {
let table_exists_query = format!("SELECT to_regclass('{}');", MIGRATION_TABLE_NAME);
let mut rows: Rows = conn.query(&table_exists_query, ()).await?;
match rows.next().await? {
Some(_) => (),
None => {
conn.query(
&format!(
r#"
CREATE TABLE IF NOT EXISTS {} (
id uuid NOT NULL PRIMARY KEY,
title TEXT NOT NULL,
created_at TEXT
);
"#,
MIGRATION_TABLE_NAME
),
(),
)
.await?;
}
};
conn.query(
&format!(
r#"
CREATE TABLE IF NOT EXISTS {} (
id uuid NOT NULL PRIMARY KEY,
title TEXT NOT NULL,
created_at TEXT
);
"#,
MIGRATION_TABLE_NAME
),
(),
)
.await?;

Ok(())
}

/// Runs an "up" migration. Errors if migration with same title has been previously
/// Runs an "up" migration. Skip if migration with same title has been previously
/// ran.
///
///
/// # Arguments
///
///
/// * `conn` - A reference to the database connection.
/// * `title` - The title of the migration.
/// * `migration_sql` - The SQL statement for the migration.
///
///
/// # Returns
///
///
/// Returns `Ok(())` if the migration is successful, otherwise returns an `Error`.
pub async fn run_up(conn: &Connection, title: &str, migration_sql: &str) -> Result<(), Error> {
setup(conn).await?;
let existing_migration_query = format!(
"SELECT id FROM {} WHERE title = '{}';",
MIGRATION_TABLE_NAME,
title
MIGRATION_TABLE_NAME, title
);
let mut existing_migration_rows = conn.query(&existing_migration_query, ()).await?;
match existing_migration_rows.next().await? {
Some(_) => Err(Error::Misuse("Migration previously ran".to_string())),
Some(_) => {
println!("Skipping Migration '{}'", title);
Ok(())
}
None => {
println!("Running Migration '{}'", title);
conn.query(migration_sql, ()).await?;

let now = chrono::Utc::now().to_rfc3339();
let uuid = uuid::Uuid::new_v4();
let insert_ran_migration = format!(
"INSERT INTO {} (id, title, created_at) ('{}', '{}', '{}')",
MIGRATION_TABLE_NAME,
uuid,
title,
now
"INSERT INTO {} (id, title, created_at) VALUES ('{}', '{}', '{}');",
MIGRATION_TABLE_NAME, uuid, title, now
);
conn.query(&insert_ran_migration, ()).await?;
println!("Ran Migration '{}' Successfuly", title);
Ok(())
}
}
}
}

0 comments on commit 82400b8

Please sign in to comment.