/** * Returns the number of differences. * * Compares the columns of the fromTable and the toTable, * and modifies the inner tableDiff if necessary. * * @param boolean $caseInsensitive * @return integer */ public function compareColumns($caseInsensitive = false) { $fromTableColumns = $this->getFromTable()->getColumns(); $toTableColumns = $this->getToTable()->getColumns(); $columnDifferences = 0; // check for new columns in $toTable foreach ($toTableColumns as $column) { if (!$this->getFromTable()->hasColumn($column->getName(), $caseInsensitive)) { $this->tableDiff->addAddedColumn($column->getName(), $column); $columnDifferences++; } } // check for removed columns in $toTable foreach ($fromTableColumns as $column) { if (!$this->getToTable()->hasColumn($column->getName(), $caseInsensitive)) { $this->tableDiff->addRemovedColumn($column->getName(), $column); $columnDifferences++; } } // check for column differences foreach ($fromTableColumns as $fromColumn) { if ($this->getToTable()->hasColumn($fromColumn->getName(), $caseInsensitive)) { $toColumn = $this->getToTable()->getColumn($fromColumn->getName(), $caseInsensitive); $columnDiff = ColumnComparator::computeDiff($fromColumn, $toColumn, $caseInsensitive); if ($columnDiff) { $this->tableDiff->addModifiedColumn($fromColumn->getName(), $columnDiff); $columnDifferences++; } } } // check for column renamings foreach ($this->tableDiff->getAddedColumns() as $addedColumnName => $addedColumn) { foreach ($this->tableDiff->getRemovedColumns() as $removedColumnName => $removedColumn) { if (!ColumnComparator::computeDiff($addedColumn, $removedColumn, $caseInsensitive)) { // no difference except the name, that's probably a renaming $this->tableDiff->addRenamedColumn($removedColumn, $addedColumn); $this->tableDiff->removeAddedColumn($addedColumnName); $this->tableDiff->removeRemovedColumn($removedColumnName); $columnDifferences--; // skip to the next added column break; } } } return $columnDifferences; }
/** * {@inheritdoc} */ public function getModifyTableDDL(TableDiff $tableDiff) { $changedNotEditableThroughDirectDDL = $this->tableAlteringWorkaround && (false || $tableDiff->hasModifiedFks() || $tableDiff->hasModifiedIndices() || $tableDiff->hasModifiedColumns() || $tableDiff->hasRenamedColumns() || $tableDiff->hasRemovedFks() || $tableDiff->hasRemovedIndices() || $tableDiff->hasRemovedColumns() || $tableDiff->hasAddedIndices() || $tableDiff->hasAddedFks() || $tableDiff->hasAddedPkColumns()); if ($this->tableAlteringWorkaround && !$changedNotEditableThroughDirectDDL && $tableDiff->hasAddedColumns()) { $addedCols = $tableDiff->getAddedColumns(); foreach ($addedCols as $column) { $sqlChangeNotSupported = false || $column->isPrimaryKey() || $column->isUnique() || false !== array_search($column->getDefaultValue(), array('CURRENT_TIME', 'CURRENT_DATE', 'CURRENT_TIMESTAMP')) || substr(trim($column->getDefaultValue()), 0, 1) == '(' || $column->isNotNull() && $column->getDefaultValue() == 'NULL'; if ($sqlChangeNotSupported) { $changedNotEditableThroughDirectDDL = true; break; } } } if ($changedNotEditableThroughDirectDDL) { return $this->getMigrationTableDDL($tableDiff); } return parent::getModifyTableDDL($tableDiff); }
/** * Builds the DDL SQL to alter a table * based on a TableDiff instance * * @return string */ public function getModifyTableColumnsDDL(TableDiff $tableDiff) { $ret = ''; foreach ($tableDiff->getRemovedColumns() as $column) { $ret .= $this->getRemoveColumnDDL($column); } foreach ($tableDiff->getRenamedColumns() as $columnRenaming) { $ret .= $this->getRenameColumnDDL($columnRenaming[0], $columnRenaming[1]); } if ($modifiedColumns = $tableDiff->getModifiedColumns()) { $ret .= $this->getModifyColumnsDDL($modifiedColumns); } if ($addedColumns = $tableDiff->getAddedColumns()) { $ret .= $this->getAddColumnsDDL($addedColumns); } return $ret; }
public function getModifyTableDDL(TableDiff $tableDiff) { $alterTableStatements = ''; $toTable = $tableDiff->getToTable(); // drop indices, foreign keys foreach ($tableDiff->getRemovedFks() as $fk) { $alterTableStatements .= $this->getDropForeignKeyDDL($fk); } foreach ($tableDiff->getModifiedFks() as $fkModification) { list($fromFk) = $fkModification; $alterTableStatements .= $this->getDropForeignKeyDDL($fromFk); } foreach ($tableDiff->getRemovedIndices() as $index) { $alterTableStatements .= $this->getDropIndexDDL($index); } foreach ($tableDiff->getModifiedIndices() as $indexModification) { list($fromIndex) = $indexModification; $alterTableStatements .= $this->getDropIndexDDL($fromIndex); } // alter table structure if ($tableDiff->hasModifiedPk()) { $alterTableStatements .= $this->getDropPrimaryKeyDDL($tableDiff->getFromTable()); } foreach ($tableDiff->getRenamedColumns() as $columnRenaming) { $alterTableStatements .= $this->getRenameColumnDDL($columnRenaming[0], $columnRenaming[1]); } if ($modifiedColumns = $tableDiff->getModifiedColumns()) { $alterTableStatements .= $this->getModifyColumnsDDL($modifiedColumns); } if ($addedColumns = $tableDiff->getAddedColumns()) { $alterTableStatements .= $this->getAddColumnsDDL($addedColumns); } foreach ($tableDiff->getRemovedColumns() as $column) { $alterTableStatements .= $this->getRemoveColumnDDL($column); } // add new indices and foreign keys if ($tableDiff->hasModifiedPk()) { $alterTableStatements .= $this->getAddPrimaryKeyDDL($tableDiff->getToTable()); } // create indices, foreign keys foreach ($tableDiff->getModifiedIndices() as $indexModification) { list($oldIndex, $toIndex) = $indexModification; $alterTableStatements .= $this->getAddIndexDDL($toIndex); } foreach ($tableDiff->getAddedIndices() as $index) { $alterTableStatements .= $this->getAddIndexDDL($index); } foreach ($tableDiff->getModifiedFks() as $fkModification) { list(, $toFk) = $fkModification; $alterTableStatements .= $this->getAddForeignKeyDDL($toFk); } foreach ($tableDiff->getAddedFks() as $fk) { $alterTableStatements .= $this->getAddForeignKeyDDL($fk); } $ret = ''; if (trim($alterTableStatements)) { //merge all changes into one command. This prevents https://github.com/propelorm/Propel2/issues/1115 $changes = explode(';', $alterTableStatements); $changeFragments = []; foreach ($changes as $change) { if (trim($change)) { $changeFragments[] = preg_replace(sprintf('/ALTER TABLE %s /', $this->quoteIdentifier($toTable->getName())), "\n\n ", trim($change)); } } $ret .= sprintf("\nALTER TABLE %s%s;\n", $this->quoteIdentifier($toTable->getName()), implode(',', $changeFragments)); } return $ret; }