| 46 | } |
| 47 | |
| 48 | pub fn format_report(&self) -> String { |
| 49 | let mut report = String::new(); |
| 50 | |
| 51 | for drift in &self.table_drifts { |
| 52 | report.push_str(&format!("\nTable '{}' has schema drift:\n", drift.table_name)); |
| 53 | |
| 54 | if !drift.missing_in_sqlite.is_empty() { |
| 55 | report.push_str(" Columns in metadata but missing from SQLite:\n"); |
| 56 | for col in &drift.missing_in_sqlite { |
| 57 | report.push_str(&format!(" - {} ({})\n", col.name, col.pg_type)); |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | if !drift.missing_in_metadata.is_empty() { |
| 62 | report.push_str(" Columns in SQLite but missing from metadata:\n"); |
| 63 | for col in &drift.missing_in_metadata { |
| 64 | report.push_str(&format!(" - {} ({})\n", col.name, col.sqlite_type)); |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | if !drift.type_mismatches.is_empty() { |
| 69 | report.push_str(" Type mismatches:\n"); |
| 70 | for mismatch in &drift.type_mismatches { |
| 71 | report.push_str(&format!( |
| 72 | " - {} expected SQLite type '{}' but found '{}'\n", |
| 73 | mismatch.column_name, |
| 74 | mismatch.metadata_sqlite_type, |
| 75 | mismatch.actual_sqlite_type |
| 76 | )); |
| 77 | } |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | report |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | pub struct SchemaDriftDetector; |