Skip to content

Commit 8e79918

Browse files
author
Bizley
authored
Merge pull request #152 from bizley/migration-timestamps
4.3.0
2 parents f8eefee + fead242 commit 8e79918

26 files changed

+867
-279
lines changed

README.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,32 +64,32 @@ The following console command are available (assuming you named the controller `
6464
- Generate migration to create DB table `table_name`:
6565

6666
```
67-
php yii migration/create table_name
67+
php yii migration/create "table_name"
6868
```
6969

7070
- Generate migration to update DB table `table_name`:
7171

7272
```
73-
php yii migration/update table_name
73+
php yii migration/update "table_name"
7474
```
7575

7676
To generate migrations for all the tables in the database at once (except the excluded ones) use asterisk (*):
7777

7878
```
79-
php yii migration/create *
80-
php yii migration/update *
79+
php yii migration/create "*"
80+
php yii migration/update "*"
8181
```
82-
In environments that hijack asterisk (like dockerized env) use `"*"`.
82+
8383
You can generate multiple migrations for many tables at once by separating the names with comma:
8484

8585
```
86-
php yii migration/create table_name1,table_name2,table_name3
86+
php yii migration/create "table_name1,table_name2,table_name3"
8787
```
8888

8989
You can provide an asterisk as a part of table name to use all tables matching the pattern:
9090

9191
```
92-
php yii migration/update prefix_*
92+
php yii migration/update "prefix_*"
9393
```
9494

9595
Creating multiple table migrations at once forces the proper migration order based on the presence of the foreign keys.
@@ -118,8 +118,9 @@ You can easily generate updating migration for database table by comparing its c
118118
| `skipMigrations` | | List of migrations from the history table that should be skipped during the update process (see [2] below).
119119
| `excludeTables` | | List of tables that should be skipped.
120120
| `experimental` | `ex` | Whether to run in experimental mode (see [3] below).
121-
| `fileMode` | `fm` | **New in 4.2.0** - Generated file mode to be changed using `chmod`.
122-
| `fileOwnership` | `fo` | **New in 4.2.0** - Generated file ownership to be changed using `chown`/`chgrp`.
121+
| `fileMode` | `fm` | Generated file mode to be changed using `chmod`.
122+
| `fileOwnership` | `fo` | Generated file ownership to be changed using `chown`/`chgrp`.
123+
| `leeway` | `lw` | **New in 4.3.0** - The leeway in seconds to apply to a starting timestamp when generating migration, so it can be saved with a later date
123124

124125
[1] Remember that with different database types general column schemas may be generated with different length.
125126

infection.json.dist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@
1919
"mutators": {
2020
"@default": true
2121
},
22-
"minCoveredMsi": 95
22+
"minCoveredMsi": 97
2323
}

migrating_to_v4.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ pattern, except excluded ones).
7777

7878
### create-all
7979

80-
Not available anymore. Use `create *` instead (or `create "*"` in environments that hijack asterisk).
80+
Not available anymore. Use `create "*"` instead.
8181

8282
### update
8383

@@ -87,4 +87,4 @@ pattern, except excluded ones).
8787

8888
### update-all
8989

90-
Not available anymore. Use `update *` instead (or `update "*"` in environments that hijack asterisk).
90+
Not available anymore. Use `update "*"` instead.

src/Arranger.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public function arrangeTables(array $inputTables): void
4141
foreach ($inputTables as $inputTable) {
4242
$this->addDependency($inputTable);
4343
$foreignKeys = $this->mapper->getStructureOf($inputTable)->getForeignKeys();
44-
/** @var ForeignKeyInterface $foreignKey */
44+
4545
foreach ($foreignKeys as $foreignKey) {
4646
$this->addDependency($inputTable, $foreignKey->getReferredTable());
4747
}

src/Comparator.php

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -240,15 +240,10 @@ private function compareForeignKeys(
240240
$oldForeignKey = $oldStructure->getForeignKey($name);
241241
$newForeignKeyColumns = $foreignKey->getColumns();
242242
$oldForeignKeyColumns = $oldForeignKey->getColumns();
243-
$intersection = array_intersect($newForeignKeyColumns, $oldForeignKeyColumns);
244243

245244
if (
246-
count(
247-
array_merge(
248-
array_diff($newForeignKeyColumns, $intersection),
249-
array_diff($oldForeignKeyColumns, $intersection)
250-
)
251-
)
245+
array_diff($newForeignKeyColumns, $oldForeignKeyColumns)
246+
!== array_diff($oldForeignKeyColumns, $newForeignKeyColumns)
252247
) {
253248
$blueprint->addDescription(
254249
"different foreign key '$name' columns ("
@@ -273,15 +268,10 @@ private function compareForeignKeys(
273268

274269
$newForeignKeyReferredColumns = $foreignKey->getReferredColumns();
275270
$oldForeignKeyReferredColumns = $oldForeignKey->getReferredColumns();
276-
$intersection = array_intersect($newForeignKeyReferredColumns, $oldForeignKeyReferredColumns);
277271

278272
if (
279-
count(
280-
array_merge(
281-
array_diff($newForeignKeyReferredColumns, $intersection),
282-
array_diff($oldForeignKeyReferredColumns, $intersection)
283-
)
284-
)
273+
array_diff($newForeignKeyReferredColumns, $oldForeignKeyReferredColumns)
274+
!== array_diff($oldForeignKeyReferredColumns, $newForeignKeyReferredColumns)
285275
) {
286276
$blueprint->addDescription(
287277
"different foreign key '$name' referred columns ("
@@ -408,14 +398,9 @@ private function comparePrimaryKeys(
408398

409399
$newPrimaryKeyColumns = $newPrimaryKey ? $newPrimaryKey->getColumns() : [];
410400
$oldPrimaryKeyColumns = $oldPrimaryKey ? $oldPrimaryKey->getColumns() : [];
411-
$intersection = array_intersect($newPrimaryKeyColumns, $oldPrimaryKeyColumns);
401+
$differentColumns = array_diff($newPrimaryKeyColumns, $oldPrimaryKeyColumns);
412402

413-
$differentColumns = array_merge(
414-
array_diff($newPrimaryKeyColumns, $intersection),
415-
array_diff($oldPrimaryKeyColumns, $intersection)
416-
);
417-
418-
if (count($differentColumns)) {
403+
if ($differentColumns !== array_diff($oldPrimaryKeyColumns, $newPrimaryKeyColumns)) {
419404
$blueprint->addDescription('different primary key definition');
420405

421406
$alreadyDropped = false;
@@ -570,16 +555,8 @@ private function compareIndexes(
570555

571556
$newIndexColumns = $index->getColumns();
572557
$oldIndexColumns = $oldIndex->getColumns();
573-
$intersection = array_intersect($newIndexColumns, $oldIndexColumns);
574558

575-
if (
576-
count(
577-
array_merge(
578-
array_diff($newIndexColumns, $intersection),
579-
array_diff($oldIndexColumns, $intersection)
580-
)
581-
)
582-
) {
559+
if (array_diff($newIndexColumns, $oldIndexColumns) !== array_diff($oldIndexColumns, $newIndexColumns)) {
583560
$blueprint->addDescription(
584561
"different index '$name' columns (DB: "
585562
. $this->stringifyValue($newIndexColumns) . ') != MIG: ('

src/Extractor.php

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,31 +37,13 @@ public function __construct(Connection $db, bool $experimental = false)
3737
/**
3838
* Extracts migration data structures.
3939
* @param string $migration
40-
* @param array<string> $migrationPaths
40+
* @param string[] $migrationPaths
4141
* @throws ErrorException
4242
*/
4343
public function extract(string $migration, array $migrationPaths): void
4444
{
4545
$this->setDummyMigrationClass();
46-
47-
if (strpos($migration, '\\') === false) { // not namespaced
48-
$fileFound = false;
49-
$file = null;
50-
foreach ($migrationPaths as $path) {
51-
/** @var string $file */
52-
$file = Yii::getAlias($path . DIRECTORY_SEPARATOR . $migration . '.php');
53-
if (file_exists($file)) {
54-
$fileFound = true;
55-
break;
56-
}
57-
}
58-
59-
if (!$fileFound) {
60-
throw new ErrorException("File '{$migration}.php' can not be found! Check migration history table.");
61-
}
62-
63-
require_once $file;
64-
}
46+
$this->loadFile($migration, $migrationPaths);
6547

6648
$this->subject = new $migration(['db' => $this->db, 'experimental' => $this->experimental]);
6749
if ($this->subject instanceof MigrationChangesInterface === false) {
@@ -73,6 +55,32 @@ public function extract(string $migration, array $migrationPaths): void
7355
$this->subject->up();
7456
}
7557

58+
/**
59+
* Loads a non-namespaced file.
60+
* @param string $migration
61+
* @param string[] $migrationPaths
62+
* @throws ErrorException
63+
*/
64+
private function loadFile(string $migration, array $migrationPaths): void
65+
{
66+
if (strpos($migration, '\\') !== false) {
67+
// migration with `\` character is most likely namespaced, so it doesn't require loading
68+
return;
69+
}
70+
71+
foreach ($migrationPaths as $path) {
72+
/** @var string $file */
73+
$file = Yii::getAlias($path . DIRECTORY_SEPARATOR . $migration . '.php');
74+
if (file_exists($file)) {
75+
require_once $file;
76+
77+
return;
78+
}
79+
}
80+
81+
throw new ErrorException("File '{$migration}.php' can not be found! Check migration history table.");
82+
}
83+
7684
/**
7785
* Sets the dummy migration file instead the real one to extract the migration structure instead of applying them.
7886
* It uses Yii's class map autoloaders hack.
@@ -82,6 +90,7 @@ private function setDummyMigrationClass(): void
8290
{
8391
// attempt to register Yii's autoloader in case it's not been done already
8492
// registering it second time should be skipped anyway
93+
/** @infection-ignore-all */
8594
spl_autoload_register(['Yii', 'autoload'], true, true);
8695

8796
Yii::$classMap['yii\db\Migration'] = Yii::getAlias('@bizley/migration/dummy/Migration.php');

src/HistoryManager.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,12 @@ public function fetchHistory(): array
108108
->all($this->db);
109109

110110
$history = [];
111-
foreach ($rows as $key => $row) {
111+
foreach ($rows as $row) {
112112
if ($row['version'] === MigrateController::BASE_MIGRATION) {
113113
continue;
114114
}
115115

116-
if (preg_match('/m?(\d{6}_?\d{6})(\D.*)?$/is', $row['version'], $matches)) {
116+
if (preg_match('/m?(\d{6}_?\d{6})(\D.*)?/i', $row['version'], $matches)) {
117117
$row['canonicalVersion'] = str_replace('_', '', $matches[1]);
118118
} else {
119119
$row['canonicalVersion'] = $row['version'];

src/Schema.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ public static function identifySchema($schema): string
169169
*/
170170
public static function isSQLite($schema): bool
171171
{
172-
return static::identifySchema($schema) === self::SQLITE;
172+
return self::identifySchema($schema) === self::SQLITE;
173173
}
174174

175175
/**
@@ -190,7 +190,7 @@ public static function getDefaultLength(?string $schema, string $type, string $e
190190
$schema = self::MYSQL . '+';
191191
}
192192

193-
return static::$defaultLength[$schema][$type] ?? null;
193+
return self::$defaultLength[$schema][$type] ?? null;
194194
}
195195

196196
/**
@@ -206,6 +206,6 @@ public static function getAlias(?string $schema, string $type, string $length):
206206
return null;
207207
}
208208

209-
return static::$aliases[$schema][$type][$length] ?? null;
209+
return self::$aliases[$schema][$type][$length] ?? null;
210210
}
211211
}

src/SqlColumnMapper.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ private function detectUnique(): void
232232
* @param int $offset
233233
* @return array{0: int, 1: string}
234234
*/
235-
private function findPart(string $type, string $sentence, int $offset = 0): array
235+
private function findPart(string $type, string $sentence, int $offset): array
236236
{
237237
$sentence = substr($sentence, $offset);
238238

@@ -257,7 +257,7 @@ private function findPart(string $type, string $sentence, int $offset = 0): arra
257257
[$end, $part] = $this->findExpressionPart($sentenceArray);
258258
}
259259

260-
return [$end ? $end + $offset : 0, $part];
260+
return [$end + $offset, $part];
261261
}
262262

263263
/**

src/TableMapper.php

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use PDO;
1818
use Throwable;
1919
use yii\base\NotSupportedException;
20+
use yii\db\ColumnSchema;
2021
use yii\db\Connection;
2122
use yii\db\Constraint;
2223
use yii\db\cubrid\Schema as CubridSchema;
@@ -54,7 +55,7 @@ public function getStructureOf(string $table, array $referencesToPostpone = []):
5455
{
5556
$this->suppressedForeignKeys = [];
5657
$foreignKeys = $this->getForeignKeys($table);
57-
/** @var ForeignKeyInterface $foreignKey */
58+
5859
foreach ($foreignKeys as $foreignKeyName => $foreignKey) {
5960
if (in_array($foreignKey->getReferredTable(), $referencesToPostpone, true)) {
6061
$this->suppressedForeignKeys[] = $foreignKey;
@@ -171,16 +172,7 @@ private function getColumns(string $table, array $indexes = []): array
171172
$engineVersion = $this->getEngineVersion();
172173

173174
foreach ($tableSchema->columns as $column) {
174-
$isUnique = false;
175-
176-
/** @var IndexInterface $index */
177-
foreach ($indexes as $index) {
178-
$indexColumns = $index->getColumns();
179-
if ($index->isUnique() && count($indexColumns) === 1 && $indexColumns[0] === $column->name) {
180-
$isUnique = true;
181-
break;
182-
}
183-
}
175+
$isUnique = $this->isUnique($indexes, $column);
184176

185177
$mappedColumn = ColumnFactory::build($column->type);
186178
$mappedColumn->setName($column->name);
@@ -209,6 +201,23 @@ private function getColumns(string $table, array $indexes = []): array
209201
return $mappedColumns;
210202
}
211203

204+
/**
205+
* @param array<IndexInterface> $indexes
206+
* @param ColumnSchema $column
207+
* @return bool
208+
*/
209+
private function isUnique(array $indexes, ColumnSchema $column): bool
210+
{
211+
foreach ($indexes as $index) {
212+
$indexColumns = $index->getColumns();
213+
if ($index->isUnique() && count($indexColumns) === 1 && $indexColumns[0] === $column->name) {
214+
return true;
215+
}
216+
}
217+
218+
return false;
219+
}
220+
212221
/**
213222
* Returns the suppressed foreign keys that must be added in migration at the end.
214223
* @return array<ForeignKeyInterface>

0 commit comments

Comments
 (0)