protected function execute(InputInterface $input, OutputInterface $output) { $ymlParser = new Parser(); $config = $ymlParser->parse(file_get_contents($input->getOption('config'))); $directoryIterator = new RegexIterator(new DirectoryIterator($config['path']), '/.php$/'); $versionTable = $config['version_table']; foreach ($this->getConnections($config) as $connection) { if (!$connection->getSchemaManager()->tablesExist($versionTable)) { $schema = $connection->getSchemaManager()->createSchema(); $table = $schema->createTable($versionTable); $table->addColumn('id', 'integer', array('autoincrement')); $table->addColumn('name', 'string', array('notnull', 'customSchemaOptions' => array('unique'))); $table->addColumn('status', 'integer'); $table->addColumn('error', 'string'); $diff = new SchemaDiff(array($table)); $queries = $diff->toSql($connection->getDatabasePlatform()); foreach ($queries as $query) { $connection->exec($query); } } foreach ($directoryIterator as $classFile) { if ($classFile->isDot()) { continue; } $fileName = $classFile->getPathname(); require_once $fileName; $reflection = new FileReflection($classFile->getPathname()); $migration = $reflection->getClass()->newInstance(); $executed = (bool) $connection->createQueryBuilder()->select(array('count(1)'))->from($versionTable)->where('name = :name')->setParameter('name', $fileName)->setMaxResults(1)->execute()->fetchColumn(); if (!$executed) { $output->writeln("<info>executing migration {$fileName}</info>"); try { $connection->exec($migration->getUpSql()); $output->writeln("<info>{$fileName} executed succesfuly!</info>"); } catch (Exception $exception) { $connection->createQueryBuilder()->insert($versionTable)->values(array('name' => ":name", 'status' => 2, 'error' => ":error"))->setParameter('error', $exception->getMessage())->setParameter('name', $fileName)->execute(); $output->writeln("<error>error executing migration {$fileName}</error>"); $output->writeln("<error>{$exception->getMessage()}</error>"); continue; } $connection->createQueryBuilder()->insert($versionTable)->values(array('name' => ":name", 'status' => 1))->setParameter('name', $fileName)->execute(); } } } }
/** * Fix mime types */ public function run() { if (!$this->connection->getDatabasePlatform() instanceof SqlitePlatform) { return; } $sourceSchema = $this->connection->getSchemaManager()->createSchema(); $schemaDiff = new SchemaDiff(); foreach ($sourceSchema->getTables() as $tableSchema) { $primaryKey = $tableSchema->getPrimaryKey(); if (!$primaryKey) { continue; } $columnNames = $primaryKey->getColumns(); // add a column diff for every primary key column, // but do not actually change anything, this will // force the generation of SQL statements to alter // those tables, which will then trigger the // specific SQL code from OCSqlitePlatform try { $tableDiff = new TableDiff($tableSchema->getName()); $tableDiff->fromTable = $tableSchema; foreach ($columnNames as $columnName) { $columnSchema = $tableSchema->getColumn($columnName); $columnDiff = new ColumnDiff($columnSchema->getName(), $columnSchema); $tableDiff->changedColumns[] = $columnDiff; $schemaDiff->changedTables[] = $tableDiff; } } catch (SchemaException $e) { // ignore } } $this->connection->beginTransaction(); foreach ($schemaDiff->toSql($this->connection->getDatabasePlatform()) as $sql) { $this->connection->query($sql); } $this->connection->commit(); }
public function toSql(\Doctrine\DBAL\Schema\SchemaDiff $schema) { return $schema->toSaveSql($this->getPlatform()); //return $schema->toSql($this->getPlatform()); //it can return with DROP TABLE }
/** * @param \Doctrine\DBAL\Schema\Schema|\Doctrine\DBAL\Schema\SchemaDiff $schema * @return bool */ private function executeSchemaChange($schema) { $this->conn->beginTransaction(); foreach ($schema->toSql($this->conn->getDatabasePlatform()) as $sql) { $this->conn->query($sql); } $this->conn->commit(); if ($this->conn->getDatabasePlatform() instanceof SqlitePlatform) { $this->conn->close(); $this->conn->connect(); } return true; }
/** * Installs the database tables for all entity classes contained within the * $metadatas array. Returns true if new tables were created or existing * ones altered. Otherwise this will return false if there were no database * migrations needed. * * @param array $metadatas * * @return bool */ public function installDatabaseFor(array $metadatas) { if (count($metadatas) > 0) { // We need to create the SchemaDiff manually here because we want // to avoid calling the execution for two separate SchemaDiff // objects (one for missing tables and one for new ones). // Also, while $tool->createSchema($missingEntities) works great // for new tables, $tool->updateSchema($updateEntities) would // actually delete all the DB tables that the DB contains and are // not part of the entity tables passed to the function. Therefore, // we do this manually here. $em = $this->getEntityManager(); $conn = $em->getConnection(); $sm = $conn->getSchemaManager(); $cmf = $em->getMetadataFactory(); $tool = new \Doctrine\ORM\Tools\SchemaTool($em); $comparator = new \Doctrine\DBAL\Schema\Comparator(); // NOTE: $newSchema != $toSchema because $toSchema would actually // contain each and every table in the database. We'll only need // to traverse the $newSchema for the purposes of the desired // functionality but we also need $fromSchema to check whether // the table already exists and also to get the current schema // for that table to figure out the changes to the new table. $fromSchema = $sm->createSchema(); $newSchema = $tool->getSchemaFromMetadata($metadatas); $newTables = array(); $changedTables = array(); foreach ($newSchema->getTables() as $newTable) { // Check if the table already exists if ($fromSchema->hasTable($newTable->getName())) { $diff = $comparator->diffTable($fromSchema->getTable($newTable->getName()), $newTable); if ($diff) { $changedTables[] = $diff; } } else { $newTables[] = $newTable; } } if (count($newTables) > 0 || count($changedTables) > 0) { // If we have new or changed tables (or both), we'll gather // these DB changes into a SchemaDiff object and get all the // necessary DB migration queries for that diff object. // Finally, those queries are executed against the DB. $schemaDiff = new SchemaDiff($newTables, $changedTables); $platform = $conn->getDatabasePlatform(); $migrateSql = $schemaDiff->toSql($platform); foreach ($migrateSql as $sql) { $conn->executeQuery($sql); } return true; } } return false; }