/** * Browses the foreign keys and creates referrers for the foreign table. * This method can be called several times on the same table. It only * adds the missing referrers and is non-destructive. * Warning: only use when all the tables were created. * * @param boolean $throwErrors * @throws BuildException */ public function setupReferrers($throwErrors = false) { foreach ($this->foreignKeys as $foreignKey) { // table referrers $foreignTable = $this->database->getTable($foreignKey->getForeignTableName()); if (null !== $foreignTable) { $referrers = $foreignTable->getReferrers(); if (null === $referrers || !in_array($foreignKey, $referrers, true)) { $foreignTable->addReferrer($foreignKey); } } elseif ($throwErrors) { throw new BuildException(sprintf('Table "%s" contains a foreign key to nonexistent table "%s"', $this->getName(), $foreignKey->getForeignTableName())); } // foreign pk's $localColumnNames = $foreignKey->getLocalColumns(); foreach ($localColumnNames as $localColumnName) { $localColumn = $this->getColumn($localColumnName); if (null !== $localColumn) { if ($localColumn->isPrimaryKey() && !$this->getContainsForeignPK()) { $this->setContainsForeignPK(true); } } elseif ($throwErrors) { // give notice of a schema inconsistency. // note we do not prevent the npe as there is nothing // that we can do, if it is to occur. throw new BuildException(sprintf('Table "%s" contains a foreign key with nonexistent local column "%s"', $this->getName(), $localColumnName)); } } // foreign column references $foreignColumnNames = $foreignKey->getForeignColumns(); foreach ($foreignColumnNames as $foreignColumnName) { if (null === $foreignTable) { continue; } $foreignColumn = $foreignTable->getColumn($foreignColumnName); if (null !== $foreignColumn) { if (!$foreignColumn->hasReferrer($foreignKey)) { $foreignColumn->addReferrer($foreignKey); } } elseif ($throwErrors && !$foreignKey->isPolymorphic()) { // if the foreign column does not exist, we may have an // external reference or a misspelling throw new BuildException(sprintf('Table "%s" contains a foreign key to table "%s" with nonexistent column "%s"', $this->getName(), $foreignTable->getName(), $foreignColumnName)); } } if ($this->getPlatform() instanceof MysqlPlatform) { $this->addExtraIndices(); } } }
/** * Returns the number of differences. * * Compares the tables of the fromDatabase and the toDatabase, and modifies * the inner databaseDiff if necessary. * * @param boolean $caseInsensitive * @return integer */ public function compareTables($caseInsensitive = false) { $fromDatabaseTables = $this->fromDatabase->getTables(); $toDatabaseTables = $this->toDatabase->getTables(); $databaseDifferences = 0; $platform = $this->toDatabase->getPlatform() ?: $this->fromDatabase->getPlatform(); // check for new tables in $toDatabase foreach ($toDatabaseTables as $table) { if ($platform) { $platform->normalizeTable($table); } if (!$this->fromDatabase->hasTable($table->getName(), $caseInsensitive) && !$table->isSkipSql()) { $this->databaseDiff->addAddedTable($table->getName(), $table); $databaseDifferences++; } } // check for removed tables in $toDatabase foreach ($fromDatabaseTables as $table) { if (!$this->toDatabase->hasTable($table->getName(), $caseInsensitive) && !$table->isSkipSql()) { $this->databaseDiff->addRemovedTable($table->getName(), $table); $databaseDifferences++; } } // check for table differences foreach ($fromDatabaseTables as $fromTable) { if ($this->toDatabase->hasTable($fromTable->getName(), $caseInsensitive)) { $toTable = $this->toDatabase->getTable($fromTable->getName(), $caseInsensitive); $databaseDiff = TableComparator::computeDiff($fromTable, $toTable, $caseInsensitive); if ($databaseDiff) { $this->databaseDiff->addModifiedTable($fromTable->getName(), $databaseDiff); $databaseDifferences++; } } } $renamed = []; // check for table renamings foreach ($this->databaseDiff->getAddedTables() as $addedTableName => $addedTable) { foreach ($this->databaseDiff->getRemovedTables() as $removedTableName => $removedTable) { if (!in_array($addedTableName, $renamed) && !TableComparator::computeDiff($addedTable, $removedTable, $caseInsensitive)) { // no difference except the name, that's probably a renaming $renamed[] = $addedTableName; $this->databaseDiff->addRenamedTable($removedTableName, $addedTableName); $this->databaseDiff->removeAddedTable($addedTableName); $this->databaseDiff->removeRemovedTable($removedTableName); $databaseDifferences--; } } } return $databaseDifferences; }
/** * Returns the number of differences. * * Compares the tables of the fromDatabase and the toDatabase, and modifies * the inner databaseDiff if necessary. * * @param boolean $caseInsensitive * @return integer */ public function compareTables($caseInsensitive = false) { $fromDatabaseTables = $this->fromDatabase->getTables(); $toDatabaseTables = $this->toDatabase->getTables(); $databaseDifferences = 0; // check for new tables in $toDatabase foreach ($toDatabaseTables as $table) { if ($this->isTableExcluded($table)) { continue; } if (!$this->fromDatabase->hasTable($table->getName(), $caseInsensitive) && !$table->isSkipSql()) { $this->databaseDiff->addAddedTable($table->getName(), $table); $databaseDifferences++; } } // check for removed tables in $toDatabase if ($this->getRemoveTable()) { foreach ($fromDatabaseTables as $table) { if ($this->isTableExcluded($table)) { continue; } if (!$this->toDatabase->hasTable($table->getName(), $caseInsensitive) && !$table->isSkipSql()) { $this->databaseDiff->addRemovedTable($table->getName(), $table); $databaseDifferences++; } } } // check for table differences foreach ($fromDatabaseTables as $fromTable) { if ($this->isTableExcluded($fromTable)) { continue; } if ($this->toDatabase->hasTable($fromTable->getName(), $caseInsensitive)) { $toTable = $this->toDatabase->getTable($fromTable->getName(), $caseInsensitive); $databaseDiff = TableComparator::computeDiff($fromTable, $toTable, $caseInsensitive); if ($databaseDiff) { $this->databaseDiff->addModifiedTable($fromTable->getName(), $databaseDiff); $databaseDifferences++; } } } // check for table renamings foreach ($this->databaseDiff->getAddedTables() as $addedTableName => $addedTable) { foreach ($this->databaseDiff->getRemovedTables() as $removedTableName => $removedTable) { if (!TableComparator::computeDiff($addedTable, $removedTable, $caseInsensitive)) { // no difference except the name, that's probably a renaming if ($this->getWithRenaming()) { $this->databaseDiff->addRenamedTable($removedTableName, $addedTableName); $this->databaseDiff->removeAddedTable($addedTableName); $this->databaseDiff->removeRemovedTable($removedTableName); $databaseDifferences--; } else { $this->databaseDiff->addPossibleRenamedTable($removedTableName, $addedTableName); } // skip to the next added table break; } } } return $databaseDifferences; }
public function testAddArrayTable() { $database = new Database(); $database->addTable(['name' => 'books']); $database->addTable(['name' => 'authors']); $database->addTable(['name' => 'categories', 'skipSql' => 'true']); $database->addTable(['name' => 'publishers', 'readOnly' => 'true']); $this->assertTrue($database->hasTable('books')); $this->assertTrue($database->hasTable('books', true)); $this->assertFalse($database->hasTable('BOOKS')); $this->assertTrue($database->hasTableByPhpName('Books')); $this->assertInstanceOf('Propel\\Generator\\Model\\Table', $database->getTable('books')); $this->assertInstanceOf('Propel\\Generator\\Model\\Table', $database->getTableByPhpName('Books')); // 3 tables because read only table is excluded from the count $this->assertSame(3, $database->countTables()); // 3 tables because skipped sql table is excluded from the count $this->assertCount(3, $database->getTablesForSql()); }