use colored::{ColoredString, Colorize};
use std::fmt::Display;
use crate::diff::diff_output::DiffOutput;
use crate::diff::types::DiffOutputMarker;
use std::time::Duration;
#[cfg_attr(test, derive(PartialEq))]
#[derive(Debug, Clone)]
pub enum TableSource {
First,
Second,
}
impl Display for TableSource {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::First => write!(f, "first"),
Self::Second => write!(f, "second"),
}
}
}
#[cfg_attr(test, derive(PartialEq))]
#[derive(Debug, Clone)]
pub struct TableCountDiff(i64, i64);
impl TableCountDiff {
pub fn new(first: i64, second: i64) -> Self {
Self(first, second)
}
pub fn first(&self) -> i64 {
self.0
}
pub fn second(&self) -> i64 {
self.1
}
}
#[cfg_attr(test, derive(PartialEq))]
#[derive(Debug, Clone)]
pub enum TableDiffOutput {
NoCountDiff(String, i64),
NoDiffWithDuration(String, Duration),
NotExists(String, TableSource),
Diff(String, TableCountDiff),
NoPrimaryKeyFound(String),
DataDiffWithDuration(String, i64, i64, Duration),
}
impl TableDiffOutput {
pub fn skip_table_diff(&self) -> bool {
matches!(self, Self::Diff(_, _) | Self::NotExists(_, _))
}
pub fn to_string(&self) -> ColoredString {
match self {
Self::NoCountDiff(table, count) => {
format!("{} - No difference. Total rows: {}", table, count)
.green()
.bold()
}
Self::NotExists(table, source) => format!("{} - Does not exist in {}", table, source)
.red()
.bold()
.underline(),
Self::Diff(table, diffs) => format!(
"{} - First table rows: {}, Second table rows: {}",
table,
diffs.first(),
diffs.second()
)
.red()
.bold(),
TableDiffOutput::NoPrimaryKeyFound(table) => {
format!("{} - No primary key found", table).red().bold()
}
TableDiffOutput::NoDiffWithDuration(table, duration) => {
format!("{} - No difference in {}ms", table, duration.as_millis())
.green()
.bold()
}
TableDiffOutput::DataDiffWithDuration(table_name, position, offset, duration) => {
format!(
"{} - Data diff between rows [{},{}] - in {}ms",
table_name,
position,
offset,
duration.as_millis()
)
.red()
.bold()
}
}
}
}
impl DiffOutputMarker for TableDiffOutput {
fn convert(self) -> DiffOutput {
DiffOutput::TableDiff(self.clone())
}
}
impl From<TableDiffOutput> for DiffOutput {
fn from(val: TableDiffOutput) -> Self {
DiffOutput::TableDiff(val)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_skip_table_when_needed() {
let no_count_diff = TableDiffOutput::NoCountDiff("test".to_string(), 1000);
let not_exists = TableDiffOutput::NotExists("test".to_string(), TableSource::First);
let diff = TableDiffOutput::Diff("test".to_string(), TableCountDiff::new(1, 2));
let no_primary_key = TableDiffOutput::NoPrimaryKeyFound("test".to_string());
let no_diff_with_duration =
TableDiffOutput::NoDiffWithDuration("test".to_string(), Duration::from_millis(1));
let data_diff_with_duration = TableDiffOutput::DataDiffWithDuration(
"test".to_string(),
1,
2,
Duration::from_millis(1),
);
assert!(not_exists.skip_table_diff());
assert!(diff.skip_table_diff());
assert!(!no_count_diff.skip_table_diff());
assert!(!no_primary_key.skip_table_diff());
assert!(!no_diff_with_duration.skip_table_diff());
assert!(!data_diff_with_duration.skip_table_diff());
}
}