From aa60890b833898e6d52cd7d68d4662001234a119 Mon Sep 17 00:00:00 2001 From: Saurav Sharma Date: Mon, 18 Mar 2024 12:55:38 +0545 Subject: [PATCH] fix: check child run before before adding migration to list Signed-off-by: Saurav Sharma --- src/error.rs | 4 --- src/migrator/mod.rs | 40 +++++++---------------------- src/migrator/tests.rs | 59 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 62 insertions(+), 41 deletions(-) diff --git a/src/error.rs b/src/error.rs index 919a114a..ef991339 100644 --- a/src/error.rs +++ b/src/error.rs @@ -14,10 +14,6 @@ pub enum Error { /// Error for failed to create migrations plan #[error("failed to create migrations plan")] FailedToCreateMigrationPlan, - /// Error raised when order cannot be determine properly for replace and run - /// before - #[error("replace and run before migration order cannot be determined properly")] - ReplaceRunBeforeMisMatch, /// Parent is not applied #[error("children is applied before parent")] ParentIsNotApplied, diff --git a/src/migrator/mod.rs b/src/migrator/mod.rs index cd0b73db..cfae3ea8 100644 --- a/src/migrator/mod.rs +++ b/src/migrator/mod.rs @@ -501,36 +501,6 @@ where } } - // Hashmap which contains all children generated from run before list - let mut run_before_children = HashMap::<_, Vec<_>>::new(); - // in first loop add initial parent and child from parent due to run before - for (child, parents) in &parents_due_to_run_before { - for &parent in parents { - // since run before children is hash map we can have only one child occurrence - run_before_children.entry(parent).or_default().push(child); - } - } - // in second loop through recursive add all descendants - for (child, parents) in &parents_due_to_run_before { - for parent in parents { - populate_recursive(&mut run_before_children, parent, child); - } - } - - // check for inconsistent order of migration for replace and run before - for (parent_migration, children_vec) in &run_before_children { - for &child in children_vec { - let root = get_root(&parent_due_to_replaces, child); - if !children_vec.contains(&root) { - if let Some(replace_children_vec) = replace_children.get(root) { - if !replace_children_vec.contains(parent_migration) { - return Err(Error::ReplaceRunBeforeMisMatch); - } - } - } - } - } - let mut migration_list = Vec::new(); // Create migration list until migration list length is equal to hash set @@ -559,7 +529,15 @@ where child .parents() .iter() - .all(|child_parent| migration_list.contains(&child_parent)) + .all(|child_parent| migration_list.contains(&child_parent)); + parents_due_to_run_before + .get(child) + .unwrap_or(&vec![]) + .iter() + .all(|run_before_migration| { + migration_list.contains(run_before_migration) + || children.contains(run_before_migration) + }) }) }); if all_required_added { diff --git a/src/migrator/tests.rs b/src/migrator/tests.rs index 2a5a0ab1..04305a76 100644 --- a/src/migrator/tests.rs +++ b/src/migrator/tests.rs @@ -215,7 +215,7 @@ async fn replaces_multiple_times() { } #[tokio::test] -async fn replaces_run_before_mismatch_1() { +async fn replace_run_before_cond_1() { struct A; migration!(A, "a", vec_box!(), vec_box!(), vec_box!()); struct B; @@ -226,11 +226,11 @@ async fn replaces_run_before_mismatch_1() { migration!(D, "d", vec_box!(), vec_box!(), vec_box!(B)); let mut migrator = CustomMigrator::default(); let plan = generate_plan(&mut migrator, vec_box!(A, B, C, D)).await; - assert!(plan.is_err()); + assert!(plan.is_ok(), "{:?}", plan.err()); } #[tokio::test] -async fn replaces_run_before_mismatch_2() { +async fn replaces_run_before_cond_2() { struct A; migration!(A, "a", vec_box!(), vec_box!(), vec_box!()); struct B; @@ -243,11 +243,11 @@ async fn replaces_run_before_mismatch_2() { migration!(E, "e", vec_box!(), vec_box!(), vec_box!(C)); let mut migrator = CustomMigrator::default(); let plan = generate_plan(&mut migrator, vec_box!(A, B, C, D, E)).await; - assert!(plan.is_err()); + assert!(plan.is_ok(), "{:?}", plan.err()); } #[tokio::test] -async fn replaces_run_before_ok_1() { +async fn replaces_run_before_cond_3() { struct A; migration!(A, "a", vec_box!(), vec_box!(), vec_box!()); struct B; @@ -264,7 +264,7 @@ async fn replaces_run_before_ok_1() { } #[tokio::test] -async fn replaces_run_before_ok_2() { +async fn replaces_run_before_cond_4() { struct A; migration!(A, "a", vec_box!(), vec_box!(), vec_box!()); struct B; @@ -280,6 +280,53 @@ async fn replaces_run_before_ok_2() { assert!(plan.is_ok(), "{:?}", plan.err()); } +#[tokio::test] +async fn replaces_run_before_cond_5() { + struct A; + migration!(A, "a", vec_box!(), vec_box!(), vec_box!()); + struct B; + migration!(B, "b", vec_box!(A), vec_box!(), vec_box!()); + struct C; + migration!(C, "c", vec_box!(), vec_box!(B), vec_box!()); + struct D; + migration!(D, "d", vec_box!(), vec_box!(C), vec_box!(C)); + let mut migrator = CustomMigrator::default(); + let plan = generate_plan(&mut migrator, vec_box!(A, B, C, D)).await; + assert!(plan.is_err()); +} + +#[tokio::test] +async fn replaces_run_before_cond_6() { + struct A; + migration!(A, "a", vec_box!(), vec_box!(), vec_box!()); + struct B; + migration!(B, "b", vec_box!(A), vec_box!(), vec_box!()); + struct C; + migration!(C, "c", vec_box!(), vec_box!(B), vec_box!()); + struct D; + migration!(D, "d", vec_box!(), vec_box!(C, E), vec_box!()); + struct E; + migration!(E, "e", vec_box!(), vec_box!(D), vec_box!(C)); + let mut migrator = CustomMigrator::default(); + let plan = generate_plan(&mut migrator, vec_box!(A, B, C, D, E)).await; + assert!(plan.is_err()); +} + +#[tokio::test] +async fn replaces_run_before_cond_7() { + struct A; + migration!(A, "a", vec_box!(), vec_box!(), vec_box!()); + struct B; + migration!(B, "b", vec_box!(A), vec_box!(), vec_box!()); + struct C; + migration!(C, "c", vec_box!(), vec_box!(B), vec_box!(D)); + struct D; + migration!(D, "d", vec_box!(), vec_box!(C), vec_box!()); + let mut migrator = CustomMigrator::default(); + let plan = generate_plan(&mut migrator, vec_box!(A, B, C, D)).await; + assert!(plan.is_err()); +} + #[tokio::test] async fn loop_error() { struct A;