use crate::models::{TableSchema, Field, FieldMapping};
use anyhow::Result;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct SchemaComparison {
pub source_table: String,
pub target_table: String,
pub missing_fields: Vec<Field>,
pub extra_fields: Vec<Field>,
pub different_fields: Vec<(Field, Field)>,
pub suggested_mappings: Vec<FieldMapping>,
}
pub struct SchemaComparator {
}
impl SchemaComparator {
pub fn new() -> Self {
Self {}
}
pub fn compare(&self, source_schema: &TableSchema, target_schema: &TableSchema) -> Result<SchemaComparison> {
let mut missing_fields = vec![];
let mut extra_fields = vec![];
let mut different_fields = vec![];
let mut suggested_mappings = vec![];
let mut source_fields = std::collections::HashMap::new();
for field in &source_schema.fields {
source_fields.insert(field.name.clone(), field);
}
let mut target_fields = std::collections::HashMap::new();
for field in &target_schema.fields {
target_fields.insert(field.name.clone(), field);
}
for (name, field) in &source_fields {
if !target_fields.contains_key(name) {
missing_fields.push((*field).clone());
}
}
for (name, field) in &target_fields {
if !source_fields.contains_key(name) {
extra_fields.push((*field).clone());
}
}
for (name, source_field) in &source_fields {
if let Some(target_field) = target_fields.get(name) {
if source_field.data_type != target_field.data_type ||
source_field.length != target_field.length ||
source_field.nullable != target_field.nullable {
different_fields.push(((*source_field).clone(), (*target_field).clone()));
}
}
}
suggested_mappings = self.generate_suggested_mappings(source_schema, target_schema)?;
Ok(SchemaComparison {
source_table: source_schema.name.clone(),
target_table: target_schema.name.clone(),
missing_fields,
extra_fields,
different_fields,
suggested_mappings,
})
}
fn generate_suggested_mappings(&self, source_schema: &TableSchema, target_schema: &TableSchema) -> Result<Vec<FieldMapping>> {
let mut mappings = vec![];
for source_field in &source_schema.fields {
for target_field in &target_schema.fields {
if source_field.name == target_field.name {
mappings.push(FieldMapping {
source_table: source_schema.name.clone(),
source_field: source_field.name.clone(),
target_table: target_schema.name.clone(),
target_field: target_field.name.clone(),
});
break;
}
}
}
Ok(mappings)
}
}
pub struct FieldMapper {
}
impl FieldMapper {
pub fn new() -> Self {
Self {}
}
pub fn set_mapping(&self, _mappings: Vec<FieldMapping>) -> Result<()> {
Ok(())
}
pub fn load_mappings_from_file(&self, _file_path: &str) -> Result<Vec<FieldMapping>> {
Ok(vec![])
}
pub fn save_mappings_to_file(&self, _mappings: &[FieldMapping], _file_path: &str) -> Result<()> {
Ok(())
}
}