/** * @see sfTask */ protected function execute($arguments = array(), $options = array()) { $databaseManager = new sfDatabaseManager($this->configuration); $connections = $this->getConnections($databaseManager); $manager = new PropelMigrationManager(); $manager->setConnections($connections); $manager->setMigrationTable($options['migration-table']); $migrationDirectory = sfConfig::get('sf_root_dir') . DIRECTORY_SEPARATOR . $options['migration-dir']; $manager->setMigrationDir($migrationDirectory); if (!($nextMigrationTimestamp = $manager->getFirstUpMigrationTimestamp())) { $this->logSection('propel', 'All migrations were already executed - nothing to migrate.'); return false; } $this->logSection('propel', sprintf('Executing migration %s up', $manager->getMigrationClassName($nextMigrationTimestamp))); $migration = $manager->getMigrationObject($nextMigrationTimestamp); if (false === $migration->preUp($manager)) { $this->logSection('propel', 'preUp() returned false. Aborting migration.', null, 'ERROR'); return false; } foreach ($migration->getUpSQL() as $datasource => $sql) { $connection = $manager->getConnection($datasource); if ($options['verbose']) { $this->logSection('propel', sprintf(' Connecting to database "%s" using DSN "%s"', $datasource, $connection['dsn']), null, 'COMMENT'); } $pdo = $manager->getPdoConnection($datasource); $res = 0; $statements = PropelSQLParser::parseString($sql); foreach ($statements as $statement) { try { if ($options['verbose']) { $this->logSection('propel', sprintf(' Executing statement "%s"', $statement), null, 'COMMENT'); } $stmt = $pdo->prepare($statement); $stmt->execute(); $res++; } catch (PDOException $e) { $this->logSection(sprintf('Failed to execute SQL "%s". Aborting migration.', $statement), null, 'ERROR'); return false; // continue } } if (!$res) { $this->logSection('propel', 'No statement was executed. The version was not updated.'); $this->logSection('propel', sprintf('Please review the code in "%s"', $manager->getMigrationDir() . DIRECTORY_SEPARATOR . $manager->getMigrationClassName($nextMigrationTimestamp))); $this->logSection('propel', 'Migration aborted', null, 'ERROR'); return false; } $this->logSection('propel', sprintf('%d of %d SQL statements executed successfully on datasource "%s"', $res, count($statements), $datasource)); $manager->updateLatestMigrationTimestamp($datasource, $nextMigrationTimestamp); if ($options['verbose']) { $this->logSection('propel', sprintf(' Updated latest migration date to %d for datasource "%s"', $nextMigrationTimestamp, $datasource), null, 'COMMENT'); } } $migration->postUp($manager); if ($timestamps = $manager->getValidMigrationTimestamps()) { $this->logSection('propel', sprintf('Migration complete. %d migrations left to execute.', count($timestamps))); } else { $this->logSection('propel', 'Migration complete. No further migration to execute.'); } }
/** * Main method builds all the targets for a typical propel project. */ public function main() { $manager = new PropelMigrationManager(); $manager->setConnections($this->getGeneratorConfig()->getBuildConnections()); $manager->setMigrationTable($this->getMigrationTable()); $manager->setMigrationDir($this->getOutputDirectory()); $previousTimestamps = $manager->getAlreadyExecutedMigrationTimestamps(); if (!($nextMigrationTimestamp = array_pop($previousTimestamps))) { $this->log('No migration were ever executed on this database - nothing to reverse.'); return false; } $this->log(sprintf('Executing migration %s down', $manager->getMigrationClassName($nextMigrationTimestamp))); if ($nbPreviousTimestamps = count($previousTimestamps)) { $previousTimestamp = array_pop($previousTimestamps); } else { $previousTimestamp = 0; } $migration = $manager->getMigrationObject($nextMigrationTimestamp); if (false === $migration->preDown($manager)) { $this->log('preDown() returned false. Aborting migration.', Project::MSG_ERR); return false; } foreach ($migration->getDownSQL() as $datasource => $sql) { $connection = $manager->getConnection($datasource); $this->log(sprintf('Connecting to database "%s" using DSN "%s"', $datasource, $connection['dsn']), Project::MSG_VERBOSE); $pdo = $manager->getPdoConnection($datasource); $res = 0; $statements = PropelSQLParser::parseString($sql); foreach ($statements as $statement) { try { $this->log(sprintf('Executing statement "%s"', $statement), Project::MSG_VERBOSE); $stmt = $pdo->prepare($statement); $stmt->execute(); $res++; } catch (PDOException $e) { $this->log(sprintf('Failed to execute SQL "%s"', $statement), Project::MSG_ERR); // continue } } if (!$res) { $this->log('No statement was executed. The version was not updated.'); $this->log(sprintf('Please review the code in "%s"', $manager->getMigrationDir() . DIRECTORY_SEPARATOR . $manager->getMigrationClassName($nextMigrationTimestamp))); $this->log('Migration aborted', Project::MSG_ERR); return false; } $this->log(sprintf('%d of %d SQL statements executed successfully on datasource "%s"', $res, count($statements), $datasource)); $manager->updateLatestMigrationTimestamp($datasource, $previousTimestamp); $this->log(sprintf('Downgraded migration date to %d for datasource "%s"', $previousTimestamp, $datasource), Project::MSG_VERBOSE); } $migration->postDown($manager); if ($nbPreviousTimestamps) { $this->log(sprintf('Reverse migration complete. %d more migrations available for reverse.', $nbPreviousTimestamps)); } else { $this->log('Reverse migration complete. No more migration available for reverse'); } }
/** * Main method builds all the targets for a typical propel project. */ public function main() { $manager = new PropelMigrationManager(); $manager->setConnections($this->getGeneratorConfig()->getBuildConnections()); $manager->setMigrationTable($this->getMigrationTable()); $manager->setMigrationDir($this->getOutputDirectory()); if (!($nextMigrationTimestamp = $manager->getFirstUpMigrationTimestamp())) { $this->log('All migrations were already executed - nothing to migrate.'); return false; } $timestamps = $manager->getValidMigrationTimestamps(); if (count($timestamps) > 1) { $this->log(sprintf('%d migrations to execute', count($timestamps))); } foreach ($timestamps as $timestamp) { $this->log(sprintf('Executing migration %s up', $manager->getMigrationClassName($timestamp))); $migration = $manager->getMigrationObject($timestamp); if (false === $migration->preUp($manager)) { $this->log('preUp() returned false. Aborting migration.', Project::MSG_ERR); return false; } foreach ($migration->getUpSQL() as $datasource => $sql) { $connection = $manager->getConnection($datasource); $this->log(sprintf('Connecting to database "%s" using DSN "%s"', $datasource, $connection['dsn']), Project::MSG_VERBOSE); $pdo = $manager->getPdoConnection($datasource); $res = 0; $statements = PropelSQLParser::parseString($sql); foreach ($statements as $statement) { try { $this->log(sprintf('Executing statement "%s"', $statement), Project::MSG_VERBOSE); $stmt = $pdo->prepare($statement); $stmt->execute(); $res++; } catch (PDOException $e) { $this->log(sprintf('Failed to execute SQL "%s"', $statement), Project::MSG_ERR); // continue } } if (!$res) { $this->log('No statement was executed. The version was not updated.'); $this->log(sprintf('Please review the code in "%s"', $manager->getMigrationDir() . DIRECTORY_SEPARATOR . $manager->getMigrationClassName($timestamp))); $this->log('Migration aborted', Project::MSG_ERR); return false; } $this->log(sprintf('%d of %d SQL statements executed successfully on datasource "%s"', $res, count($statements), $datasource)); } // migrations for datasources have passed - update the timestamp // for all datasources foreach ($manager->getConnections() as $datasource => $connection) { $manager->updateLatestMigrationTimestamp($datasource, $timestamp); $this->log(sprintf('Updated latest migration date to %d for datasource "%s"', $timestamp, $datasource), Project::MSG_VERBOSE); } $migration->postUp($manager); } $this->log('Migration complete. No further migration to execute.'); }
public function main() { $manager = new PropelMigrationManager(); $manager->setConnections($this->getGeneratorConfig()->getBuildConnections()); $manager->setMigrationTable($this->getMigrationTable()); $manager->setMigrationDir($this->getOutputDirectory()); // the following is a verbose version of PropelMigrationManager::getValidMigrationTimestamps() // mostly for explicit output $this->log('Checking Database Versions...'); foreach ($manager->getConnections() as $datasource => $params) { $this->log(sprintf('Connecting to database "%s" using DSN "%s"', $datasource, $params['dsn']), Project::MSG_VERBOSE); if (!$manager->migrationTableExists($datasource)) { $this->log(sprintf('Migration table does not exist in datasource "%s"; creating it.', $datasource), Project::MSG_VERBOSE); $manager->createMigrationTable($datasource); } } if ($oldestMigrationTimestamp = $manager->getOldestDatabaseVersion()) { $this->log(sprintf('Latest migration was executed on %s (timestamp %d)', date('Y-m-d H:i:s', $oldestMigrationTimestamp), $oldestMigrationTimestamp), Project::MSG_VERBOSE); } else { $this->log('No migration was ever executed on these connection settings.', Project::MSG_VERBOSE); } $this->log('Listing Migration files...'); $dir = $this->getOutputDirectory(); $migrationTimestamps = $manager->getMigrationTimestamps(); $nbExistingMigrations = count($migrationTimestamps); if ($migrationTimestamps) { $this->log(sprintf('%d valid migration classes found in "%s"', $nbExistingMigrations, $dir), Project::MSG_VERBOSE); if ($validTimestamps = $manager->getValidMigrationTimestamps()) { $countValidTimestamps = count($validTimestamps); if ($countValidTimestamps == 1) { $this->log('1 migration needs to be executed:'); } else { $this->log(sprintf('%d migrations need to be executed:', $countValidTimestamps)); } } foreach ($migrationTimestamps as $timestamp) { $this->log(sprintf(' %s %s %s', $timestamp == $oldestMigrationTimestamp ? '>' : ' ', $manager->getMigrationClassName($timestamp), $timestamp <= $oldestMigrationTimestamp ? '(executed)' : ''), $timestamp <= $oldestMigrationTimestamp ? Project::MSG_VERBOSE : Project::MSG_INFO); } } else { $this->log(sprintf('No migration file found in "%s".', $dir)); $this->log('Make sure you run the sql-diff task.'); return false; } $migrationTimestamps = $manager->getValidMigrationTimestamps(); $nbNotYetExecutedMigrations = count($migrationTimestamps); if (!$nbNotYetExecutedMigrations) { $this->log('All migration files were already executed - Nothing to migrate.'); return false; } $this->log(sprintf('Call the "migrate" task to execute %s', $countValidTimestamps == 1 ? 'it' : 'them')); }
/** * Main method builds all the targets for a typical propel project. */ public function main() { // check to make sure task received all correct params $this->validate(); $generatorConfig = $this->getGeneratorConfig(); // loading model from database $this->log('Reading databases structure...'); $connections = $generatorConfig->getBuildConnections(); if (!$connections) { throw new Exception('You must define database connection settings in a buildtime-conf.xml file to use diff'); } $manager = new PropelMigrationManager(); $manager->setConnections($connections); $manager->setMigrationDir($this->getOutputDirectory()); $manager->setMigrationTable($this->getGeneratorConfig()->getBuildProperty('migrationTable')); if ($manager->hasPendingMigrations()) { throw new Exception('Uncommitted migrations have been found ; you should either execute or delete them before rerunning the \'diff\' task'); } $totalNbTables = 0; $ad = new AppData(); foreach ($connections as $name => $params) { $this->log(sprintf('Connecting to database "%s" using DSN "%s"', $name, $params['dsn']), Project::MSG_VERBOSE); $pdo = $generatorConfig->getBuildPDO($name); $database = new Database($name); $platform = $generatorConfig->getConfiguredPlatform($pdo); if (!$platform->supportsMigrations()) { $this->log(sprintf('Skipping database "%s" since vendor "%s" does not support migrations', $name, $platform->getDatabaseType())); continue; } $database->setPlatform($platform); $database->setDefaultIdMethod(IDMethod::NATIVE); $parser = $generatorConfig->getConfiguredSchemaParser($pdo); $nbTables = $parser->parse($database, $this); $ad->addDatabase($database); $totalNbTables += $nbTables; $this->log(sprintf('%d tables found in database "%s"', $nbTables, $name), Project::MSG_VERBOSE); } if ($totalNbTables) { $this->log(sprintf('%d tables found in all databases.', $totalNbTables)); } else { $this->log('No table found in all databases'); } // loading model from XML $this->packageObjectModel = true; $appDatasFromXml = $this->getDataModels(); $appDataFromXml = array_pop($appDatasFromXml); // comparing models $this->log('Comparing models...'); $migrationsUp = array(); $migrationsDown = array(); foreach ($ad->getDatabases() as $database) { $name = $database->getName(); $this->log(sprintf('Comparing database "%s"', $name), Project::MSG_VERBOSE); if (!$appDataFromXml->hasDatabase($name)) { // FIXME: tables present in database but not in XML continue; } $databaseDiff = PropelDatabaseComparator::computeDiff($database, $appDataFromXml->getDatabase($name), $this->isCaseInsensitive()); if (!$databaseDiff) { $this->log(sprintf('Same XML and database structures for datasource "%s" - no diff to generate', $name), Project::MSG_VERBOSE); continue; } $this->log(sprintf('Structure of database was modified in datasource "%s": %s', $name, $databaseDiff->getDescription())); $platform = $generatorConfig->getConfiguredPlatform(null, $name); $migrationsUp[$name] = $platform->getModifyDatabaseDDL($databaseDiff); $migrationsDown[$name] = $platform->getModifyDatabaseDDL($databaseDiff->getReverseDiff()); } if (!$migrationsUp) { $this->log('Same XML and database structures for all datasource - no diff to generate'); return; } $timestamp = time(); $migrationFileName = $manager->getMigrationFileName($timestamp); $migrationClassBody = $manager->getMigrationClassBody($migrationsUp, $migrationsDown, $timestamp); $_f = new PhingFile($this->getOutputDirectory(), $migrationFileName); file_put_contents($_f->getAbsolutePath(), $migrationClassBody); $this->log(sprintf('"%s" file successfully created in %s', $_f->getName(), $_f->getParent())); if ($editorCmd = $this->getEditorCmd()) { $this->log(sprintf('Using "%s" as text editor', $editorCmd)); shell_exec($editorCmd . ' ' . escapeshellarg($_f->getAbsolutePath())); } else { $this->log(' Please review the generated SQL statements, and add data migration code if necessary.'); $this->log(' Once the migration class is valid, call the "migrate" task to execute it.'); } }
/** * @see sfTask */ protected function execute($arguments = array(), $options = array()) { $databaseManager = new sfDatabaseManager($this->configuration); $connections = $this->getConnections($databaseManager); $manager = new PropelMigrationManager(); $manager->setConnections($connections); $manager->setMigrationTable($options['migration-table']); $migrationDirectory = sfConfig::get('sf_root_dir') . DIRECTORY_SEPARATOR . $options['migration-dir']; $manager->setMigrationDir($migrationDirectory); $this->logSection('propel', 'Checking Database Versions...'); foreach ($connections as $name => $params) { if ($options['verbose']) { $this->logSection('propel', sprintf(' Connecting to database "%s" using DSN "%s"', $name, $params['dsn']), null, 'COMMENT'); } if (!$manager->migrationTableExists($name)) { if ($options['verbose']) { $this->logSection('propel', sprintf(' Migration table does not exist in datasource "%s"; creating it.', $name), null, 'COMMENT'); } $manager->createMigrationTable($name); } } $oldestMigrationTimestamp = $manager->getOldestDatabaseVersion(); if ($options['verbose']) { if ($oldestMigrationTimestamp) { $this->logSection('propel', sprintf(' Latest migration was executed on %s (timestamp %d)', date('Y-m-d H:i:s', $oldestMigrationTimestamp), $oldestMigrationTimestamp), null, 'COMMENT'); } else { $this->logSection('propel', ' No migration was ever executed on these connection settings.', null, 'COMMENT'); } } $this->logSection('propel', 'Listing Migration files...'); $migrationTimestamps = $manager->getMigrationTimestamps(); $nbExistingMigrations = count($migrationTimestamps); if ($migrationTimestamps) { if ($options['verbose']) { $this->logSection('propel', sprintf(' %d valid migration classes found in "%s"', $nbExistingMigrations, $options['migration-dir']), null, 'COMMENT'); } if ($validTimestamps = $manager->getValidMigrationTimestamps()) { $countValidTimestamps = count($validTimestamps); if ($countValidTimestamps == 1) { $this->logSection('propel', '1 migration needs to be executed:'); } else { $this->logSection('propel', sprintf('%d migrations need to be executed:', $countValidTimestamps)); } } foreach ($migrationTimestamps as $timestamp) { if ($timestamp <= $oldestMigrationTimestamp && $options['verbose']) { $this->logSection('propel', sprintf(' %s %s (executed)', $timestamp == $oldestMigrationTimestamp ? '>' : ' ', $manager->getMigrationClassName($timestamp)), null, 'COMMENT'); } elseif ($timestamp > $oldestMigrationTimestamp) { $this->logSection('propel', sprintf(' %s', $manager->getMigrationClassName($timestamp))); } } } else { $this->logSection('propel', sprintf('No migration file found in "%s".', $options['migration-dir'])); $this->logSection('propel', 'Make sure you run the sql-diff task.'); return false; } $migrationTimestamps = $manager->getValidMigrationTimestamps(); $nbNotYetExecutedMigrations = count($migrationTimestamps); if (!$nbNotYetExecutedMigrations) { $this->logSection('propel', 'All migration files were already executed - Nothing to migrate.'); return false; } $this->logSection('propel', sprintf('Call the "propel:migrate" task to execute %s', $countValidTimestamps == 1 ? 'it' : 'them')); }