public function readDatabase() { $this->database = new Database(); $this->database->setIdentifierQuoting(true); $this->database->setPlatform($this->platform); $this->parser->parse($this->database); }
public function readDatabase() { $this->database = new Database(); $this->database->setSchema('migration'); $this->database->setPlatform($this->platform); $this->parser->parse($this->database); }
public function testParse() { $parser = new MysqlSchemaParser(Propel::getConnection('reverse-bookstore')); $parser->setGeneratorConfig(new QuickGeneratorConfig()); $database = new Database(); $database->setPlatform(new DefaultPlatform()); $this->assertEquals(1, $parser->parse($database), 'One table and one view defined should return one as we exclude views'); $tables = $database->getTables(); $this->assertEquals(1, count($tables)); $table = $tables[0]; $this->assertEquals('Book', $table->getPhpName()); $this->assertEquals(4, count($table->getColumns())); }
public function testTableInheritsSchema() { $database = new Database(); $database->setPlatform(new SchemaPlatform()); $database->setSchema("Foo"); $table = new Table("Bar"); $database->addTable($table); $this->assertTrue($database->hasTable("Foo.Bar")); $this->assertFalse($database->hasTable("Bar")); $database = new Database(); $database->setPlatform(new NoSchemaPlatform()); $database->addTable($table); $this->assertFalse($database->hasTable("Foo.Bar")); $this->assertTrue($database->hasTable("Bar")); }
/** * @dataProvider parseDataProvider */ public function testParse($columnDDL, $expectedColumnPhpName, $expectedColumnDefaultType, $expectedColumnDefaultValue, $expectedSize, $expectedScale) { $this->con->query("create table foo ( {$columnDDL} );"); $parser = new PgsqlSchemaParser($this->con); $parser->setGeneratorConfig(new QuickGeneratorConfig()); $database = new Database(); $database->setPlatform(new DefaultPlatform()); // make sure our DDL insert produced exactly the SQL we inserted $this->assertGreaterThanOrEqual(1, $parser->parse($database), 'We parsed at least one table.'); $table = $database->getTable('foo'); $columns = $table->getColumns(); $this->assertEquals(1, count($columns)); // check out our rev-eng column info $defaultValue = $columns[0]->getDefaultValue(); $this->assertEquals($expectedColumnPhpName, $columns[0]->getPhpName()); $this->assertEquals($expectedColumnDefaultType, $defaultValue->getType()); $this->assertEquals($expectedColumnDefaultValue, $defaultValue->getValue()); $this->assertEquals($expectedSize, $columns[0]->getSize()); $this->assertEquals($expectedScale, $columns[0]->getScale()); }
/** * Builds the model classes from the database schema. * * @return Database The built-out Database (with all tables, etc.) */ protected function buildModel() { $config = $this->getGeneratorConfig(); $connection = $this->getConnection(); $databaseName = $config->getConfigProperty('reverse.connection'); $database = new Database($this->getDatabaseName()); $database->setPlatform($config->getConfiguredPlatform($connection), $databaseName); $database->setDefaultIdMethod(IdMethod::NATIVE); $buildConnection = $config->getBuildConnection($databaseName); $this->log(sprintf('Reading database structure of database `%s` using dsn `%s`', $this->getDatabaseName(), $buildConnection['dsn'])); $parser = $config->getConfiguredSchemaParser($connection, $databaseName); $this->log(sprintf('SchemaParser `%s` chosen', get_class($parser))); $nbTables = $parser->parse($database); $excludeTables = $config->getConfigProperty('exclude_tables'); $tables = []; foreach ($database->getTables() as $table) { /* Was copypasted from DatabaseComparator::isTableExcluded() */ $skip = false; $tablename = $table->getName(); if (in_array($tablename, $excludeTables)) { $skip = true; } else { foreach ($excludeTables as $exclude_tablename) { if (preg_match('/^' . str_replace('*', '.*', $exclude_tablename) . '$/', $tablename)) { $skip = true; } } } $skip && $database->removeTable($table); } $this->log(sprintf('Successfully reverse engineered %d tables', $nbTables)); return $database; }
public function testGetColumnDDLAutoIncrement() { $database = new Database(); $database->setPlatform($this->getPlatform()); $table = new Table('foo_table'); $table->setIdMethod(IdMethod::NATIVE); $database->addTable($table); $column = new Column('foo'); $column->getDomain()->copy($this->getPlatform()->getDomainForType(PropelTypes::BIGINT)); $column->setAutoIncrement(true); $table->addColumn($column); $expected = 'foo bigserial'; $this->assertEquals($expected, $this->getPlatform()->getColumnDDL($column)); }
/** * Builds the model classes from the database schema. * * @return Database The built-out Database (with all tables, etc.) */ protected function buildModel() { $config = $this->getGeneratorConfig(); $connection = $this->getConnection(); $this->log('Reading database structure...'); $database = new Database($this->getDatabaseName()); $database->setPlatform($config->getConfiguredPlatform($connection)); $database->setDefaultIdMethod(IdMethod::NATIVE); $parser = $config->getConfiguredSchemaParser($connection); $nbTables = $parser->parse($database); $this->log(sprintf('Successfully reverse engineered %d tables', $nbTables)); return $database; }
public function testQualifiedName() { $table = new Table(); $table->setSchema("foo"); $table->setCommonName("bar"); $this->assertEquals($table->getName(), "bar"); $this->assertEquals($table->getCommonName(), "bar"); $database = new Database(); $database->addTable($table); $database->setPlatform(new NoSchemaPlatform()); $this->assertEquals($table->getName(), "bar"); $database->setPlatform(new SchemaPlatform()); $this->assertEquals($table->getName(), "foo.bar"); }
public function testCompareModifiedFks() { $db1 = new Database(); $db1->setPlatform($this->platform); $c1 = new Column('Foo'); $c2 = new Column('Bar'); $fk1 = new ForeignKey(); $fk1->addReference($c1, $c2); $t1 = new Table('Baz'); $t1->addForeignKey($fk1); $db1->addTable($t1); $t1->doNaming(); $db2 = new Database(); $db2->setPlatform($this->platform); $c3 = new Column('Foo'); $c4 = new Column('Bar2'); $fk2 = new ForeignKey(); $fk2->addReference($c3, $c4); $t2 = new Table('Baz'); $t2->addForeignKey($fk2); $db2->addTable($t2); $t2->doNaming(); $tc = new TableComparator(); $tc->setFromTable($t1); $tc->setToTable($t2); $nbDiffs = $tc->compareForeignKeys(); $tableDiff = $tc->getTableDiff(); $this->assertEquals(1, $nbDiffs); $this->assertEquals(1, count($tableDiff->getModifiedFks())); $this->assertEquals(array('Baz_FK_1' => array($fk1, $fk2)), $tableDiff->getModifiedFks()); }
public function testHasPlatform() { $column = new Column(); $this->assertFalse($column->hasPlatform()); $table = new Table(); $table->addColumn($column); $this->assertFalse($column->hasPlatform()); $database = new Database(); $database->addTable($table); $this->assertFalse($column->hasPlatform()); $platform = new DefaultPlatform(); $database->setPlatform($platform); $this->assertTrue($column->hasPlatform()); }
public function testAddTableWithSameNameOnDifferentSchema() { $db = new Database(); $db->setPlatform(new PgsqlPlatform()); $t1 = new Table('t1'); $db->addTable($t1); $this->assertEquals('t1', $t1->getName()); $t1b = new Table('t1'); $t1b->setSchema('bis'); $db->addTable($t1b); $this->assertEquals('bis.t1', $t1b->getName()); }
/** * Builds the model classes from the database schema. * * @return Database The built-out Database (with all tables, etc.) */ protected function buildModel() { $config = $this->getGeneratorConfig(); $connection = $this->getConnection(); $databaseName = $config->getConfigProperty('reverse.connection'); $database = new Database($this->getDatabaseName()); $database->setPlatform($config->getConfiguredPlatform($connection), $databaseName); $database->setDefaultIdMethod(IdMethod::NATIVE); $buildConnection = $config->getBuildConnection($databaseName); $this->log(sprintf('Reading database structure of database `%s` using dsn `%s`', $this->getDatabaseName(), $buildConnection['dsn'])); $parser = $config->getConfiguredSchemaParser($connection, $databaseName); $this->log(sprintf('SchemaParser `%s` chosen', get_class($parser))); $nbTables = $parser->parse($database); $this->log(sprintf('Successfully reverse engineered %d tables', $nbTables)); return $database; }
/** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { $generatorConfig = $this->getGeneratorConfig(array('propel.platform.class' => $input->getOption('platform'), 'propel.reverse.parser.class' => $this->getReverseClass($input), 'propel.migration.table' => $input->getOption('migration-table')), $input); $this->createDirectory($input->getOption('output-dir')); $manager = new MigrationManager(); $manager->setGeneratorConfig($generatorConfig); $manager->setSchemas($this->getSchemas($input->getOption('input-dir'))); $connections = array(); $optionConnections = $input->getOption('connection'); if (!$optionConnections) { $connections = $generatorConfig->getBuildConnections($input->getOption('input-dir')); } else { foreach ($optionConnections as $connection) { list($name, $dsn, $infos) = $this->parseConnection($connection); $connections[$name] = array_merge(array('dsn' => $dsn), $infos); } } $manager->setConnections($connections); $manager->setMigrationTable($input->getOption('migration-table')); $manager->setWorkingDirectory($input->getOption('output-dir')); if ($manager->hasPendingMigrations()) { throw new RuntimeException('Uncommitted migrations have been found ; you should either execute or delete them before rerunning the \'diff\' task'); } $totalNbTables = 0; $schema = new Schema(); foreach ($connections as $name => $params) { if ($input->getOption('verbose')) { $output->writeln(sprintf('Connecting to database "%s" using DSN "%s"', $name, $params['dsn'])); } $conn = $manager->getAdapterConnection($name); $platform = $generatorConfig->getConfiguredPlatform($conn, $name); if (!$platform->supportsMigrations()) { $output->writeln(sprintf('Skipping database "%s" since vendor "%s" does not support migrations', $name, $platform->getDatabaseType())); continue; } $database = new Database($name); $database->setPlatform($platform); $database->setDefaultIdMethod(IdMethod::NATIVE); $parser = $generatorConfig->getConfiguredSchemaParser($conn); $nbTables = $parser->parse($database, $this); $schema->addDatabase($database); $totalNbTables += $nbTables; if ($input->getOption('verbose')) { $output->writeln(sprintf('%d tables found in database "%s"', $nbTables, $name), Output::VERBOSITY_VERBOSE); } } if ($totalNbTables) { $output->writeln(sprintf('%d tables found in all databases.', $totalNbTables)); } else { $output->writeln('No table found in all databases'); } $appDatasFromXml = $manager->getDataModels(); $appDataFromXml = array_pop($appDatasFromXml); // comparing models $output->writeln('Comparing models...'); $migrationsUp = array(); $migrationsDown = array(); foreach ($schema->getDatabases() as $database) { $name = $database->getName(); if ($input->getOption('verbose')) { $output->writeln(sprintf('Comparing database "%s"', $name)); } if (!$appDataFromXml->hasDatabase($name)) { // FIXME: tables present in database but not in XML continue; } $databaseDiff = DatabaseComparator::computeDiff($database, $appDataFromXml->getDatabase($name)); if (!$databaseDiff) { if ($input->getOption('verbose')) { $output->writeln(sprintf('Same XML and database structures for datasource "%s" - no diff to generate', $name)); } continue; } $output->writeln(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) { $output->writeln('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); $file = $input->getOption('output-dir') . DIRECTORY_SEPARATOR . $migrationFileName; file_put_contents($file, $migrationClassBody); $output->writeln(sprintf('"%s" file successfully created.', $file)); if (null !== ($editorCmd = $input->getOption('editor'))) { $output->writeln(sprintf('Using "%s" as text editor', $editorCmd)); shell_exec($editorCmd . ' ' . escapeshellarg($file)); } else { $output->writeln('Please review the generated SQL statements, and add data migration code if necessary.'); $output->writeln('Once the migration class is valid, call the "migrate" task to execute it.'); } }
/** * @return Database */ public function readConnectedDatabase() { $this->getDatabase(); $database = new Database(); $database->setSchema($this->database->getSchema()); $database->setName($this->database->getName()); $database->setPlatform($this->getPlatform()); $this->getParser()->parse($database); return $database; }
public function createMigrationTable($datasource) { $platform = $this->getPlatform($datasource); // modelize the table $database = new Database($datasource); $database->setPlatform($platform); $table = new Table($this->getMigrationTable()); $database->addTable($table); $column = new Column('version'); $column->getDomain()->copy($platform->getDomainForType('INTEGER')); $column->setDefaultValue(0); $table->addColumn($column); // insert the table into the database $statements = $platform->getAddTableDDL($table); $conn = $this->getAdapterConnection($datasource); $res = SqlParser::executeString($statements, $conn); if (!$res) { throw new \Exception(sprintf('Unable to create migration table in datasource "%s"', $datasource)); } }
/** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { $configOptions = []; if ($this->hasInputOption('connection', $input)) { foreach ($input->getOption('connection') as $conn) { $configOptions += $this->connectionToProperties($conn); } } if ($this->hasInputOption('migration-table', $input)) { $configOptions['propel']['migrations']['tableName'] = $input->getOption('migration-table'); } if ($this->hasInputOption('schema-dir', $input)) { $configOptions['propel']['paths']['schemaDir'] = $input->getOption('schema-dir'); } if ($this->hasInputOption('output-dir', $input)) { $configOptions['propel']['paths']['migrationDir'] = $input->getOption('output-dir'); } $generatorConfig = $this->getGeneratorConfig($configOptions, $input); $this->createDirectory($generatorConfig->getSection('paths')['migrationDir']); $manager = new MigrationManager(); $manager->setGeneratorConfig($generatorConfig); $manager->setSchemas($this->getSchemas($generatorConfig->getSection('paths')['schemaDir'], $input->getOption('recursive'))); $connections = []; $optionConnections = $input->getOption('connection'); if (!$optionConnections) { $connections = $generatorConfig->getBuildConnections(); } else { foreach ($optionConnections as $connection) { list($name, $dsn, $infos) = $this->parseConnection($connection); $connections[$name] = array_merge(['dsn' => $dsn], $infos); } } $manager->setConnections($connections); $manager->setMigrationTable($generatorConfig->getConfigProperty('migrations.tableName')); $manager->setWorkingDirectory($generatorConfig->getSection('paths')['migrationDir']); if ($manager->hasPendingMigrations()) { throw new RuntimeException('Uncommitted migrations have been found ; you should either execute or delete them before rerunning the \'diff\' task'); } $totalNbTables = 0; $reversedSchema = new Schema(); foreach ($manager->getDatabases() as $appDatabase) { $name = $appDatabase->getName(); if (!($params = @$connections[$name])) { $output->writeln(sprintf('<info>No connection configured for database "%s"</info>', $name)); } if ($input->getOption('verbose')) { $output->writeln(sprintf('Connecting to database "%s" using DSN "%s"', $name, $params['dsn'])); } $conn = $manager->getAdapterConnection($name); $platform = $generatorConfig->getConfiguredPlatform($conn, $name); if (!$platform->supportsMigrations()) { $output->writeln(sprintf('Skipping database "%s" since vendor "%s" does not support migrations', $name, $platform->getDatabaseType())); continue; } $additionalTables = []; foreach ($appDatabase->getTables() as $table) { if ($table->getSchema() && $table->getSchema() != $appDatabase->getSchema()) { $additionalTables[] = $table; } } if ($input->getOption('disable-identifier-quoting')) { $platform->setIdentifierQuoting(false); } $database = new Database($name); $database->setPlatform($platform); $database->setSchema($appDatabase->getSchema()); $database->setDefaultIdMethod(IdMethod::NATIVE); $parser = $generatorConfig->getConfiguredSchemaParser($conn, $name); $nbTables = $parser->parse($database, $additionalTables); $reversedSchema->addDatabase($database); $totalNbTables += $nbTables; if ($input->getOption('verbose')) { $output->writeln(sprintf('%d tables found in database "%s"', $nbTables, $name), Output::VERBOSITY_VERBOSE); } } if ($totalNbTables) { $output->writeln(sprintf('%d tables found in all databases.', $totalNbTables)); } else { $output->writeln('No table found in all databases'); } // comparing models $output->writeln('Comparing models...'); $tableRenaming = $input->getOption('table-renaming'); $migrationsUp = []; $migrationsDown = []; $removeTable = !$input->getOption('skip-removed-table'); $excludedTables = $input->getOption('skip-tables'); foreach ($reversedSchema->getDatabases() as $database) { $name = $database->getName(); if ($input->getOption('verbose')) { $output->writeln(sprintf('Comparing database "%s"', $name)); } if (!($appDataDatabase = $manager->getDatabase($name))) { $output->writeln(sprintf('<error>Database "%s" does not exist in schema.xml. Skipped.</error>', $name)); continue; } $configManager = new ConfigurationManager(); $excludedTables = array_merge((array) $excludedTables, (array) $configManager->getSection('exclude_tables')); $databaseDiff = DatabaseComparator::computeDiff($database, $appDataDatabase, false, $tableRenaming, $removeTable, $excludedTables); if (!$databaseDiff) { if ($input->getOption('verbose')) { $output->writeln(sprintf('Same XML and database structures for datasource "%s" - no diff to generate', $name)); } continue; } $output->writeln(sprintf('Structure of database was modified in datasource "%s": %s', $name, $databaseDiff->getDescription())); foreach ($databaseDiff->getPossibleRenamedTables() as $fromTableName => $toTableName) { $output->writeln(sprintf('<info>Possible table renaming detected: "%s" to "%s". It will be deleted and recreated. Use --table-renaming to only rename it.</info>', $fromTableName, $toTableName)); } $conn = $manager->getAdapterConnection($name); $platform = $generatorConfig->getConfiguredPlatform($conn, $name); if ($input->getOption('disable-identifier-quoting')) { $platform->setIdentifierQuoting(false); } $migrationsUp[$name] = $platform->getModifyDatabaseDDL($databaseDiff); $migrationsDown[$name] = $platform->getModifyDatabaseDDL($databaseDiff->getReverseDiff()); } if (!$migrationsUp) { $output->writeln('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, $input->getOption('comment')); $file = $generatorConfig->getSection('paths')['migrationDir'] . DIRECTORY_SEPARATOR . $migrationFileName; file_put_contents($file, $migrationClassBody); $output->writeln(sprintf('"%s" file successfully created.', $file)); if (null !== ($editorCmd = $input->getOption('editor'))) { $output->writeln(sprintf('Using "%s" as text editor', $editorCmd)); shell_exec($editorCmd . ' ' . escapeshellarg($file)); } else { $output->writeln('Please review the generated SQL statements, and add data migration code if necessary.'); $output->writeln('Once the migration class is valid, call the "migrate" task to execute it.'); } }
/** * Adds a database to the list and sets the Schema property to this * Schema. The database can be specified as a Database object or a * DOMNode object. * * @param Database|array $database * @return Database */ public function addDatabase($database) { if ($database instanceof Database) { $platform = null; $database->setParentSchema($this); if (null === $database->getPlatform()) { if ($config = $this->getGeneratorConfig()) { $platform = $config->getConfiguredPlatform(null, $database->getName()); } $database->setPlatform($platform ? $platform : $this->platform); } $this->databases[] = $database; return $database; } // XML attributes array / hash $db = new Database(); $db->setParentSchema($this); $db->loadMapping($database); return $this->addDatabase($db); }
public function testAutoNamespaceToDatabaseSchemaName() { $yamlConf = <<<EOF propel: database: connections: mysource: adapter: mysql classname: Propel\\Runtime\\Connection\\DebugPDO dsn: mysql:host=localhost;dbname=mydb user: root password: generator: schema: autoNamespace: true EOF; $configFilename = sys_get_temp_dir() . '/propel.yml'; $filesystem = new Filesystem(); $filesystem->dumpFile($configFilename, $yamlConf); $schema = 'TestSchema'; $config = new GeneratorConfig($configFilename); $platform = new MysqlPlatform(); $parentSchema = new Schema($platform); $parentSchema->setGeneratorConfig($config); $db = new Database(); $db->setPlatform($platform); $db->setParentSchema($parentSchema); $db->setSchema($schema); $this->assertEquals($schema, $db->getNamespace()); }