1- use std:: collections:: HashMap ;
1+ use std:: collections:: { BTreeMap , HashMap } ;
22use std:: path:: Path ;
33
44use anyhow:: { Context , Result } ;
@@ -9,7 +9,10 @@ use serde_json::Value;
99use tokio:: fs;
1010use vespertide_config:: FileFormat ;
1111use vespertide_core:: { MigrationAction , MigrationPlan , TableConstraint , TableDef } ;
12- use vespertide_planner:: { find_missing_fill_with, plan_next_migration, schema_from_plans} ;
12+ use vespertide_planner:: {
13+ find_missing_enum_fill_with, find_missing_fill_with, plan_next_migration, schema_from_plans,
14+ EnumFillWithRequired ,
15+ } ;
1316
1417use crate :: utils:: {
1518 load_config, load_migrations, load_models, migration_filename_with_format_and_pattern,
@@ -226,6 +229,90 @@ where
226229 Ok ( ( ) )
227230}
228231
232+ /// Collect enum fill_with values interactively for removed enum values.
233+ /// The `enum_prompt_fn` parameter handles enum type columns with selection UI.
234+ fn collect_enum_fill_with_values < E > (
235+ missing : & [ EnumFillWithRequired ] ,
236+ enum_prompt_fn : E ,
237+ ) -> Result < Vec < ( usize , BTreeMap < String , String > ) > >
238+ where
239+ E : Fn ( & str , & [ String ] ) -> Result < String > ,
240+ {
241+ let mut results = Vec :: new ( ) ;
242+
243+ println ! (
244+ "\n {} {}" ,
245+ "\u{26a0} " . bright_yellow( ) ,
246+ "The following enum value removals require replacement mappings:" . bright_yellow( )
247+ ) ;
248+ println ! ( "{}" , "\u{2500} " . repeat( 60 ) . bright_black( ) ) ;
249+
250+ for item in missing {
251+ println ! (
252+ " {} {}.{}: removing enum values" ,
253+ "\u{2022} " . bright_cyan( ) ,
254+ item. table. bright_white( ) ,
255+ item. column. bright_green( )
256+ ) ;
257+
258+ let mut mappings = BTreeMap :: new ( ) ;
259+ for removed in & item. removed_values {
260+ let prompt = format ! (
261+ " Replace '{}' in {}.{} with" ,
262+ removed. bright_red( ) ,
263+ item. table. bright_white( ) ,
264+ item. column. bright_green( )
265+ ) ;
266+ let value = enum_prompt_fn ( & prompt, & item. remaining_values ) ?;
267+ mappings. insert ( removed. clone ( ) , value) ;
268+ }
269+ results. push ( ( item. action_index , mappings) ) ;
270+ }
271+
272+ println ! ( "{}" , "\u{2500} " . repeat( 60 ) . bright_black( ) ) ;
273+ Ok ( results)
274+ }
275+
276+ /// Apply collected enum fill_with mappings to the migration plan.
277+ fn apply_enum_fill_with_to_plan (
278+ plan : & mut MigrationPlan ,
279+ collected : & [ ( usize , BTreeMap < String , String > ) ] ,
280+ ) {
281+ for ( action_index, mappings) in collected {
282+ if let Some ( MigrationAction :: ModifyColumnType { fill_with, .. } ) =
283+ plan. actions . get_mut ( * action_index)
284+ {
285+ match fill_with {
286+ Some ( existing) => {
287+ existing. extend ( mappings. clone ( ) ) ;
288+ }
289+ None => {
290+ * fill_with = Some ( mappings. clone ( ) ) ;
291+ }
292+ }
293+ }
294+ }
295+ }
296+
297+ /// Handle interactive enum fill_with collection if there are missing values.
298+ fn handle_missing_enum_fill_with < E > (
299+ plan : & mut MigrationPlan ,
300+ current_schema : & [ TableDef ] ,
301+ enum_prompt_fn : E ,
302+ ) -> Result < ( ) >
303+ where
304+ E : Fn ( & str , & [ String ] ) -> Result < String > ,
305+ {
306+ let missing = find_missing_enum_fill_with ( plan, current_schema) ;
307+
308+ if !missing. is_empty ( ) {
309+ let collected = collect_enum_fill_with_values ( & missing, enum_prompt_fn) ?;
310+ apply_enum_fill_with_to_plan ( plan, & collected) ;
311+ }
312+
313+ Ok ( ( ) )
314+ }
315+
229316/// Check that no AddColumn action adds a non-nullable FK column without a default.
230317/// This is logically impossible: existing rows can't satisfy the FK constraint.
231318fn check_non_nullable_fk_add_columns ( plan : & MigrationPlan ) -> Result < ( ) > {
@@ -303,6 +390,9 @@ pub async fn cmd_revision(message: String, fill_with_args: Vec<String>) -> Resul
303390 prompt_enum_value,
304391 ) ?;
305392
393+ // Handle any missing enum fill_with values (for removed enum values) interactively
394+ handle_missing_enum_fill_with ( & mut plan, & baseline_schema, prompt_enum_value) ?;
395+
306396 plan. id = uuid:: Uuid :: new_v4 ( ) . to_string ( ) ;
307397 plan. comment = Some ( message) ;
308398 if plan. created_at . is_none ( ) {
0 commit comments