Skip to content

Commit 14128c9

Browse files
committed
#11 - Implement new option 'skip-foreign-checks'
1 parent 9f5edfc commit 14128c9

File tree

5 files changed

+166
-22
lines changed

5 files changed

+166
-22
lines changed

src/Console/Commands/Migration.php

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,12 @@
1414
namespace Phalcon\Migrations\Console\Commands;
1515

1616
use Phalcon\Config;
17-
use Phalcon\Cop\Parser;
18-
use Phalcon\Migrations\Console\Color;
19-
use Phalcon\Migrations\Migrations;
20-
use Phalcon\Migrations\Script\ScriptException;
21-
use Phalcon\Mvc\Model\Exception;
2217
use Phalcon\Config\Adapter\Ini as IniConfig;
2318
use Phalcon\Config\Adapter\Json as JsonConfig;
2419
use Phalcon\Config\Adapter\Yaml as YamlConfig;
20+
use Phalcon\Cop\Parser;
21+
use Phalcon\Migrations\Console\Color;
22+
use Phalcon\Migrations\Migrations;
2523

2624
/**
2725
* Migration Command
@@ -69,8 +67,8 @@ public function getPossibleParams(): array
6967

7068
/**
7169
* @throws CommandsException
72-
* @throws ScriptException
73-
* @throws Exception
70+
* @throws \Phalcon\Db\Exception
71+
* @throws \Exception
7472
*/
7573
public function run(): void
7674
{
@@ -146,15 +144,16 @@ public function run(): void
146144
break;
147145
case 'run':
148146
Migrations::run([
149-
'directory' => $path,
150-
'tableName' => $tableName,
151-
'migrationsDir' => $migrationsDir,
152-
'force' => $this->parser->has('force'),
153-
'tsBased' => $migrationsTsBased,
154-
'config' => $config,
155-
'version' => $this->parser->get('version'),
156-
'migrationsInDb' => $migrationsInDb,
157-
'verbose' => $this->parser->has('verbose'),
147+
'directory' => $path,
148+
'tableName' => $tableName,
149+
'migrationsDir' => $migrationsDir,
150+
'force' => $this->parser->has('force'),
151+
'tsBased' => $migrationsTsBased,
152+
'config' => $config,
153+
'version' => $this->parser->get('version'),
154+
'migrationsInDb' => $migrationsInDb,
155+
'verbose' => $this->parser->has('verbose'),
156+
'skip-foreign-checks' => $this->parser->has('skip-foreign-checks'),
158157
]);
159158
break;
160159
case 'list':

src/Migrations.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
use Phalcon\Migrations\Version\IncrementalItem;
2929
use Phalcon\Migrations\Version\ItemCollection as VersionCollection;
3030
use Phalcon\Migrations\Version\TimestampedItem;
31+
use SplFileInfo;
3132

3233
class Migrations
3334
{
@@ -191,13 +192,15 @@ public static function generate(array $options)
191192
* @param array $options
192193
* @throws DbException
193194
* @throws RuntimeException
195+
* @throws Exception
194196
*/
195197
public static function run(array $options)
196198
{
197199
$optionStack = new OptionStack();
198200
$listTables = new ListTablesIterator();
199201
$optionStack->setOptions($options);
200202
$optionStack->setDefaultOption('verbose', false);
203+
$optionStack->setDefaultOption('skip-foreign-checks', false);
201204

202205
// Define versioning type to be used
203206
if (!empty($options['tsBased']) || $optionStack->getOption('tsBased')) {
@@ -355,12 +358,18 @@ public static function run(array $options)
355358
$migrationStartTime = date('Y-m-d H:i:s');
356359

357360
if ($optionStack->getOption('tableName') === '@') {
361+
/** @var SplFileInfo $fileInfo */
358362
foreach ($iterator as $fileInfo) {
359363
if (!$fileInfo->isFile() || 0 !== strcasecmp($fileInfo->getExtension(), 'php')) {
360364
continue;
361365
}
362366

363-
ModelMigration::migrate($fileInfo->getBasename('.php'), $initialVersion, $versionItem);
367+
ModelMigration::migrate(
368+
$fileInfo->getBasename('.php'),
369+
$initialVersion,
370+
$versionItem,
371+
$optionStack->getOption('skip-foreign-checks')
372+
);
364373
}
365374
} else {
366375
if (!empty($prefix)) {
@@ -369,7 +378,12 @@ public static function run(array $options)
369378

370379
$tables = explode(',', $optionStack->getOption('tableName'));
371380
foreach ($tables as $tableName) {
372-
ModelMigration::migrate($tableName, $initialVersion, $versionItem);
381+
ModelMigration::migrate(
382+
$tableName,
383+
$initialVersion,
384+
$versionItem,
385+
$optionStack->getOption('skip-foreign-checks')
386+
);
373387
}
374388
}
375389

src/Mvc/Model/Migration.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,12 +328,14 @@ public static function shouldExportDataFromTable(string $table, array $exportTab
328328
* @param string $tableName
329329
* @param ItemInterface|null $fromVersion
330330
* @param ItemInterface|null $toVersion
331+
* @param bool $skipForeignChecks
331332
* @throws Exception
332333
*/
333334
public static function migrate(
334335
string $tableName,
335336
ItemInterface $fromVersion = null,
336-
ItemInterface $toVersion = null
337+
ItemInterface $toVersion = null,
338+
bool $skipForeignChecks = false
337339
): void {
338340
$fromVersion = $fromVersion ?: VersionCollection::createItem($fromVersion);
339341
$toVersion = $toVersion ?: VersionCollection::createItem($toVersion);
@@ -342,6 +344,10 @@ public static function migrate(
342344
return; // nothing to do
343345
}
344346

347+
if ($skipForeignChecks === true) {
348+
self::$connection->execute('SET FOREIGN_KEY_CHECKS=0');
349+
}
350+
345351
if ($fromVersion->getStamp() < $toVersion->getStamp()) {
346352
$toMigration = self::createClass($toVersion, $tableName);
347353

@@ -378,6 +384,10 @@ public static function migrate(
378384
$toMigration->morph();
379385
}
380386
}
387+
388+
if ($skipForeignChecks === true) {
389+
self::$connection->execute('SET FOREIGN_KEY_CHECKS=1');
390+
}
381391
}
382392

383393
/**

tests/_support/Helper/Mysql.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,23 @@ public function _initialize()
3131

3232
public function _before(TestInterface $test)
3333
{
34+
$this->setForeignKeys();
3435
foreach ($this->getPhalconDb()->listTables() as $table) {
3536
$this->getPhalconDb()->dropTable($table);
3637
}
38+
39+
$this->setForeignKeys(true);
3740
}
3841

3942
public function _after(TestInterface $test)
4043
{
44+
$this->setForeignKeys();
4145
foreach ($this->getPhalconDb()->listTables() as $table) {
4246
$this->getPhalconDb()->dropTable($table);
4347
}
4448

49+
$this->setForeignKeys(true);
50+
4551
/**
4652
* Reset filename or DB connection
4753
*/
@@ -123,4 +129,14 @@ public function batchInsert(string $table, array $columns, array $rows)
123129

124130
$this->getPhalconDb()->execute($query);
125131
}
132+
133+
/**
134+
* Executes 'SET FOREIGN_KEY_CHECKS' query
135+
*
136+
* @param bool $enabled
137+
*/
138+
protected function setForeignKeys(bool $enabled = false): void
139+
{
140+
$this->getPhalconDb()->execute('SET FOREIGN_KEY_CHECKS=' . intval($enabled));
141+
}
126142
}

tests/cli/RunCest.php

Lines changed: 108 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,15 @@
1515

1616
use CliTester;
1717
use Phalcon\Db\Column;
18+
use Phalcon\Db\Reference;
1819

1920
final class RunCest
2021
{
22+
/**
23+
* @var string
24+
*/
25+
protected $configPath = 'tests/_data/cli/migrations.php';
26+
2127
/**
2228
* @param CliTester $I
2329
*/
@@ -46,14 +52,113 @@ public function generateAndRun(CliTester $I): void
4652
],
4753
]);
4854

49-
$configPath = 'tests/_data/cli/migrations.php';
55+
$I->runShellCommand('php phalcon-migrations generate --config=' . $this->configPath);
56+
$I->seeInShellOutput('Success: Version 1.0.0 was successfully generated');
57+
$I->seeResultCodeIs(0);
58+
59+
$I->runShellCommand('php phalcon-migrations run --config=' . $this->configPath);
60+
$I->seeInShellOutput('Success: Version 1.0.0 was successfully migrated');
61+
$I->seeResultCodeIs(0);
62+
}
63+
64+
/**
65+
* @param CliTester $I
66+
*/
67+
public function skipForeignKeys(CliTester $I): void
68+
{
69+
$table1 = 'client';
70+
$table2 = 'x-skip-foreign-keys';
71+
72+
$this->createTablesWithForeignKey($I);
5073

51-
$I->runShellCommand('php phalcon-migrations generate --config=' . $configPath);
74+
$I->runShellCommand('php phalcon-migrations generate --config=' . $this->configPath);
5275
$I->seeInShellOutput('Success: Version 1.0.0 was successfully generated');
5376
$I->seeResultCodeIs(0);
5477

55-
$I->runShellCommand('php phalcon-migrations run --config=' . $configPath);
78+
$migrationContent = file_get_contents(codecept_output_dir('1.0.0/' . $table2 . '.php'));
79+
$I->assertNotFalse(strpos($migrationContent, "'referencedTable' => 'client',"));
80+
81+
$I->getPhalconDb()->dropTable($table2);
82+
$I->getPhalconDb()->dropTable($table1);
83+
84+
$I->runShellCommand('php phalcon-migrations run --skip-foreign-checks --config=' . $this->configPath);
5685
$I->seeInShellOutput('Success: Version 1.0.0 was successfully migrated');
5786
$I->seeResultCodeIs(0);
5887
}
88+
89+
/**
90+
* @param CliTester $I
91+
*/
92+
public function expectForeignKeyDbError(CliTester $I): void
93+
{
94+
$table1 = 'client';
95+
$table2 = 'x-skip-foreign-keys';
96+
97+
$this->createTablesWithForeignKey($I);
98+
99+
$I->runShellCommand('php phalcon-migrations generate --config=' . $this->configPath);
100+
$I->seeInShellOutput('Success: Version 1.0.0 was successfully generated');
101+
$I->seeResultCodeIs(0);
102+
103+
$migrationContent = file_get_contents(codecept_output_dir('1.0.0/' . $table2 . '.php'));
104+
$I->assertNotFalse(strpos($migrationContent, "'referencedTable' => 'client',"));
105+
106+
$I->getPhalconDb()->dropTable($table2);
107+
$I->getPhalconDb()->dropTable($table1);
108+
109+
$I->runShellCommand('php phalcon-migrations run --config=' . $this->configPath, false);
110+
$I->seeInShellOutput('Fatal Error: SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint');
111+
$I->seeResultCodeIs(1);
112+
}
113+
114+
/**
115+
* DRY!
116+
*
117+
* @param CliTester $I
118+
*/
119+
protected function createTablesWithForeignKey(CliTester $I): void
120+
{
121+
$schema = getenv('MYSQL_TEST_DB_DATABASE');
122+
$table1 = 'client';
123+
$table2 = 'x-skip-foreign-keys';
124+
125+
$I->getPhalconDb()->createTable($table1, $schema, [
126+
'columns' => [
127+
new Column('id', [
128+
'type' => Column::TYPE_INTEGER,
129+
'size' => 11,
130+
'notNull' => true,
131+
'primary' => true,
132+
]),
133+
],
134+
]);
135+
136+
$I->getPhalconDb()->createTable($table2, $schema, [
137+
'columns' => [
138+
new Column('id', [
139+
'type' => Column::TYPE_INTEGER,
140+
'size' => 10,
141+
'notNull' => true,
142+
]),
143+
new Column('clientId', [
144+
'type' => Column::TYPE_INTEGER,
145+
'size' => 11,
146+
'notNull' => true,
147+
]),
148+
],
149+
'references' => [
150+
new Reference(
151+
'fk_client_1',
152+
[
153+
'referencedSchema' => $schema,
154+
'referencedTable' => $table1,
155+
'columns' => ['clientId'],
156+
'referencedColumns' => ['id'],
157+
'onUpdate' => 'NO ACTION',
158+
'onDelete' => 'NO ACTION',
159+
]
160+
),
161+
],
162+
]);
163+
}
59164
}

0 commit comments

Comments
 (0)