diff --git a/migration-engine/connectors/migration-connector/src/lib.rs b/migration-engine/connectors/migration-connector/src/lib.rs index 1d9b8d0a3925..6b44912ebc69 100644 --- a/migration-engine/connectors/migration-connector/src/lib.rs +++ b/migration-engine/connectors/migration-connector/src/lib.rs @@ -93,11 +93,17 @@ fn checksum(script: &str) -> String { checksum.format_checksum() } +/// The length (in bytes, or equivalently ascii characters) of the checksum +/// strings. +const CHECKSUM_STR_LEN: usize = 64; + /// Format a checksum to a hexadecimal string. This is used to checksum /// migration scripts with Sha256. pub trait FormatChecksum { /// Format a checksum to a hexadecimal string. fn format_checksum(&self) -> String; + /// Obsolete checksum method, should only be used for compatibility. + fn format_checksum_old(&self) -> String; } impl FormatChecksum for [u8; 32] { @@ -106,6 +112,26 @@ impl FormatChecksum for [u8; 32] { let mut checksum_string = String::with_capacity(32 * 2); + for byte in self { + write!(checksum_string, "{:02x}", byte).unwrap(); + } + + assert_eq!(checksum_string.len(), CHECKSUM_STR_LEN); + + checksum_string + } + + // Due to an omission in a previous version of the migration engine, + // some migrations tables will have old migrations with checksum strings + // that have not been zero-padded. + // + // Corresponding issue: + // https://github.com/prisma/prisma-engines/issues/1887 + fn format_checksum_old(&self) -> String { + use std::fmt::Write as _; + + let mut checksum_string = String::with_capacity(32 * 2); + for byte in self { write!(checksum_string, "{:x}", byte).unwrap(); } @@ -113,3 +139,14 @@ impl FormatChecksum for [u8; 32] { checksum_string } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn format_checksum_does_not_strip_zeros() { + assert_eq!(checksum("hello"), "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"); + assert_eq!(checksum("abcd").len(), CHECKSUM_STR_LEN); + } +} \ No newline at end of file diff --git a/migration-engine/connectors/migration-connector/src/migrations_directory.rs b/migration-engine/connectors/migration-connector/src/migrations_directory.rs index 5417e8f70517..7d69a9365ad6 100644 --- a/migration-engine/connectors/migration-connector/src/migrations_directory.rs +++ b/migration-engine/connectors/migration-connector/src/migrations_directory.rs @@ -5,7 +5,7 @@ //! It also contains multiple subfolders, named after the migration id, and each containing: //! - A migration script -use crate::{ConnectorError, ConnectorResult, FormatChecksum}; +use crate::{CHECKSUM_STR_LEN, ConnectorError, ConnectorResult, FormatChecksum}; use sha2::{Digest, Sha256, Sha512}; use std::{ error::Error, @@ -221,7 +221,19 @@ impl MigrationDirectory { hasher.update(&filesystem_script); let filesystem_script_checksum: [u8; 32] = hasher.finalize().into(); - Ok(checksum_str == filesystem_script_checksum.format_checksum()) + // Due to an omission in a previous version of the migration engine, + // some migrations tables will have old migrations with checksum strings + // that have not been zero-padded. + // + // Corresponding issue: + // https://github.com/prisma/prisma-engines/issues/1887 + let filesystem_script_checksum_str = if checksum_str.len() > 0 && checksum_str.len() != CHECKSUM_STR_LEN { + filesystem_script_checksum.format_checksum_old() + } else { + filesystem_script_checksum.format_checksum() + }; + + Ok(checksum_str == filesystem_script_checksum_str) } /// Write the migration script to the directory.