|
| 1 | +// SPDX-License-Identifier: Apache-2.0 |
| 2 | + |
| 3 | +package migrations |
| 4 | + |
| 5 | +import ( |
| 6 | + "testing" |
| 7 | + |
| 8 | + "github.com/stretchr/testify/require" |
| 9 | + "github.com/xataio/pgroll/pkg/backfill" |
| 10 | + "github.com/xataio/pgroll/pkg/schema" |
| 11 | +) |
| 12 | + |
| 13 | +func TestCoordinator(t *testing.T) { |
| 14 | + type testCase map[string]struct { |
| 15 | + actions []DBAction |
| 16 | + expectedOrder []string |
| 17 | + } |
| 18 | + |
| 19 | + testCases := testCase{ |
| 20 | + "empty": { |
| 21 | + actions: []DBAction{}, |
| 22 | + expectedOrder: []string{}, |
| 23 | + }, |
| 24 | + "single action": { |
| 25 | + actions: []DBAction{ |
| 26 | + NewRenameDuplicatedColumnAction(nil, &schema.Table{Name: "t1"}, "column1"), |
| 27 | + }, |
| 28 | + expectedOrder: []string{"rename_duplicated_t1_column1"}, |
| 29 | + }, |
| 30 | + "multiple actions with duplicates": { |
| 31 | + actions: []DBAction{ |
| 32 | + NewRenameDuplicatedColumnAction(nil, &schema.Table{Name: "t1"}, "column1"), |
| 33 | + NewRenameDuplicatedColumnAction(nil, &schema.Table{Name: "t1"}, "column2"), |
| 34 | + NewRenameDuplicatedColumnAction(nil, &schema.Table{Name: "t1"}, "column1"), // Duplicate |
| 35 | + }, |
| 36 | + expectedOrder: []string{"rename_duplicated_t1_column2", "rename_duplicated_t1_column1"}, |
| 37 | + }, |
| 38 | + "multiple actions with mutiple duplicated for renaming": { |
| 39 | + actions: []DBAction{ |
| 40 | + NewDropColumnAction(nil, "t1", "column1"), |
| 41 | + NewRenameDuplicatedColumnAction(nil, &schema.Table{Name: "t1"}, "column1"), |
| 42 | + NewDropColumnAction(nil, "t1", "column2"), |
| 43 | + NewRenameDuplicatedColumnAction(nil, &schema.Table{Name: "t1"}, "column2"), |
| 44 | + NewDropColumnAction(nil, "t1", "column3"), |
| 45 | + NewRenameDuplicatedColumnAction(nil, &schema.Table{Name: "t1"}, "column3"), |
| 46 | + NewDropColumnAction(nil, "t1", "column1"), |
| 47 | + NewRenameDuplicatedColumnAction(nil, &schema.Table{Name: "t1"}, "column1"), |
| 48 | + NewDropColumnAction(nil, "t1", "column2"), |
| 49 | + NewRenameDuplicatedColumnAction(nil, &schema.Table{Name: "t1"}, "column2"), |
| 50 | + }, |
| 51 | + expectedOrder: []string{ |
| 52 | + "drop_column_t1_column3", |
| 53 | + "rename_duplicated_t1_column3", |
| 54 | + "drop_column_t1_column1", |
| 55 | + "rename_duplicated_t1_column1", |
| 56 | + "drop_column_t1_column2", |
| 57 | + "rename_duplicated_t1_column2", |
| 58 | + }, |
| 59 | + }, |
| 60 | + "add same column multiple times to same table": { |
| 61 | + actions: []DBAction{ |
| 62 | + NewCreateTableAction(nil, "test_table", "", ""), |
| 63 | + NewAddColumnAction(nil, "t1", Column{Name: "column1"}, false), |
| 64 | + NewAddColumnAction(nil, "t1", Column{Name: "column1"}, false), // Duplicate |
| 65 | + }, |
| 66 | + expectedOrder: []string{"create_table_test_table", "add_column_t1_column1"}, |
| 67 | + }, |
| 68 | + "create table multiple time with different statement with the same name": { |
| 69 | + actions: []DBAction{ |
| 70 | + NewCreateTableAction(nil, "test_table", "", ""), |
| 71 | + NewCreateTableAction(nil, "test_table", "id INT", ""), |
| 72 | + NewCommentTableAction(nil, "test_table", ptr("This is a test table")), |
| 73 | + NewCommentColumnAction(nil, "test_table", "id", ptr("This is a test column")), |
| 74 | + }, |
| 75 | + expectedOrder: []string{"create_table_test_table", "comment_table_test_table", "comment_column_test_table_id"}, |
| 76 | + }, |
| 77 | + "drop default value on column": { |
| 78 | + actions: []DBAction{ |
| 79 | + NewCreateTableAction(nil, "test_table", "", ""), |
| 80 | + NewAddColumnAction(nil, "test_table1", Column{Name: "column1", Default: ptr("default_value")}, false), |
| 81 | + NewDropDefaultValueAction(nil, "test_table", "column1"), |
| 82 | + }, |
| 83 | + expectedOrder: []string{"create_table_test_table", "add_column_test_table1_column1", "drop_default_test_table_column1"}, |
| 84 | + }, |
| 85 | + "alter column multiple times rollback phase": { |
| 86 | + actions: []DBAction{ |
| 87 | + NewDropColumnAction(nil, "t1", "column1"), |
| 88 | + NewDropFunctionAction(nil, |
| 89 | + backfill.TriggerFunctionName("t1", "column1"), |
| 90 | + backfill.TriggerFunctionName("t1", "__pgroll_new_column1"), |
| 91 | + ), |
| 92 | + NewDropColumnAction(nil, "t1", backfill.CNeedsBackfillColumn), |
| 93 | + NewDropColumnAction(nil, "t1", "column1"), |
| 94 | + NewDropFunctionAction(nil, |
| 95 | + backfill.TriggerFunctionName("t1", "column1"), |
| 96 | + backfill.TriggerFunctionName("t1", "__pgroll_new_column1"), |
| 97 | + ), |
| 98 | + NewDropColumnAction(nil, "t1", backfill.CNeedsBackfillColumn), |
| 99 | + }, |
| 100 | + expectedOrder: []string{ |
| 101 | + "drop_column_t1_column1", |
| 102 | + "drop_function__pgroll_trigger_t1_column1__pgroll_trigger_t1___pgroll_new_column1", |
| 103 | + "drop_column_t1_" + backfill.CNeedsBackfillColumn, |
| 104 | + }, |
| 105 | + }, |
| 106 | + "alter column multiple times complete phase": { |
| 107 | + actions: []DBAction{ |
| 108 | + NewAlterSequenceOwnerAction(nil, "t1", "column1", TemporaryName("column1")), |
| 109 | + NewDropColumnAction(nil, "t1", "column1"), |
| 110 | + NewDropFunctionAction(nil, |
| 111 | + backfill.TriggerFunctionName("t1", "column1"), |
| 112 | + backfill.TriggerFunctionName("t1", TemporaryName("column1")), |
| 113 | + ), |
| 114 | + NewDropColumnAction(nil, "t1", backfill.CNeedsBackfillColumn), |
| 115 | + NewRenameDuplicatedColumnAction(nil, &schema.Table{Name: "t1"}, "column1"), |
| 116 | + NewAlterSequenceOwnerAction(nil, "t1", "column1", TemporaryName("column1")), |
| 117 | + NewDropColumnAction(nil, "t1", "column1"), |
| 118 | + NewDropFunctionAction(nil, |
| 119 | + backfill.TriggerFunctionName("t1", "column1"), |
| 120 | + backfill.TriggerFunctionName("t1", TemporaryName("column1")), |
| 121 | + ), |
| 122 | + NewDropColumnAction(nil, "t1", backfill.CNeedsBackfillColumn), |
| 123 | + NewRenameDuplicatedColumnAction(nil, &schema.Table{Name: "t1"}, "column1"), |
| 124 | + }, |
| 125 | + expectedOrder: []string{ |
| 126 | + "alter_sequence_owner_t1_column1_to__pgroll_new_column1", |
| 127 | + "drop_column_t1_column1", |
| 128 | + "drop_function__pgroll_trigger_t1_column1__pgroll_trigger_t1__pgroll_new_column1", |
| 129 | + "drop_column_t1_" + backfill.CNeedsBackfillColumn, |
| 130 | + "rename_duplicated_t1_column1", |
| 131 | + }, |
| 132 | + }, |
| 133 | + "create table and add multiple constraints": { |
| 134 | + actions: []DBAction{ |
| 135 | + NewCreateTableAction(nil, "test_table", "", ""), |
| 136 | + NewAddColumnAction(nil, "column1", Column{}, false), |
| 137 | + NewAddColumnAction(nil, "column2", Column{}, false), |
| 138 | + NewCreateUniqueIndexConcurrentlyAction(nil, "public", "test_table", "my_idx", "column1"), |
| 139 | + NewCreateFKConstraintAction(nil, "test_table", "column2", []string{"other_column"}, nil, false, false, false), |
| 140 | + NewCreateCheckConstraintAction(nil, "test_table", "my_check", "column1 > 0", []string{"column1"}, false, false), |
| 141 | + }, |
| 142 | + expectedOrder: []string{ |
| 143 | + "create_table_test_table", |
| 144 | + "add_column_column1_", |
| 145 | + "add_column_column2_", |
| 146 | + "create_unique_index_concurrently_test_table_my_idx", |
| 147 | + "create_fk_constraint_test_table_column2", |
| 148 | + "create_check_constraint_test_table_my_check", |
| 149 | + }, |
| 150 | + }, |
| 151 | + } |
| 152 | + |
| 153 | + for name, tc := range testCases { |
| 154 | + t.Run(name, func(t *testing.T) { |
| 155 | + coordinator := NewCoordinator(tc.actions) |
| 156 | + if len(coordinator.orderedActions) != len(tc.expectedOrder) { |
| 157 | + t.Fatalf("expected order length %d, got %d", len(tc.expectedOrder), len(coordinator.orderedActions)) |
| 158 | + } |
| 159 | + |
| 160 | + require.Equal(t, tc.expectedOrder, coordinator.orderedActions, "order of actions does not match expected") |
| 161 | + }) |
| 162 | + } |
| 163 | +} |
0 commit comments