Skip to content

Commit

Permalink
Fix creating indexes for renamed columns and updating foreign keys fo…
Browse files Browse the repository at this point in the history
…r renamed parent tables in SqlitePlatform
  • Loading branch information
hason committed Nov 22, 2012
1 parent d679eb9 commit a42b8ed
Show file tree
Hide file tree
Showing 3 changed files with 234 additions and 74 deletions.
242 changes: 172 additions & 70 deletions lib/Doctrine/DBAL/Platforms/SqlitePlatform.php
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -558,21 +558,8 @@ protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff)
} }


$sql = array(); $sql = array();
$indexes = $diff->fromTable->getIndexes();

foreach ($diff->removedIndexes as $index) {
if (isset($indexes[$index->getName()])) {
unset($indexes[$index->getName()]);
}
}

foreach (array_merge($diff->changedIndexes, $diff->addedIndexes) as $index) {
$name = $index->getName();
$indexes[$name] = $index;
}

$tableName = $diff->newName ?: $diff->name; $tableName = $diff->newName ?: $diff->name;
foreach ($indexes as $indexName => $index) { foreach ($this->getIndexesInAlteredTable($diff) as $indexName => $index) {
if ($index->isPrimary()) { if ($index->isPrimary()) {
continue; continue;
} }
Expand Down Expand Up @@ -684,83 +671,95 @@ public function getAlterTableSQL(TableDiff $diff)


$table = clone $fromTable; $table = clone $fromTable;


$columns = $table->getColumns(); $columns = array();

$oldColumnNames = array();
$newColumnNames = array();
$columnSql = array(); $columnSql = array();

foreach ($table->getColumns() as $columnName => $column) {
$columnName = strtolower($columnName);
$columns[$columnName] = $column;
$oldColumnNames[$columnName] = $newColumnNames[$columnName] = $column->getQuotedName($this);
}

foreach ($diff->removedColumns as $columnName => $column) { foreach ($diff->removedColumns as $columnName => $column) {
if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) {
continue; continue;
} }


unset($columns[$columnName]); $columnName = strtolower($columnName);
} if (isset($columns[$columnName])) {

unset($columns[$columnName]);
$fromColumns = array(); unset($oldColumnNames[$columnName]);
$toColumns = array(); unset($newColumnNames[$columnName]);
foreach ($columns as $columnName => $column) { }
$fromColumns[$columnName] = $toColumns[$columnName] = $column->getQuotedName($this);
} }


foreach ($diff->renamedColumns as $oldColumnName => $column) { foreach ($diff->renamedColumns as $oldColumnName => $column) {
if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) {
continue; continue;
} }


unset($columns[$oldColumnName]); $oldColumnName = strtolower($oldColumnName);
$columns[$column->getName()] = $column; if (isset($columns[$oldColumnName])) {
$toColumns[$oldColumnName] = $column->getQuotedName($this); unset($columns[$oldColumnName]);
}

$columns[strtolower($column->getName())] = $column;

if (isset($newColumnNames[$oldColumnName])) {
$newColumnNames[$oldColumnName] = $column->getQuotedName($this);
}
} }


foreach ($diff->changedColumns as $oldColumnName => $columnDiff) { foreach ($diff->changedColumns as $oldColumnName => $columnDiff) {
if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) {
continue; continue;
} }


unset($columns[$oldColumnName]); if (isset($columns[$oldColumnName])) {
$columnName = $columnDiff->column->getName(); unset($columns[$oldColumnName]);
$columns[$columnName] = $columnDiff->column;
$toColumns[$oldColumnName] = $columnDiff->column->getQuotedName($this);
}

foreach ($diff->addedColumns as $columnName => $column) {
if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) {
continue;
} }


$columns[$columnName] = $column; $columns[strtolower($columnDiff->column->getName())] = $columnDiff->column;
}

$foreignKeys = $table->getForeignKeys();


foreach ($diff->removedForeignKeys as $constraint) { if (isset($newColumnNames[$oldColumnName])) {
$constraintName = strtolower($constraint->getName()); $newColumnNames[$oldColumnName] = $columnDiff->column->getQuotedName($this);
if (isset($foreignKeys[$constraintName])) {
unset($foreignKeys[$constraintName]);
} }
} }


foreach ($diff->changedForeignKeys as $constraint) { foreach ($diff->addedColumns as $columnName => $column) {
$constraintName = strtolower($constraint->getName()); if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) {
$foreignKeys[$constraintName] = $constraint; continue;
} }


foreach ($diff->addedForeignKeys as $constraint) { $columns[strtolower($columnName)] = $column;
$foreignKeys[] = $constraint;
} }


$sql = array(); $sql = array();
$tableSql = array(); $tableSql = array();
if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { if ( ! $this->onSchemaAlterTable($diff, $tableSql)) {
$newTableName = $diff->newName ?: $diff->name; $newTableName = $diff->newName ?: $diff->name;


$tempTable = new Table('__temp__'.$newTableName, $columns, $this->getPrimaryIndex($diff), $foreignKeys, 0, $table->getOptions()); $dataTable = new Table('__temp__'.$table->getName());
$tempTable->addOption('alter', true);
$newTable = new Table($newTableName); $newTable = new Table($table->getName(), $columns, $this->getPrimaryIndexInAlteredTable($diff), $this->getForeignKeysInAlteredTable($diff), 0, $table->getOptions());
$newTable->addOption('alter', true);


$sql = array_merge($this->getPreAlterTableIndexForeignKeySQL($diff), $this->getCreateTableSQL($tempTable, self::CREATE_INDEXES | self::CREATE_FOREIGNKEYS)); $sql = $this->getPreAlterTableIndexForeignKeySQL($diff);
$sql[] = sprintf('INSERT INTO %s (%s) SELECT %s FROM %s', $tempTable->getQuotedName($this), implode(', ', $toColumns), implode(', ', $fromColumns), $table->getQuotedName($this)); //$sql = array_merge($sql, $this->getCreateTableSQL($dataTable, 0));
$sql[] = sprintf('CREATE TEMPORARY TABLE %s AS SELECT %s FROM %s', $dataTable->getQuotedName($this), implode(', ', $oldColumnNames), $table->getQuotedName($this));
$sql[] = $this->getDropTableSQL($fromTable); $sql[] = $this->getDropTableSQL($fromTable);
$sql[] = 'ALTER TABLE '.$tempTable->getQuotedName($this).' RENAME TO '.$newTable->getQuotedName($this);
$sql = array_merge($sql, $this->getCreateTableSQL($newTable));
$sql[] = sprintf('INSERT INTO %s (%s) SELECT %s FROM %s', $newTable->getQuotedName($this), implode(', ', $newColumnNames), implode(', ', $oldColumnNames), $dataTable->getQuotedName($this));
$sql[] = $this->getDropTableSQL($dataTable);

if ($diff->newName && $diff->newName != $diff->name) {
$renamedTable = new Table($diff->newName);
$sql[] = 'ALTER TABLE '.$newTable->getQuotedName($this).' RENAME TO '.$renamedTable->getQuotedName($this);
}

$sql = array_merge($sql, $this->getPostAlterTableIndexForeignKeySQL($diff)); $sql = array_merge($sql, $this->getPostAlterTableIndexForeignKeySQL($diff));
} }


Expand Down Expand Up @@ -815,34 +814,137 @@ private function getSimpleAlterTableSQL(TableDiff $diff)
return array_merge($sql, $tableSql, $columnSql); return array_merge($sql, $tableSql, $columnSql);
} }


private function getPrimaryIndex(TableDiff $diff) private function getColumnNamesInAlteredTable(TableDiff $diff)
{ {
$primaryIndex = array(); $columns = array();


foreach ($diff->fromTable->getIndexes() as $index) { foreach ($diff->fromTable->getColumns() as $columnName => $column) {
if ($index->isPrimary()) { $columns[strtolower($columnName)] = $column->getName();
$primaryIndex = array($index->getName() => $index); }

foreach ($diff->removedColumns as $columnName => $column) {
$columnName = strtolower($columnName);
if (isset($columns[$columnName])) {
unset($columns[$columnName]);
}
}

foreach ($diff->renamedColumns as $oldColumnName => $column) {
$columnName = $column->getName();
$columns[strtolower($oldColumnName)] = $columnName;
$columns[strtolower($columnName)] = $columnName;
}

foreach ($diff->changedColumns as $oldColumnName => $columnDiff) {
$columnName = $columnDiff->column->getName();
$columns[strtolower($oldColumnName)] = $columnName;
$columns[strtolower($columnName)] = $columnName;
}

foreach ($diff->addedColumns as $columnName => $column) {
$columns[strtolower($columnName)] = $columnName;
}

return $columns;
}

private function getIndexesInAlteredTable(TableDiff $diff)
{
$indexes = $diff->fromTable->getIndexes();
$columnNames = $this->getColumnNamesInAlteredTable($diff);

foreach ($indexes as $key => $index) {
$changed = false;
$indexColumns = array();
foreach ($index->getColumns() as $columnName) {
$normalizedColumnName = strtolower($columnName);
if ( ! isset($columnNames[$normalizedColumnName])) {
unset($indexes[$key]);
continue 2;
} else {
$indexColumns[] = $columnNames[$normalizedColumnName];
if ($columnName !== $columnNames[$normalizedColumnName]) {
$changed = true;
}
}
}

if ($changed) {
$indexes[$key] = new Index($index->getName(), $indexColumns, $index->isUnique(), $index->isPrimary(), $index->getFlags());
} }
} }


foreach ($diff->removedIndexes as $index) { foreach ($diff->removedIndexes as $index) {
if (isset($primaryIndex[$index->getName()])) { $indexName = strtolower($index->getName());
$primaryIndex = array(); if (strlen($indexName) && isset($indexes[$indexName])) {
break; unset($indexes[$indexName]);
} }
} }


foreach ($diff->changedIndexes as $index) { foreach (array_merge($diff->changedIndexes, $diff->addedIndexes) as $index) {
if ($index->isPrimary()) { $indexName = strtolower($index->getName());
$primaryIndex = array($index); if (strlen($indexName)) {
} elseif (isset($primaryIndex[$index->getName()])) { $indexes[$indexName] = $index;
$primaryIndex = array(); } else {
$indexes[] = $index;
} }
} }


foreach ($diff->addedIndexes as $index) { return $indexes;
}

private function getForeignKeysInAlteredTable(TableDiff $diff)
{
$foreignKeys = $diff->fromTable->getForeignKeys();
$columnNames = $this->getColumnNamesInAlteredTable($diff);

foreach ($foreignKeys as $key => $constraint) {
$changed = false;
$localColumns = array();
foreach ($constraint->getLocalColumns() as $columnName) {
$normalizedColumnName = strtolower($columnName);
if ( ! isset($columnNames[$normalizedColumnName])) {
unset($foreignKeys[$key]);
continue 2;
} else {
$localColumns[] = $columnNames[$normalizedColumnName];
if ($columnName !== $columnNames[$normalizedColumnName]) {
$changed = true;
}
}
}

if ($changed) {
$foreignKeys[$key] = new ForeignKeyConstraint($localColumns, $constraint->getForeignTableName(), $constraint->getForeignColumns(), $constraint->getName(), $constraint->getOptions());
}
}

foreach ($diff->removedForeignKeys as $constraint) {
$constraintName = strtolower($constraint->getName());
if (strlen($constraintName) && isset($foreignKeys[$constraintName])) {
unset($foreignKeys[$constraintName]);
}
}

foreach (array_merge($diff->changedForeignKeys, $diff->addedForeignKeys) as $constraint) {
$constraintName = strtolower($constraint->getName());
if (strlen($constraintName)) {
$foreignKeys[$constraintName] = $constraint;
} else {
$foreignKeys[] = $constraint;
}
}

return $foreignKeys;
}

private function getPrimaryIndexInAlteredTable(TableDiff $diff)
{
$primaryIndex = array();

foreach ($this->getIndexesInAlteredTable($diff) as $index) {
if ($index->isPrimary()) { if ($index->isPrimary()) {
$primaryIndex = array($index); $primaryIndex = array($index->getName() => $index);
} }
} }


Expand Down
10 changes: 10 additions & 0 deletions lib/Doctrine/DBAL/Schema/Index.php
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -204,6 +204,16 @@ public function overrules(Index $other)
return false; return false;
} }


/**
* Returns platform specific flags for indexes.
*
* @return array
*/
public function getFlags()
{
return array_keys($this->_flags);
}

/** /**
* Add Flag for an index that translates to platform specific handling. * Add Flag for an index that translates to platform specific handling.
* *
Expand Down
Loading

0 comments on commit a42b8ed

Please sign in to comment.