Skip to content

Allow to split up/down migration into multiple sql files using the '-- @FILE' annotation #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 38 additions & 3 deletions Migrate/Command/AbstractEnvCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

use Migrate\Migration;
use Migrate\Utils\ArrayUtil;
use SebastianBergmann\GlobalState\RuntimeException;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
Expand Down Expand Up @@ -52,6 +53,13 @@ public function getChangelogTable()
return ArrayUtil::get($this->getConfig(), 'changelog');
}

protected function checkEnv()
{
if (!file_exists(getcwd() . '/.php-database-migration/environments')) {
throw new \RuntimeException("you are not in an initialized php-database-migration directory");
}
}

protected function init(InputInterface $input, OutputInterface $output, $env = null)
{
$configDirectory = array(getcwd() . '/.php-database-migration/environments');
Expand Down Expand Up @@ -100,7 +108,7 @@ protected function init(InputInterface $input, OutputInterface $output, $env = n
public function getLocalMigrations()
{
$fileList = scandir($this->getMigrationDir());
$fileList = ArrayUtil::filter($fileList);
$fileList = ArrayUtil::filter($this->getMigrationDir(), $fileList);

$migrations = array();
foreach ($fileList as $file) {
Expand Down Expand Up @@ -204,17 +212,44 @@ public function removeFromChangelog(Migration $migration)
*/
public function executeUpMigration(Migration $migration)
{
$this->getDb()->query($migration->getSqlUp());
$this->getDb()->beginTransaction();
$result = $this->getDb()->exec($migration->getSqlUp());

if ($result === false) {
// error while executing the migration
$errorInfo = "";
$errorInfos = $this->getDb()->errorInfo();
foreach ($errorInfos as $line) {
$errorInfo .= "\n$line";
}
$this->getDb()->rollBack();
throw new \RuntimeException("migration error, some SQL may be wrong\n\nid: {$migration->getId()}\nfile: {$migration->getFile()}\n" . $errorInfo);
}

$this->saveToChangelog($migration);
$this->getDb()->commit();
}

/**
* @param Migration $migration
*/
public function executeDownMigration(Migration $migration)
{
$this->getDb()->query($migration->getSqlDown());
$this->getDb()->beginTransaction();
$result = $this->getDb()->exec($migration->getSqlDown());

if ($result === false) {
// error while executing the migration
$errorInfo = "";
$errorInfos = $this->getDb()->errorInfo();
foreach ($errorInfos as $line) {
$errorInfo .= "\n$line";
}
$this->getDb()->rollBack();
throw new \RuntimeException("migration error, some SQL may be wrong\n\nid: {$migration->getId()}\nfile: {$migration->getFile()}\n" . $errorInfo);
}
$this->removeFromChangelog($migration);
$this->getDb()->commit();
}

protected function filterMigrationsToExecute(InputInterface $input, OutputInterface $output)
Expand Down
2 changes: 2 additions & 0 deletions Migrate/Command/CreateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ protected function configure()

protected function execute(InputInterface $input, OutputInterface $output)
{
$this->checkEnv();

/* @var $questions QuestionHelper */
$questions = $this->getHelperSet()->get('question');

Expand Down
2 changes: 2 additions & 0 deletions Migrate/Command/DownCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ protected function configure()

protected function execute(InputInterface $input, OutputInterface $output)
{
$this->checkEnv();

$this->init($input, $output);

/* @var $questions QuestionHelper */
Expand Down
2 changes: 2 additions & 0 deletions Migrate/Command/UpCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ protected function configure()

protected function execute(InputInterface $input, OutputInterface $output)
{
$this->checkEnv();

$this->init($input, $output);

$toExecute = $this->filterMigrationsToExecute($input, $output);
Expand Down
39 changes: 37 additions & 2 deletions Migrate/Migration.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ public function setSqlUp($sqlUp)
$this->sqlUp = $sqlUp;
}



/**
* @return mixed
*/
Expand Down Expand Up @@ -180,8 +182,41 @@ public function load($migrationDir)
@$content = file_get_contents($migrationDir . '/' . $this->getFile());
if ($content && strpos($content, '@UNDO') > 0) {
$sql = explode('-- @UNDO', $content);
$this->setSqlUp($sql[0]);
$this->setSqlDown($sql[1]);
$this->setSqlUp($this->parseSQLFile($migrationDir, $sql[0]));
$this->setSqlDown($this->parseSQLFile($migrationDir, $sql[1]));
}
}

public function parseSQLFile($migrationDir, $content = null, $sqlFile = null, $nestingLevel = 1) {
if($nestingLevel > 5) {
// Do not allow more than 5 nesting level
throw new \RuntimeException(sprintf('Local migration "%s" is invalid : the "-- @FILE" annotation does not support more than 5 nesting level !', $this->getDescription()));
}
if( $sqlFile != null ) {
@$content = file_get_contents($migrationDir . '/' . $sqlFile);
}
if($content != null) {
if( strpos($content, '-- @FILE') !== false ) {
$buffer = '';
$isFile = false;
$lines = explode("\n", $content);
foreach($lines as $line) {
if( strpos($line, '-- @FILE') !== false ) {
$isFile = true;
continue;
}
if( $isFile ) {
$filename = trim($line);
$buffer .= PHP_EOL . $this->parseSQLFile($migrationDir, null, $filename, ($nestingLevel+1));
$isFile = false;
continue;
}
$buffer .= PHP_EOL . $line;
}
return $buffer;
} else {
return $content;
}
}
}
}
18 changes: 7 additions & 11 deletions Migrate/Utils/ArrayUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,14 @@ public static function get(array $array, $key) {
return (array_key_exists($key, $array)) ? $array[$key] : null;
}

public static function filter(array $array) {
if (isset($array['.'])) {
unset($array['.']);
public static function filter($dir, array $array) {
$files = array();
foreach ($array as $file) {
if(!is_dir(sprintf('%s/%s', $dir, $file))){
$files[] = $file;
}
}

if (isset($array['..'])) {
unset($array['..']);
}

unset($array[0]);
unset($array[1]);

return $array;
return $files;
}
}
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "alwex/php-database-migration",
"name": "php-database-migration/php-database-migration",
"description": "rake and mybatis SQL migration tool",
"homepage": "https://github.com/alwex/php-database-migration",
"homepage": "https://github.com/tellim/php-database-migration",
"keywords": ["rake", "mybatis", "migration", "sql"],
"type": "library",
"license": "MIT",
Expand Down
17 changes: 17 additions & 0 deletions tests/Command/CreateCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,21 @@ public function testExecute()

$this->assertEquals($expected, $content);
}

/**
* @expectedException \RuntimeException
* @expectedExceptionMessage you are not in an initialized php-database-migration directory
*/
public function testCreateNotInAnInitialisedProject()
{
$this->cleanEnv();

$application = new Application();
$application->add(new CreateCommand());

$command = $application->find('migrate:create');
$commandTester = new CommandTester($command);

$commandTester->execute(array('command' => $command->getName()));
}
}
98 changes: 97 additions & 1 deletion tests/Command/UpDownCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function setUp()
$this->initEnv();

$this->createMigration('0', "CREATE TABLE test (id INTEGER, thevalue TEXT);", "DROP TABLE test;");
$this->createMigration('1', "INSERT INTO test VALUES (1, 'one');", "DELETE FROM test WHERE id = 1;");
$this->createMigration('1', "SELECT 1", "DELETE FROM test WHERE id = 1;");
$this->createMigration('2', "INSERT INTO test VALUES (2, 'two');", "DELETE FROM test WHERE id = 2;");

self::$application = new Application();
Expand All @@ -42,6 +42,50 @@ public function tearDown()
$this->cleanEnv();
}

/**
* @expectedException \RuntimeException
*/
public function testUpMigrationWithError()
{
$this->createMigration('3', "SELECT ;", "SELECT ;");
$command = self::$application->find('migrate:up');
$commandTester = new CommandTester($command);

$commandTester->execute(array(
'command' => $command->getName(),
'env' => 'testing'
));
}

/**
* @expectedException \RuntimeException
*/
public function testDownMigrationWithError()
{
$this->createMigration('3', "SELECT 1;", "SELECT ;");


$command = self::$application->find('migrate:up');
$commandTester = new CommandTester($command);

$commandTester->execute(array(
'command' => $command->getName(),
'env' => 'testing'
));

$command = self::$application->find('migrate:down');
$commandTester = new CommandTester($command);

/* @var $question QuestionHelper */
$question = $command->getHelper('question');
$question->setInputStream(InputStreamUtil::type("yes\n"));

$commandTester->execute(array(
'command' => $command->getName(),
'env' => 'testing'
));
}

public function testUpAllPendingMigrations()
{

Expand Down Expand Up @@ -308,4 +352,56 @@ public function testDownTo()

$this->assertEquals($expected, $commandTester->getDisplay());
}

/**
* @expectedException \RuntimeException
* @expectedExceptionMessage you are not in an initialized php-database-migration directory
*/
public function testUpInANotInitializedDirectory()
{
$this->cleanEnv();

$command = self::$application->find('migrate:up');
$commandTester = new CommandTester($command);

$commandTester->execute(array(
'command' => $command->getName(),
'env' => 'testing',
));

$command = self::$application->find('migrate:down');
$commandTester = new CommandTester($command);

$commandTester->execute(array(
'command' => $command->getName(),
'env' => 'testing',
'--to' => '1'
));
}

/**
* @expectedException \RuntimeException
* @expectedExceptionMessage you are not in an initialized php-database-migration directory
*/
public function testDownInANotInitializedDirectory()
{
$this->cleanEnv();

$command = self::$application->find('migrate:down');
$commandTester = new CommandTester($command);

$commandTester->execute(array(
'command' => $command->getName(),
'env' => 'testing',
));

$command = self::$application->find('migrate:down');
$commandTester = new CommandTester($command);

$commandTester->execute(array(
'command' => $command->getName(),
'env' => 'testing',
'--to' => '1'
));
}
}
Loading