use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use crate::diff::SchemaDiff;
use crate::errors::Result;
use crate::snapshot::SchemaSnapshot;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MigrationPlan {
pub steps: Vec<MigrationStep>,
pub estimated_duration_secs: f64,
pub requires_downtime: bool,
pub warnings: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct MigrationStep {
pub step_number: usize,
pub operation: MigrationOperation,
pub description: String,
pub reversible: bool,
pub dependencies: Vec<usize>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum MigrationOperation {
CreateTable {
table_name: String,
columns: Vec<ColumnDefinition>,
primary_key: Option<PrimaryKeyDefinition>,
indexes: Vec<IndexDefinition>,
},
DropTable {
table_name: String,
},
AddColumn {
table_name: String,
column: ColumnDefinition,
},
DropColumn {
table_name: String,
column_name: String,
},
ModifyColumn {
table_name: String,
column_name: String,
changes: ColumnChanges,
},
AddForeignKey {
table_name: String,
constraint: ForeignKeyDefinition,
},
DropForeignKey {
table_name: String,
constraint_name: String,
},
AddUniqueConstraint {
table_name: String,
constraint: UniqueConstraintDefinition,
},
DropUniqueConstraint {
table_name: String,
constraint_name: String,
},
CreateIndex {
table_name: String,
index: IndexDefinition,
},
DropIndex {
table_name: String,
index_name: String,
},
AddCheckConstraint {
table_name: String,
constraint: CheckConstraintDefinition,
},
DropCheckConstraint {
table_name: String,
constraint_name: String,
},
CreateView {
view_name: String,
definition: String,
},
DropView {
view_name: String,
},
ModifyView {
view_name: String,
new_definition: String,
},
CreateFunction {
function_name: String,
signature: String,
body: String,
return_type: String,
},
DropFunction {
function_name: String,
signature: String,
},
CreateType {
type_name: String,
kind: String,
definition: String,
},
DropType {
type_name: String,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ColumnDefinition {
pub name: String,
pub data_type: String,
pub nullable: bool,
pub default_value: Option<String>,
pub auto_increment: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PrimaryKeyDefinition {
pub name: String,
pub columns: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ForeignKeyDefinition {
pub name: String,
pub columns: Vec<String>,
pub referenced_table: String,
pub referenced_columns: Vec<String>,
pub on_delete: Option<String>,
pub on_update: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UniqueConstraintDefinition {
pub name: String,
pub columns: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct IndexDefinition {
pub name: String,
pub columns: Vec<String>,
pub unique: bool,
pub index_type: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct CheckConstraintDefinition {
pub name: String,
pub expression: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ColumnChanges {
pub data_type: Option<TypeChange>,
pub nullable: Option<bool>,
pub default_value: Option<DefaultChange>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct TypeChange {
pub old_type: String,
pub new_type: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DefaultChange {
pub old_default: Option<String>,
pub new_default: Option<String>,
}
#[async_trait]
pub trait Planner: Send + Sync {
async fn create_plan(
&self,
current: &SchemaSnapshot,
target: &SchemaSnapshot,
diff: &SchemaDiff,
) -> Result<MigrationPlan>;
async fn validate_plan(&self, plan: &MigrationPlan) -> Result<()>;
}