use sha2::{Digest, Sha384};
use std::borrow::Cow;
use crate::sql_str::SqlStr;
use super::MigrationType;
#[derive(Debug, Clone)]
pub struct Migration {
pub version: i64,
pub description: Cow<'static, str>,
pub migration_type: MigrationType,
pub sql: SqlStr,
pub checksum: Cow<'static, [u8]>,
pub no_tx: bool,
}
impl Migration {
pub fn new(
version: i64,
description: Cow<'static, str>,
migration_type: MigrationType,
sql: SqlStr,
no_tx: bool,
) -> Self {
let checksum = checksum(sql.as_str());
Self::with_checksum(
version,
description,
migration_type,
sql,
checksum.into(),
no_tx,
)
}
pub(crate) fn with_checksum(
version: i64,
description: Cow<'static, str>,
migration_type: MigrationType,
sql: SqlStr,
checksum: Cow<'static, [u8]>,
no_tx: bool,
) -> Self {
Migration {
version,
description,
migration_type,
sql,
checksum,
no_tx,
}
}
}
#[derive(Debug, Clone)]
pub struct AppliedMigration {
pub version: i64,
pub checksum: Cow<'static, [u8]>,
}
pub fn checksum(sql: &str) -> Vec<u8> {
Vec::from(Sha384::digest(sql).as_slice())
}
pub fn checksum_fragments<'a>(fragments: impl Iterator<Item = &'a str>) -> Vec<u8> {
let mut digest = Sha384::new();
for fragment in fragments {
digest.update(fragment);
}
digest.finalize().to_vec()
}
#[test]
fn fragments_checksum_equals_full_checksum() {
let sql = "\
\u{FEFF}create table comment (\r\n\
\tcomment_id uuid primary key default gen_random_uuid(),\r\n\
\tpost_id uuid not null references post(post_id),\r\n\
\tuser_id uuid not null references \"user\"(user_id),\r\n\
\tcontent text not null,\r\n\
\tcreated_at timestamptz not null default now()\r\n\
);\r\n\
\r\n\
create index on comment(post_id, created_at);\r\n\
";
let fragments_checksum = checksum_fragments(sql.split(""));
let full_checksum = checksum(sql);
assert_eq!(fragments_checksum, full_checksum);
}