rusty_schema_diff/
migration.rs

1//! Migration plan generation and management
2//!
3//! This module provides types and functionality for generating and managing
4//! schema migration plans.
5
6use serde::{Serialize, Deserialize};
7use crate::analyzer::SchemaChange;
8
9/// Represents a plan for migrating between schema versions
10///
11/// A migration plan contains all the necessary changes required to evolve
12/// from one schema version to another, along with impact analysis.
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct MigrationPlan {
15    /// Version of the source schema
16    pub source_version: String,
17    
18    /// Version of the target schema
19    pub target_version: String,
20    
21    /// List of changes required for migration
22    pub changes: Vec<SchemaChange>,
23    
24    /// Impact score (0-100) indicating the magnitude of changes
25    pub impact_score: u8,
26    
27    /// Indicates whether this migration contains breaking changes
28    pub is_breaking: bool,
29}
30
31impl MigrationPlan {
32    /// Creates a new migration plan
33    ///
34    /// # Arguments
35    /// * `source_version` - Version identifier of the source schema
36    /// * `target_version` - Version identifier of the target schema
37    /// * `changes` - List of schema changes required for migration
38    ///
39    /// # Returns
40    /// A new MigrationPlan instance with calculated impact scores
41    pub fn new(source_version: String, target_version: String, changes: Vec<SchemaChange>) -> Self {
42        let impact_score = Self::calculate_impact(&changes);
43        let is_breaking = Self::detect_breaking_changes(&changes);
44
45        Self {
46            source_version,
47            target_version,
48            changes,
49            impact_score,
50            is_breaking,
51        }
52    }
53
54    /// Calculates the impact score of the migration
55    ///
56    /// # Arguments
57    /// * `changes` - List of schema changes to analyze
58    ///
59    /// # Returns
60    /// An impact score between 0 and 100
61    fn calculate_impact(changes: &[SchemaChange]) -> u8 {
62        // Simple scoring algorithm
63        let score = changes.iter().map(|change| match change.change_type {
64            crate::analyzer::ChangeType::Addition => 25,
65            crate::analyzer::ChangeType::Removal => 100,
66            crate::analyzer::ChangeType::Modification => 50,
67            crate::analyzer::ChangeType::Rename => 30,
68        }).max().unwrap_or(0);
69
70        score.min(100) as u8
71    }
72
73    /// Detects if the migration contains breaking changes
74    ///
75    /// # Arguments
76    /// * `changes` - List of schema changes to analyze
77    ///
78    /// # Returns
79    /// true if breaking changes are detected, false otherwise
80    fn detect_breaking_changes(changes: &[SchemaChange]) -> bool {
81        changes.iter().any(|change| matches!(
82            change.change_type,
83            crate::analyzer::ChangeType::Removal | crate::analyzer::ChangeType::Modification
84        ))
85    }
86
87    /// Gets a list of breaking changes in the migration plan
88    ///
89    /// # Returns
90    /// A vector of references to breaking changes
91    pub fn breaking_changes(&self) -> Vec<&SchemaChange> {
92        self.changes.iter()
93            .filter(|change| matches!(
94                change.change_type,
95                crate::analyzer::ChangeType::Removal | crate::analyzer::ChangeType::Modification
96            ))
97            .collect()
98    }
99}