1111{
1212 /**
1313 * Run the migrations.
14+ *
15+ * Applies all v2 schema changes. Every operation is guarded for
16+ * idempotency so this migration is safe on both fresh installs
17+ * (where the tables were just created by the original migrations)
18+ * and upgrades from v1.x.
1419 */
1520 public function up (): void
1621 {
17- $ this ->renamePivotColumn ();
1822 $ this ->renameCountryStringColumns ();
1923 $ this ->fixRegionIdNullability ();
2024 $ this ->addMissingIndexes ();
@@ -28,36 +32,8 @@ public function down(): void
2832 // Not reversible: the original CREATE TABLE migrations handle table drops.
2933 }
3034
31- /**
32- * Rename time_zone_name → timezone_name in the country-timezone pivot table.
33- *
34- * Only applies to databases created before the column was renamed in the
35- * original migration file (commit 0258d50).
36- */
37- private function renamePivotColumn (): void
38- {
39- $ pivotTable = config ()->string ('atlas.country_timezone_pivot_tablename ' );
40-
41- if (! Schema::hasTable ($ pivotTable ) || ! Schema::hasColumn ($ pivotTable , 'time_zone_name ' )) {
42- return ;
43- }
44-
45- $ timezonesTable = config ()->string ('atlas.timezones_tablename ' );
46-
47- Schema::table ($ pivotTable , function (Blueprint $ table ): void {
48- $ table ->dropForeign (['time_zone_name ' ]);
49- $ table ->renameColumn ('time_zone_name ' , 'timezone_name ' );
50- });
51-
52- Schema::table ($ pivotTable , function (Blueprint $ table ) use ($ timezonesTable ): void {
53- $ table ->foreign ('timezone_name ' )->references ('zone_name ' )->on ($ timezonesTable );
54- });
55- }
56-
5735 /**
5836 * Rename region → region_name and subregion → subregion_name on the countries table.
59- *
60- * Only applies to databases created before the columns were renamed.
6137 */
6238 private function renameCountryStringColumns (): void
6339 {
@@ -82,8 +58,6 @@ private function renameCountryStringColumns(): void
8258
8359 /**
8460 * Make region_id nullable so that nullOnDelete() can work correctly.
85- *
86- * Only applies to databases where region_id was created as NOT NULL.
8761 */
8862 private function fixRegionIdNullability (): void
8963 {
@@ -99,43 +73,7 @@ private function fixRegionIdNullability(): void
9973 }
10074
10175 /**
102- * Remove duplicate rows from the pivot table so the unique index can be added safely.
103- *
104- * Databases upgraded from v1.x may contain duplicates because the old
105- * TimezonesSeeder had no DB-level uniqueness guarantee. Uses a
106- * database-agnostic approach (temp table + reinsert) since the pivot
107- * has no primary key column.
108- */
109- private function deduplicatePivotRows (string $ pivotTable ): void
110- {
111- $ duplicates = DB ::table ($ pivotTable )
112- ->select ('country_id ' , 'timezone_name ' )
113- ->groupBy ('country_id ' , 'timezone_name ' )
114- ->havingRaw ('COUNT(*) > 1 ' )
115- ->get ();
116-
117- if ($ duplicates ->isEmpty ()) {
118- return ;
119- }
120-
121- // For each duplicate group, delete all rows then re-insert one.
122- foreach ($ duplicates as $ row ) {
123- DB ::table ($ pivotTable )
124- ->where ('country_id ' , $ row ->country_id )
125- ->where ('timezone_name ' , $ row ->timezone_name )
126- ->delete ();
127-
128- DB ::table ($ pivotTable )->insert ([
129- 'country_id ' => $ row ->country_id ,
130- 'timezone_name ' => $ row ->timezone_name ,
131- ]);
132- }
133- }
134-
135- /**
136- * Add indexes that were added to CREATE TABLE migrations after initial release.
137- *
138- * Only applies to databases created before the indexes were added (commit 7716529).
76+ * Add indexes introduced in v2.
13977 */
14078 private function addMissingIndexes (): void
14179 {
@@ -181,4 +119,32 @@ private function addMissingIndexes(): void
181119 });
182120 }
183121 }
122+
123+ /**
124+ * Remove duplicate rows from the pivot table so the unique index can be added safely.
125+ */
126+ private function deduplicatePivotRows (string $ pivotTable ): void
127+ {
128+ $ duplicates = DB ::table ($ pivotTable )
129+ ->select ('country_id ' , 'timezone_name ' )
130+ ->groupBy ('country_id ' , 'timezone_name ' )
131+ ->havingRaw ('COUNT(*) > 1 ' )
132+ ->get ();
133+
134+ if ($ duplicates ->isEmpty ()) {
135+ return ;
136+ }
137+
138+ foreach ($ duplicates as $ row ) {
139+ DB ::table ($ pivotTable )
140+ ->where ('country_id ' , $ row ->country_id )
141+ ->where ('timezone_name ' , $ row ->timezone_name )
142+ ->delete ();
143+
144+ DB ::table ($ pivotTable )->insert ([
145+ 'country_id ' => $ row ->country_id ,
146+ 'timezone_name ' => $ row ->timezone_name ,
147+ ]);
148+ }
149+ }
184150};
0 commit comments