Skip to content

Commit

Permalink
#11 - Implement new option 'skip-foreign-checks'
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeckerson committed Mar 22, 2020
1 parent 9f5edfc commit 14128c9
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 22 deletions.
31 changes: 15 additions & 16 deletions src/Console/Commands/Migration.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,12 @@
namespace Phalcon\Migrations\Console\Commands;

use Phalcon\Config;
use Phalcon\Cop\Parser;
use Phalcon\Migrations\Console\Color;
use Phalcon\Migrations\Migrations;
use Phalcon\Migrations\Script\ScriptException;
use Phalcon\Mvc\Model\Exception;
use Phalcon\Config\Adapter\Ini as IniConfig;
use Phalcon\Config\Adapter\Json as JsonConfig;
use Phalcon\Config\Adapter\Yaml as YamlConfig;
use Phalcon\Cop\Parser;
use Phalcon\Migrations\Console\Color;
use Phalcon\Migrations\Migrations;

/**
* Migration Command
Expand Down Expand Up @@ -69,8 +67,8 @@ public function getPossibleParams(): array

/**
* @throws CommandsException
* @throws ScriptException
* @throws Exception
* @throws \Phalcon\Db\Exception
* @throws \Exception
*/
public function run(): void
{
Expand Down Expand Up @@ -146,15 +144,16 @@ public function run(): void
break;
case 'run':
Migrations::run([
'directory' => $path,
'tableName' => $tableName,
'migrationsDir' => $migrationsDir,
'force' => $this->parser->has('force'),
'tsBased' => $migrationsTsBased,
'config' => $config,
'version' => $this->parser->get('version'),
'migrationsInDb' => $migrationsInDb,
'verbose' => $this->parser->has('verbose'),
'directory' => $path,
'tableName' => $tableName,
'migrationsDir' => $migrationsDir,
'force' => $this->parser->has('force'),
'tsBased' => $migrationsTsBased,
'config' => $config,
'version' => $this->parser->get('version'),
'migrationsInDb' => $migrationsInDb,
'verbose' => $this->parser->has('verbose'),
'skip-foreign-checks' => $this->parser->has('skip-foreign-checks'),
]);
break;
case 'list':
Expand Down
18 changes: 16 additions & 2 deletions src/Migrations.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use Phalcon\Migrations\Version\IncrementalItem;
use Phalcon\Migrations\Version\ItemCollection as VersionCollection;
use Phalcon\Migrations\Version\TimestampedItem;
use SplFileInfo;

class Migrations
{
Expand Down Expand Up @@ -191,13 +192,15 @@ public static function generate(array $options)
* @param array $options
* @throws DbException
* @throws RuntimeException
* @throws Exception
*/
public static function run(array $options)
{
$optionStack = new OptionStack();
$listTables = new ListTablesIterator();
$optionStack->setOptions($options);
$optionStack->setDefaultOption('verbose', false);
$optionStack->setDefaultOption('skip-foreign-checks', false);

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

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

ModelMigration::migrate($fileInfo->getBasename('.php'), $initialVersion, $versionItem);
ModelMigration::migrate(
$fileInfo->getBasename('.php'),
$initialVersion,
$versionItem,
$optionStack->getOption('skip-foreign-checks')
);
}
} else {
if (!empty($prefix)) {
Expand All @@ -369,7 +378,12 @@ public static function run(array $options)

$tables = explode(',', $optionStack->getOption('tableName'));
foreach ($tables as $tableName) {
ModelMigration::migrate($tableName, $initialVersion, $versionItem);
ModelMigration::migrate(
$tableName,
$initialVersion,
$versionItem,
$optionStack->getOption('skip-foreign-checks')
);
}
}

Expand Down
12 changes: 11 additions & 1 deletion src/Mvc/Model/Migration.php
Original file line number Diff line number Diff line change
Expand Up @@ -328,12 +328,14 @@ public static function shouldExportDataFromTable(string $table, array $exportTab
* @param string $tableName
* @param ItemInterface|null $fromVersion
* @param ItemInterface|null $toVersion
* @param bool $skipForeignChecks
* @throws Exception
*/
public static function migrate(
string $tableName,
ItemInterface $fromVersion = null,
ItemInterface $toVersion = null
ItemInterface $toVersion = null,
bool $skipForeignChecks = false
): void {
$fromVersion = $fromVersion ?: VersionCollection::createItem($fromVersion);
$toVersion = $toVersion ?: VersionCollection::createItem($toVersion);
Expand All @@ -342,6 +344,10 @@ public static function migrate(
return; // nothing to do
}

if ($skipForeignChecks === true) {
self::$connection->execute('SET FOREIGN_KEY_CHECKS=0');
}

if ($fromVersion->getStamp() < $toVersion->getStamp()) {
$toMigration = self::createClass($toVersion, $tableName);

Expand Down Expand Up @@ -378,6 +384,10 @@ public static function migrate(
$toMigration->morph();
}
}

if ($skipForeignChecks === true) {
self::$connection->execute('SET FOREIGN_KEY_CHECKS=1');
}
}

/**
Expand Down
16 changes: 16 additions & 0 deletions tests/_support/Helper/Mysql.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,23 @@ public function _initialize()

public function _before(TestInterface $test)
{
$this->setForeignKeys();
foreach ($this->getPhalconDb()->listTables() as $table) {
$this->getPhalconDb()->dropTable($table);
}

$this->setForeignKeys(true);
}

public function _after(TestInterface $test)
{
$this->setForeignKeys();
foreach ($this->getPhalconDb()->listTables() as $table) {
$this->getPhalconDb()->dropTable($table);
}

$this->setForeignKeys(true);

/**
* Reset filename or DB connection
*/
Expand Down Expand Up @@ -123,4 +129,14 @@ public function batchInsert(string $table, array $columns, array $rows)

$this->getPhalconDb()->execute($query);
}

/**
* Executes 'SET FOREIGN_KEY_CHECKS' query
*
* @param bool $enabled
*/
protected function setForeignKeys(bool $enabled = false): void
{
$this->getPhalconDb()->execute('SET FOREIGN_KEY_CHECKS=' . intval($enabled));
}
}
111 changes: 108 additions & 3 deletions tests/cli/RunCest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,15 @@

use CliTester;
use Phalcon\Db\Column;
use Phalcon\Db\Reference;

final class RunCest
{
/**
* @var string
*/
protected $configPath = 'tests/_data/cli/migrations.php';

/**
* @param CliTester $I
*/
Expand Down Expand Up @@ -46,14 +52,113 @@ public function generateAndRun(CliTester $I): void
],
]);

$configPath = 'tests/_data/cli/migrations.php';
$I->runShellCommand('php phalcon-migrations generate --config=' . $this->configPath);
$I->seeInShellOutput('Success: Version 1.0.0 was successfully generated');
$I->seeResultCodeIs(0);

$I->runShellCommand('php phalcon-migrations run --config=' . $this->configPath);
$I->seeInShellOutput('Success: Version 1.0.0 was successfully migrated');
$I->seeResultCodeIs(0);
}

/**
* @param CliTester $I
*/
public function skipForeignKeys(CliTester $I): void
{
$table1 = 'client';
$table2 = 'x-skip-foreign-keys';

$this->createTablesWithForeignKey($I);

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

$I->runShellCommand('php phalcon-migrations run --config=' . $configPath);
$migrationContent = file_get_contents(codecept_output_dir('1.0.0/' . $table2 . '.php'));
$I->assertNotFalse(strpos($migrationContent, "'referencedTable' => 'client',"));

$I->getPhalconDb()->dropTable($table2);
$I->getPhalconDb()->dropTable($table1);

$I->runShellCommand('php phalcon-migrations run --skip-foreign-checks --config=' . $this->configPath);
$I->seeInShellOutput('Success: Version 1.0.0 was successfully migrated');
$I->seeResultCodeIs(0);
}

/**
* @param CliTester $I
*/
public function expectForeignKeyDbError(CliTester $I): void
{
$table1 = 'client';
$table2 = 'x-skip-foreign-keys';

$this->createTablesWithForeignKey($I);

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

$migrationContent = file_get_contents(codecept_output_dir('1.0.0/' . $table2 . '.php'));
$I->assertNotFalse(strpos($migrationContent, "'referencedTable' => 'client',"));

$I->getPhalconDb()->dropTable($table2);
$I->getPhalconDb()->dropTable($table1);

$I->runShellCommand('php phalcon-migrations run --config=' . $this->configPath, false);
$I->seeInShellOutput('Fatal Error: SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint');
$I->seeResultCodeIs(1);
}

/**
* DRY!
*
* @param CliTester $I
*/
protected function createTablesWithForeignKey(CliTester $I): void
{
$schema = getenv('MYSQL_TEST_DB_DATABASE');
$table1 = 'client';
$table2 = 'x-skip-foreign-keys';

$I->getPhalconDb()->createTable($table1, $schema, [
'columns' => [
new Column('id', [
'type' => Column::TYPE_INTEGER,
'size' => 11,
'notNull' => true,
'primary' => true,
]),
],
]);

$I->getPhalconDb()->createTable($table2, $schema, [
'columns' => [
new Column('id', [
'type' => Column::TYPE_INTEGER,
'size' => 10,
'notNull' => true,
]),
new Column('clientId', [
'type' => Column::TYPE_INTEGER,
'size' => 11,
'notNull' => true,
]),
],
'references' => [
new Reference(
'fk_client_1',
[
'referencedSchema' => $schema,
'referencedTable' => $table1,
'columns' => ['clientId'],
'referencedColumns' => ['id'],
'onUpdate' => 'NO ACTION',
'onDelete' => 'NO ACTION',
]
),
],
]);
}
}

0 comments on commit 14128c9

Please sign in to comment.