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")); }
public function testDescColumn() { $schema = '<database name="reverse_bookstore"><table name="book"><column name="title" type="VARCHAR" size="255" description="Book Title with accent éà i" /></table></database>'; $xtad = new XmlToAppData(); $appData = $xtad->parseString($schema); $database = $appData->getDatabase(); $table = $database->getTable('book'); $c1 = $table->getColumn('title'); $parser = new MysqlSchemaParser(Propel::getConnection('reverse-bookstore')); $parser->setGeneratorConfig(new QuickGeneratorConfig()); $database = new Database(); $database->setPlatform(new DefaultPlatform()); $parser->parse($database); $c2 = $database->getTable('book')->getColumn('title'); $this->assertEquals($c1->getDescription(), $c2->getDescription()); }
public function testDecimal() { $t1 = new Table('foo'); $schema = '<database name="reverse_bookstore"><table name="foo"><column name="longitude" type="DECIMAL" scale="7" size="10" /></table></database>'; $xtad = new XmlToAppData(); $appData = $xtad->parseString($schema); $database = $appData->getDatabase(); $table = $database->getTable('foo'); $c1 = $table->getColumn('longitude'); $parser = new MysqlSchemaParser(Propel::getConnection('reverse-bookstore')); $parser->setGeneratorConfig(new QuickGeneratorConfig()); $database = new Database(); $database->setPlatform(new MysqlPlatform()); $parser->parse($database); $table = $database->getTable('foo'); $c2 = $table->getColumn('longitude'); $this->assertEquals($c1->getSize(), $c2->getSize()); $this->assertEquals($c1->getScale(), $c2->getScale()); }
/** * @dataProvider parseDataProvider */ public function testParse($columnDDL, $expectedColumnPhpName, $expectedColumnDefaultType, $expectedColumnDefaultValue) { $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->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]; $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()); }
/** * 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'); } $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); $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 imported from database "%s"', $nbTables, $name), Project::MSG_VERBOSE); } if ($totalNbTables) { $this->log(sprintf('%d tables imported from databases.', $totalNbTables)); } else { $this->log('Database is empty'); } // loading model from XML $this->packageObjectModel = true; $appDatasFromXml = $this->getDataModels(); $appDataFromXml = array_pop($appDatasFromXml); // comparing models $this->log('Comparing models...'); $manager = new PropelMigrationManager(); $manager->setConnections($connections); $manager->setMigrationDir($this->getOutputDirectory()); $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.'); } }
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 PropelTableComparator(); $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()); }
/** * @return Database */ function getDatabaseSchema() { ClassLoader::import('DATABASE:propel:'); ClassLoader::import('DATABASE:propel:model'); ClassLoader::import('DATABASE:propel:reverse'); ClassLoader::import('DATABASE:propel:reverse:mssql'); ClassLoader::import('DATABASE:propel:platform'); $parser = new MssqlSchemaParser($this); $database = new Database($this->getDBName()); $database->setPlatform(new MssqlPlatform($this)); $parser->parse($database); $database->doFinalInitialization(); return $database; }
public function readDatabase() { $this->database = new Database(); $this->database->setPlatform(new MysqlPlatform()); $this->parser->parse($this->database); }
/** * @see sfTask */ protected function execute($arguments = array(), $options = array()) { $databaseManager = new sfDatabaseManager($this->configuration); $connections = $this->getConnections($databaseManager); $this->logSection('propel', 'Reading databases structure...'); $ad = new AppData(); $totalNbTables = 0; foreach ($connections as $name => $params) { if ($options['verbose']) { $this->logSection('propel', sprintf(' Connecting to database "%s" using DSN "%s"', $name, $params['dsn']), null, 'COMMENT'); } $pdo = $databaseManager->getDatabase($name)->getConnection(); $database = new Database($name); $platform = $this->getPlatform($databaseManager, $name); $database->setPlatform($platform); $database->setDefaultIdMethod(IDMethod::NATIVE); $parser = $this->getParser($databaseManager, $name, $pdo); $parser->setMigrationTable($options['migration-table']); $parser->setPlatform($platform); $nbTables = $parser->parse($database); $ad->addDatabase($database); $totalNbTables += $nbTables; if ($options['verbose']) { $this->logSection('propel', sprintf(' %d tables imported from database "%s"', $nbTables, $name), null, 'COMMENT'); } } if ($totalNbTables) { $this->logSection('propel', sprintf('%d tables imported from databases.', $totalNbTables)); } else { $this->logSection('propel', 'Database is empty'); } $this->logSection('propel', 'Loading XML schema files...'); Phing::startup(); // required to locate behavior classes... $this->schemaToXML(self::DO_NOT_CHECK_SCHEMA, 'generated-'); $this->copyXmlSchemaFromPlugins('generated-'); $appData = $this->getModels($databaseManager, $options['verbose']); $this->logSection('propel', sprintf('%d tables defined in the schema files.', $appData->countTables())); $this->cleanup($options['verbose']); $this->logSection('propel', 'Comparing databases and schemas...'); $manager = new PropelMigrationManager(); $manager->setConnections($connections); $migrationsUp = array(); $migrationsDown = array(); foreach ($ad->getDatabases() as $database) { $name = $database->getName(); if ($options['verbose']) { $this->logSection('propel', sprintf(' Comparing database "%s"', $name), null, 'COMMENT'); } if (!$appData->hasDatabase($name)) { // FIXME: tables present in database but not in XML continue; } $databaseDiff = PropelDatabaseComparator::computeDiff($database, $appData->getDatabase($name)); if (!$databaseDiff) { if ($options['verbose']) { $this->logSection('propel', sprintf(' Same XML and database structures for datasource "%s" - no diff to generate', $name), null, 'COMMENT'); } continue; } $this->logSection('propel', sprintf('Structure of database was modified in datasource "%s": %s', $name, $databaseDiff->getDescription())); if ($options['verbose']) { $this->logBlock($databaseDiff, 'COMMENT'); } $platform = $this->getPlatform($databaseManager, $name); $migrationsUp[$name] = $platform->getModifyDatabaseDDL($databaseDiff); $migrationsDown[$name] = $platform->getModifyDatabaseDDL($databaseDiff->getReverseDiff()); } if (!$migrationsUp) { $this->logSection('propel', 'Same XML and database structures for all datasources - no diff to generate'); return; } $timestamp = time(); $migrationDirectory = sfConfig::get('sf_root_dir') . DIRECTORY_SEPARATOR . $options['migration-dir']; $migrationFileName = $manager->getMigrationFileName($timestamp); $migrationFilePath = $migrationDirectory . DIRECTORY_SEPARATOR . $migrationFileName; if ($options['ask-confirmation'] && !$this->askConfirmation(array(sprintf('Migration class will be generated in %s', $migrationFilePath), 'Are you sure you want to proceed? (Y/n)'), 'QUESTION_LARGE', true)) { $this->logSection('propel', 'Task aborted.'); return 1; } $this->getFilesystem()->mkdirs($migrationDirectory); $migrationClassBody = $manager->getMigrationClassBody($migrationsUp, $migrationsDown, $timestamp); file_put_contents($migrationFilePath, $migrationClassBody); $this->logSection('propel', sprintf('"%s" file successfully created in %s', $migrationFileName, $migrationDirectory)); if ($editorCmd = $options['editor-cmd']) { $this->logSection('propel', sprintf('Using "%s" as text editor', $editorCmd)); shell_exec($editorCmd . ' ' . escapeshellarg($migrationFilePath)); } else { $this->logSection('propel', ' Please review the generated SQL statements, and add data migration code if necessary.'); $this->logSection('propel', ' Once the migration class is valid, call the "propel:migrate" task to execute it.'); } }
/** * @return Database */ function getDatabaseSchema() { ClassLoader::import('DATABASE:propel:'); ClassLoader::import('DATABASE:propel:model'); ClassLoader::import('DATABASE:propel:reverse'); ClassLoader::import('DATABASE:propel:reverse:access'); ClassLoader::import('DATABASE:propel:platform'); $parser = new AccessSchemaParser($this); $database = new Database($this->getDBName()); $platform = new AccessPlatform($this); $platform->setDefaultTableEngine('InnoDB'); $database->setPlatform($platform); $parser->parse($database); $database->doFinalInitialization(); 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); $pdo = $this->getPdoConnection($datasource); $res = PropelSQLParser::executeString($statements, $pdo); if (!$res) { throw new Exception(sprintf('Unable to create migration table in datasource "%s"', $datasource)); } }
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(); $con = $this->getConnection(); $this->log('Reading database structure...'); $database = new Database($this->getDatabaseName()); $database->setPlatform($config->getConfiguredPlatform($con)); $database->setDefaultIdMethod(IdMethod::NATIVE); $parser = $config->getConfiguredSchemaParser($con); $nbTables = $parser->parse($database, $this); $this->log(sprintf('Successfully reverse engineered %d tables', $nbTables)); return $database; }
public function testAddTableWithSameNameOnDifferentSchema() { $db = new Database(); $db->setPlatform(new SchemaPlatform()); $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()); }
/** * Add a database to the list and sets the AppData property to this * AppData * * @param db the database to add */ public function addDatabase($db) { if ($db instanceof Database) { $db->setAppData($this); if ($db->getPlatform() === null) { $db->setPlatform($this->platform); } $this->dbList[] = $db; return $db; } else { // XML attributes array / hash $d = new Database(); $d->setAppData($this); if ($d->getPlatform() === null) { $d->setPlatform($this->platform); } $d->loadFromXML($db); return $this->addDatabase($d); // calls self w/ different param type } }
/** * Add a database to the list and sets the AppData property to this * AppData * * @param Database|string $db the database to add * * @return Database */ public function addDatabase($db) { if ($db instanceof Database) { $db->setAppData($this); if ($db->getPlatform() === null) { if ($config = $this->getGeneratorConfig()) { $pf = $config->getConfiguredPlatform(null, $db->getName()); $db->setPlatform($pf ? $pf : $this->platform); } else { $db->setPlatform($this->platform); } } $this->dbList[] = $db; return $db; } else { // XML attributes array / hash $d = new Database(); $d->setAppData($this); $d->loadFromXML($db); return $this->addDatabase($d); // calls self w/ different param type } }
/** * Builds the model classes from the database schema. * @return Database The built-out Database (with all tables, etc.) */ protected function buildModel() { $config = $this->getGeneratorConfig(); $con = $this->getConnection(); $database = new Database($this->getDatabaseName()); $database->setPlatform($config->getConfiguredPlatform($con)); // Some defaults ... $database->setDefaultIdMethod(IDMethod::NATIVE); $parser = $config->getConfiguredSchemaParser($con); $parser->parse($database); return $database; }
public function testCommaInEnumValueSet() { $column = new Column(); $table = new Table(); $database = new Database(); $platform = new DefaultPlatform(); $table->addColumn($column); $database->addTable($table); $database->setPlatform($platform); $column->loadFromXML(array('type' => PropelTypes::ENUM, 'valueSet' => 'Foo, Bar, "Foo, Bar"')); $valueSet = $column->getValueSet(); $this->assertCount(3, $valueSet); $this->assertEquals('Foo', $valueSet[0]); $this->assertEquals('Bar', $valueSet[1]); $this->assertEquals('Foo, Bar', $valueSet[2]); }
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"); }
/** * @see sfTask */ protected function execute($arguments = array(), $options = array()) { $databaseManager = new sfDatabaseManager($this->configuration); $connections = $this->getConnections($databaseManager); //$connection = $databaseManager->getDatabase($options['connection'] ? $options['connection'] : null)->getConnection(); $i = new afsDbInfo(); $this->logSection('propel', 'Reading databases structure...'); $ad = new AppData(); $totalNbTables = 0; foreach ($connections as $name => $params) { $pdo = $databaseManager->getDatabase($name)->getConnection(); $database = new Database($name); $platform = $this->getPlatform($databaseManager, $name); $database->setPlatform($platform); $database->setDefaultIdMethod(IDMethod::NATIVE); $parser = $this->getParser($databaseManager, $name, $pdo); //$parser->setMigrationTable($options['migration-table']); $parser->setPlatform($platform); $nbTables = $parser->parse($database); $ad->addDatabase($database); $totalNbTables += $nbTables; $this->logSection('propel', sprintf(' %d tables imported from database "%s"', $nbTables, $name), null, 'COMMENT'); } if ($totalNbTables) { $this->logSection('propel', sprintf('%d tables imported from databases.', $totalNbTables)); } else { $this->logSection('propel', 'Database is empty'); } $this->logSection('propel', 'Loading XML schema files...'); Phing::startup(); // required to locate behavior classes... $this->schemaToXML(self::DO_NOT_CHECK_SCHEMA, 'generated-'); $this->copyXmlSchemaFromPlugins('generated-'); $appData = $this->getModels($databaseManager, true); $this->logSection('propel', sprintf('%d tables defined in the schema files.', $appData->countTables())); $this->cleanup(true); $this->logSection('sql-diff', 'Comparing databases and schemas...'); $manager = new PropelMigrationManager(); $manager->setConnections($connections); foreach ($ad->getDatabases() as $database) { $name = $database->getName(); $filenameDiff = sfConfig::get('sf_data_dir') . "/sql/{$name}." . time() . ".diff.sql"; $this->logSection('sql-diff', sprintf(' Comparing database "%s"', $name), null, 'COMMENT'); if (!$appData->hasDatabase($name)) { // FIXME: tables present in database but not in XML continue; } $databaseDiff = PropelDatabaseComparator::computeDiff($database, $appData->getDatabase($name)); if (!$databaseDiff) { //no diff } $this->logSection('sql-diff', sprintf('Structure of database was modified in datasource "%s": %s', $name, $databaseDiff->getDescription())); $platform = $this->getPlatform($databaseManager, $name); //up sql $upDiff = $platform->getModifyDatabaseDDL($databaseDiff); //down sql $downDiff = $platform->getModifyDatabaseDDL($databaseDiff->getReverseDiff()); if ($databaseDiff) { $this->logSection('sql-diff', "Writing file {$filenameDiff}"); afStudioUtil::writeFile($filenameDiff, $upDiff); if ($options['insert'] === true || $options['insert'] === 'true') { $this->logSection('sql-diff', "Inserting sql diff"); $i->executeSql($upDiff, Propel::getConnection($name)); } if ($options['build'] === true || $options['build'] === 'true') { $this->logSection('sql-diff', 'Creating models from current schema'); $this->createTask('propel:build-model')->run(); $this->logSection('sql-diff', 'Creating forms from current schema'); $this->createTask('propel:build-forms')->run(); $this->logSection('sql-diff', 'Setting AppFlower project permissions'); $this->createTask('afs:fix-perms')->run(); $this->logSection('sql-diff', 'Creating AppFlower validator cache'); $this->createTask('appflower:validator-cache')->run(array('frontend', 'cache', 'yes')); $this->logSection('sql-diff', 'Clearing Symfony cache'); $this->createTask('cc')->run(); } } } }
/** * Builds the model classes from the database schema. * @return Database The built-out Database (with all tables, etc.) */ protected function buildModel() { $config = $this->getGeneratorConfig(); $con = $this->getConnection(); $database = new Database($this->getDatabaseName()); $database->setPlatform($config->getConfiguredPlatform($con)); // Some defaults ... $database->setDefaultIdMethod(IDMethod::NATIVE); $parser = $config->getConfiguredSchemaParser($con); $nbTables = $parser->parse($database, $this); $this->log("Successfully Reverse Engineered " . $nbTables . " tables"); return $database; }