Пример #1
0
 public function run($options = array())
 {
     Yentu::greet();
     $db = DatabaseManipulator::create();
     DatabaseItem::setDriver($db);
     ChangeReverser::setDriver($db);
     $previousMigration = '';
     if (isset($options['default-schema'])) {
         $this->schemaCondition = "default_schema = ?";
         $this->schemaConditionData[] = $options['default-schema'];
     }
     if (empty($options)) {
         $session = $db->getLastSession();
         $operations = $db->query("SELECT id, method, arguments, migration, default_schema FROM yentu_history WHERE {$this->schemaCondition} session = ? ORDER BY id DESC", $this->schemaConditionData + [$session]);
     } else {
         $operations = [];
         foreach ($options['stand_alones'] as $set) {
             $operations += $this->getOperations($db, $set);
         }
     }
     foreach ($operations as $operation) {
         if ($previousMigration !== $operation['migration']) {
             ClearIce::output("Rolling back '{$operation['migration']}' migration" . ($operation['default_schema'] != '' ? " on `{$operation['default_schema']}` schema." : ".") . "\n");
             $previousMigration = $operation['migration'];
         }
         ChangeReverser::call($operation['method'], json_decode($operation['arguments'], true));
         $db->query('DELETE FROM yentu_history WHERE id = ?', array($operation['id']));
     }
 }
Пример #2
0
 public function run($options = array())
 {
     Yentu::greet();
     $this->db = DatabaseManipulator::create();
     $this->initializeCodeWriter();
     $files = scandir(Yentu::getPath("migrations"));
     if (count($files) > 2) {
         throw new \yentu\exceptions\CommandException("Cannot run imports. Your migrations directory is not empty");
     }
     $description = $this->db->getDescription();
     $this->code->add('begin()');
     if (isset($description['schemata'])) {
         $this->importSchemata($description['schemata']);
     }
     if (isset($description['tables'])) {
         $this->importTables($description['tables']);
     }
     if (isset($description['views'])) {
         $this->importViews($description['views']);
     }
     $this->importForeignKeys();
     $this->code->add('->end();');
     $this->newVersion = date('YmdHis', time());
     $path = Yentu::getPath("migrations/{$this->newVersion}_import.php");
     file_put_contents($path, $this->code);
     \clearice\ClearIce::output("Created `{$path}`\n");
     if (!$this->db->getAssertor()->doesTableExist('yentu_history')) {
         $this->db->createHistory();
     }
     $this->db->setVersion($this->newVersion);
     $this->db->disconnect();
     return $description;
 }
Пример #3
0
 public function setUp()
 {
     $this->testDatabase = 'yentu_rollback_test';
     parent::setup();
     $this->createDb($GLOBALS['DB_NAME']);
     $this->initDb($GLOBALS['DB_FULL_DSN'], file_get_contents("tests/sql/{$GLOBALS['DRIVER']}/pre_rollback.sql"));
     $this->connect($GLOBALS['DB_FULL_DSN']);
     $this->setupStreams();
     $init = new \yentu\commands\Init();
     $init->createConfigFile(array('driver' => $GLOBALS['DRIVER'], 'host' => $GLOBALS['DB_HOST'], 'dbname' => $GLOBALS["DB_NAME"], 'user' => $GLOBALS['DB_USER'], 'password' => $GLOBALS['DB_PASSWORD'], 'file' => $GLOBALS['DB_FILE']));
     Config::readPath(\yentu\Yentu::getPath('config'), 'yentu');
 }
Пример #4
0
 public function __construct($message)
 {
     parent::__construct($message);
     foreach ($this->getTrace() as $item) {
         if (!isset($item['file'])) {
             continue;
         }
         if (realpath(Yentu::getPath('migrations')) === dirname($item['file'])) {
             $this->message .= ". Exception was thrown by action on line {$item['line']} of {$item['file']}";
             break;
         }
     }
 }
Пример #5
0
 public function createFile($name)
 {
     $this->checkExisting($name);
     $this->checkName($name);
     $this->checkPermission();
     $timestamp = date('YmdHis', time());
     $code = new \yentu\CodeWriter();
     $code->add('');
     $code->add('begin()');
     $code->add('');
     $code->add('->end();');
     $path = Yentu::getPath("migrations/{$timestamp}_{$name}.php");
     file_put_contents($path, $code);
     \clearice\ClearIce::output("Added {$path} for new migration.\n");
 }
Пример #6
0
 private function getMigrationInfo()
 {
     $runMigrations = Yentu::getRunMirations();
     $migrations = Yentu::getAllMigrations();
     $counter['previous'] = count($runMigrations);
     end($runMigrations);
     $current = "{$runMigrations[key($runMigrations)]['timestamp']} {$runMigrations[key($runMigrations)]['migration']}";
     $run = array('previous' => array(), 'yet' => array());
     foreach ($runMigrations as $timestamp => $migration) {
         unset($migrations[$timestamp]);
         $run['previous'][] = "{$timestamp} {$migration['migration']} " . ($migration['default_schema'] == '' ? '' : "on `{$migration['default_schema']}` schema");
     }
     foreach ($migrations as $timestamp => $migration) {
         $run['yet'][] = "{$timestamp} {$migration['migration']}";
     }
     $counter['yet'] = count($run['yet']);
     return array('counter' => $counter, 'current' => $current, 'run' => $run);
 }
Пример #7
0
 private function performOperation($method, $matches, $arguments)
 {
     try {
         $return = $this->driver->{$method}($arguments[0]);
         Yentu::announce($matches['command'], $matches['item_type'], $arguments[0]);
         $this->driver->setDumpQuery(false);
         ClearIce::pushOutputLevel(ClearIce::OUTPUT_LEVEL_0);
         $this->driver->query('INSERT INTO yentu_history(session, version, method, arguments, migration, default_schema) VALUES (?,?,?,?,?,?)', array($this->session, $this->version, $method, json_encode($arguments), $this->migration, self::$defaultSchema));
         ClearIce::popOutputLevel();
         $this->changes++;
         $this->driver->setDisableQuery(false);
     } catch (\yentu\exceptions\DatabaseManipulatorException $e) {
         if ($this->skipOnErrors) {
             ClearIce::output("E");
             ClearIce::output("rror " . preg_replace("/([a-z])([A-Z])/", "\$1 \$2", $matches['item_type']) . " '" . $arguments[0]['name'] . "'\n", ClearIce::OUTPUT_LEVEL_2);
         } else {
             throw $e;
         }
     }
     return $return;
 }
Пример #8
0
    /**
     * Display the greeting for the CLI user interface.
     */
    public static function greet()
    {
        $version = Yentu::getVersion();
        $welcome = <<<WELCOME
Yentu Database Migration Tool
Version {$version}


WELCOME;
        ClearIce::output($welcome);
    }
Пример #9
0
 public function run($options = array())
 {
     global $migrateCommand;
     global $migrateVariables;
     self::fillOptions($options);
     $migrateCommand = $this;
     if ($options['dump-queries'] !== true) {
         Yentu::greet();
     }
     $this->driver = ChangeLogger::wrap(DatabaseManipulator::create());
     $this->driver->setDumpQueriesOnly($options['dump-queries']);
     $this->driver->setDryRun($options['dry']);
     $totalOperations = 0;
     $filter = self::FILTER_UNRUN;
     $this->setupOptions($options, $filter);
     DatabaseItem::setDriver($this->driver);
     \yentu\Timer::start();
     $migrationPaths = Yentu::getMigrationPathsInfo();
     foreach ($migrationPaths as $path) {
         $this->setDefaultSchema($path);
         $migrateVariables = $path['variables'];
         $migrations = $this->filter(Yentu::getMigrations($path['home']), $filter);
         $this->announceMigration($migrations, $path);
         $this->currentPath = $path;
         foreach ($migrations as $migration) {
             $this->countOperations("{$path['home']}/{$migration['file']}");
             $this->driver->setVersion($migration['timestamp']);
             $this->driver->setMigration($migration['migration']);
             ClearIce::output("\nApplying '{$migration['migration']}' migration\n");
             require "{$path['home']}/{$migration['file']}";
             DatabaseItem::purge();
             ClearIce::output("\n");
             $totalOperations += $this->driver->resetOperations();
         }
     }
     if ($this->driver->getChanges()) {
         $elapsed = \yentu\Timer::stop();
         ClearIce::output("\nMigration took " . \yentu\Timer::pretty($elapsed) . "\n");
         ClearIce::output($this->driver->getChanges() . " operations performed\n");
         ClearIce::output($totalOperations - $this->driver->getChanges() . " operations skipped\n");
     }
     $this->driver->disconnect();
 }
Пример #10
0
 protected function setupStreams()
 {
     vfsStream::setup('home');
     \yentu\Yentu::setDefaultHome(vfsStream::url('home/yentu'));
     \clearice\ClearIce::setStreamUrl('output', vfsStream::url('home/output.txt'));
 }
Пример #11
0
        $class = "\\yentu\\commands\\" . ucfirst($options['__command__']);
        unset($options['__command__']);
        Config::readPath(Yentu::getPath('config'), 'yentu');
        $command = new $class();
        $command->run($options);
    } else {
        ClearIce::output(ClearIce::getHelpMessage());
    }
} catch (\yentu\exceptions\CommandException $e) {
    ClearIce::resetOutputLevel();
    ClearIce::error("Error! " . $e->getMessage() . "\n");
} catch (\ntentan\atiaa\exceptions\DatabaseDriverException $e) {
    ClearIce::resetOutputLevel();
    ClearIce::error("Database driver failed: " . $e->getMessage() . "\n");
    Yentu::reverseCommand($command);
} catch (\yentu\exceptions\DatabaseManipulatorException $e) {
    ClearIce::resetOutputLevel();
    ClearIce::error("Failed to perform database action: " . $e->getMessage() . "\n");
    Yentu::reverseCommand($command);
} catch (\ntentan\atiaa\DescriptionException $e) {
    ClearIce::resetOutputLevel();
    ClearIce::error("Failed to perform database action: " . $e->getMessage() . "\n");
    Yentu::reverseCommand($command);
} catch (\yentu\exceptions\SyntaxErrorException $e) {
    ClearIce::resetOutputLevel();
    ClearIce::error("Error found in syntax: {$e->getMessage()}\n");
    Yentu::reverseCommand($command);
} catch (\PDOException $e) {
    ClearIce::resetOutputLevel();
    ClearIce::error("Failed to connect to database: {$e->getMessage()}\n");
}
Пример #12
0
 /**
  * @expectedException \yentu\exceptions\CommandException
  */
 public function testExistingDb()
 {
     $this->pdo->query('CREATE TABLE yentu_history(dummy INTEGER)');
     $initCommand = new \yentu\commands\Init();
     \yentu\Yentu::setDefaultHome(vfsStream::url("home/yentu"));
     $initCommand->run(array('driver' => $GLOBALS['DRIVER'], 'host' => $GLOBALS['DB_HOST'], 'dbname' => $GLOBALS['DB_NAME'], 'user' => $GLOBALS['DB_USER'], 'password' => $GLOBALS['DB_PASSWORD'], 'file' => $GLOBALS['DB_FILE']));
 }
Пример #13
0
 public function run($options = array())
 {
     Yentu::greet();
     if (file_exists(Yentu::getPath(''))) {
         throw new CommandException("Could not initialize yentu. Your project has already been initialized with yentu.");
     } else {
         if (!is_writable(dirname(Yentu::getPath('')))) {
             throw new CommandException("Your current directory is not writable.");
         }
     }
     $params = $this->getParams($options);
     if (count($params) == 0 && defined('STDOUT')) {
         global $argv;
         throw new CommandException("You didn't provide any parameters for initialization. Please execute " . "`{$argv[0]} init -i` to initialize yentu interractively. " . "You can also try `{$argv[0]} init --help` for more information.");
     }
     $this->createConfigFile($params);
     Config::readPath(Yentu::getPath('config'), 'yentu');
     $db = \yentu\DatabaseManipulator::create($params);
     if ($db->getAssertor()->doesTableExist('yentu_history')) {
         throw new CommandException("Could not initialize yentu. Your database has already been initialized with yentu.");
     }
     $db->createHistory();
     $db->disconnect();
     ClearIce::output("Yentu successfully initialized.\n");
 }