use super::{exec, sql, DIRECTION_DOWN, DIRECTION_UP};
use crate::database::migrations::{CustomMigrationError, MigrationDirection};
use crate::database::DatabaseConnection;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Provenance {
Executed,
Baselined,
}
impl Provenance {
pub fn label(self) -> &'static str {
match self {
Self::Executed => "executed",
Self::Baselined => "baselined",
}
}
}
pub fn direction_label(direction: MigrationDirection) -> &'static str {
match direction {
MigrationDirection::Up => DIRECTION_UP,
MigrationDirection::Down => DIRECTION_DOWN,
}
}
pub async fn record(
connection: &DatabaseConnection,
migration_name: &str,
direction: MigrationDirection,
) -> Result<(), CustomMigrationError> {
record_with_metadata(
connection,
migration_name,
direction,
Provenance::Executed,
None,
)
.await
}
pub async fn record_with_metadata(
connection: &DatabaseConnection,
migration_name: &str,
direction: MigrationDirection,
provenance: Provenance,
checksum: Option<&str>,
) -> Result<(), CustomMigrationError> {
let binds = [
migration_name,
direction_label(direction),
provenance.label(),
checksum.unwrap_or(""),
];
if exec::execute(connection, sql::upsert(connection), &binds)
.await
.is_err()
{
exec::execute(connection, sql::plain_insert(connection), &binds).await?;
}
clear_opposite(connection, migration_name, direction).await
}
async fn clear_opposite(
connection: &DatabaseConnection,
migration_name: &str,
direction: MigrationDirection,
) -> Result<(), CustomMigrationError> {
let opposite = match direction {
MigrationDirection::Up => DIRECTION_DOWN,
MigrationDirection::Down => DIRECTION_UP,
};
exec::execute(
connection,
sql::delete_direction(connection),
&[migration_name, opposite],
)
.await
}