Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fix creating indexes for renamed columns and updating foreign keys fo…

…r renamed parent tables in SqlitePlatform
  • Loading branch information...
commit a42b8ed15ac617bfd8c1ec8549752878d0a75036 1 parent d679eb9
@hason hason authored
View
242 lib/Doctrine/DBAL/Platforms/SqlitePlatform.php
@@ -558,21 +558,8 @@ protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff)
}
$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;
- foreach ($indexes as $indexName => $index) {
+ foreach ($this->getIndexesInAlteredTable($diff) as $indexName => $index) {
if ($index->isPrimary()) {
continue;
}
@@ -684,21 +671,28 @@ public function getAlterTableSQL(TableDiff $diff)
$table = clone $fromTable;
- $columns = $table->getColumns();
-
+ $columns = array();
+ $oldColumnNames = array();
+ $newColumnNames = 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) {
if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) {
continue;
}
- unset($columns[$columnName]);
- }
-
- $fromColumns = array();
- $toColumns = array();
- foreach ($columns as $columnName => $column) {
- $fromColumns[$columnName] = $toColumns[$columnName] = $column->getQuotedName($this);
+ $columnName = strtolower($columnName);
+ if (isset($columns[$columnName])) {
+ unset($columns[$columnName]);
+ unset($oldColumnNames[$columnName]);
+ unset($newColumnNames[$columnName]);
+ }
}
foreach ($diff->renamedColumns as $oldColumnName => $column) {
@@ -706,9 +700,16 @@ public function getAlterTableSQL(TableDiff $diff)
continue;
}
- unset($columns[$oldColumnName]);
- $columns[$column->getName()] = $column;
- $toColumns[$oldColumnName] = $column->getQuotedName($this);
+ $oldColumnName = strtolower($oldColumnName);
+ if (isset($columns[$oldColumnName])) {
+ unset($columns[$oldColumnName]);
+ }
+
+ $columns[strtolower($column->getName())] = $column;
+
+ if (isset($newColumnNames[$oldColumnName])) {
+ $newColumnNames[$oldColumnName] = $column->getQuotedName($this);
+ }
}
foreach ($diff->changedColumns as $oldColumnName => $columnDiff) {
@@ -716,36 +717,23 @@ public function getAlterTableSQL(TableDiff $diff)
continue;
}
- unset($columns[$oldColumnName]);
- $columnName = $columnDiff->column->getName();
- $columns[$columnName] = $columnDiff->column;
- $toColumns[$oldColumnName] = $columnDiff->column->getQuotedName($this);
- }
-
- foreach ($diff->addedColumns as $columnName => $column) {
- if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) {
- continue;
+ if (isset($columns[$oldColumnName])) {
+ unset($columns[$oldColumnName]);
}
- $columns[$columnName] = $column;
- }
-
- $foreignKeys = $table->getForeignKeys();
+ $columns[strtolower($columnDiff->column->getName())] = $columnDiff->column;
- foreach ($diff->removedForeignKeys as $constraint) {
- $constraintName = strtolower($constraint->getName());
- if (isset($foreignKeys[$constraintName])) {
- unset($foreignKeys[$constraintName]);
+ if (isset($newColumnNames[$oldColumnName])) {
+ $newColumnNames[$oldColumnName] = $columnDiff->column->getQuotedName($this);
}
}
- foreach ($diff->changedForeignKeys as $constraint) {
- $constraintName = strtolower($constraint->getName());
- $foreignKeys[$constraintName] = $constraint;
- }
+ foreach ($diff->addedColumns as $columnName => $column) {
+ if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) {
+ continue;
+ }
- foreach ($diff->addedForeignKeys as $constraint) {
- $foreignKeys[] = $constraint;
+ $columns[strtolower($columnName)] = $column;
}
$sql = array();
@@ -753,14 +741,25 @@ public function getAlterTableSQL(TableDiff $diff)
if ( ! $this->onSchemaAlterTable($diff, $tableSql)) {
$newTableName = $diff->newName ?: $diff->name;
- $tempTable = new Table('__temp__'.$newTableName, $columns, $this->getPrimaryIndex($diff), $foreignKeys, 0, $table->getOptions());
- $tempTable->addOption('alter', true);
- $newTable = new Table($newTableName);
+ $dataTable = new Table('__temp__'.$table->getName());
+
+ $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[] = sprintf('INSERT INTO %s (%s) SELECT %s FROM %s', $tempTable->getQuotedName($this), implode(', ', $toColumns), implode(', ', $fromColumns), $table->getQuotedName($this));
+ $sql = $this->getPreAlterTableIndexForeignKeySQL($diff);
+ //$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[] = '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));
}
@@ -815,34 +814,137 @@ private function getSimpleAlterTableSQL(TableDiff $diff)
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) {
- if ($index->isPrimary()) {
- $primaryIndex = array($index->getName() => $index);
+ foreach ($diff->fromTable->getColumns() as $columnName => $column) {
+ $columns[strtolower($columnName)] = $column->getName();
+ }
+
+ 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) {
- if (isset($primaryIndex[$index->getName()])) {
- $primaryIndex = array();
- break;
+ $indexName = strtolower($index->getName());
+ if (strlen($indexName) && isset($indexes[$indexName])) {
+ unset($indexes[$indexName]);
}
}
- foreach ($diff->changedIndexes as $index) {
- if ($index->isPrimary()) {
- $primaryIndex = array($index);
- } elseif (isset($primaryIndex[$index->getName()])) {
- $primaryIndex = array();
+ foreach (array_merge($diff->changedIndexes, $diff->addedIndexes) as $index) {
+ $indexName = strtolower($index->getName());
+ if (strlen($indexName)) {
+ $indexes[$indexName] = $index;
+ } 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()) {
- $primaryIndex = array($index);
+ $primaryIndex = array($index->getName() => $index);
}
}
View
10 lib/Doctrine/DBAL/Schema/Index.php
@@ -205,6 +205,16 @@ public function overrules(Index $other)
}
/**
+ * 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.
*
* @example $index->addFlag('CLUSTERED')
View
56 tests/Doctrine/Tests/DBAL/Platforms/SqlitePlatformTest.php
@@ -145,10 +145,12 @@ public function testModifyLimitQueryWithEmptyOffset()
public function getGenerateAlterTableSql()
{
return array(
- "CREATE TABLE __temp__userlist (id INTEGER NOT NULL, baz VARCHAR(255) DEFAULT 'def' NOT NULL, bloo BOOLEAN DEFAULT '0' NOT NULL, quota INTEGER DEFAULT NULL, PRIMARY KEY(id))",
- "INSERT INTO __temp__userlist (id, baz, bloo) SELECT id, bar, bloo FROM mytable",
+ "CREATE TEMPORARY TABLE __temp__mytable AS SELECT id, bar, bloo FROM mytable",
"DROP TABLE mytable",
- "ALTER TABLE __temp__userlist RENAME TO userlist",
+ "CREATE TABLE mytable (id INTEGER NOT NULL, baz VARCHAR(255) DEFAULT 'def' NOT NULL, bloo BOOLEAN DEFAULT '0' NOT NULL, quota INTEGER DEFAULT NULL, PRIMARY KEY(id))",
+ "INSERT INTO mytable (id, baz, bloo) SELECT id, bar, bloo FROM __temp__mytable",
+ "DROP TABLE __temp__mytable",
+ "ALTER TABLE mytable RENAME TO userlist",
);
}
@@ -210,13 +212,15 @@ public function testCreateTableWithDeferredForeignKeys()
$table->addColumn('article', 'integer');
$table->addColumn('post', 'integer');
$table->addColumn('parent', 'integer');
+ $table->setPrimaryKey(array('id'));
$table->addForeignKeyConstraint('article', array('article'), array('id'), array('deferrable' => true));
$table->addForeignKeyConstraint('post', array('post'), array('id'), array('deferred' => true));
$table->addForeignKeyConstraint('user', array('parent'), array('id'), array('deferrable' => true, 'deferred' => true));
$sql = array(
'CREATE TABLE user ('
- . 'article INTEGER NOT NULL, post INTEGER NOT NULL, parent INTEGER NOT NULL, id INTEGER NOT NULL'
+ . 'id INTEGER NOT NULL, article INTEGER NOT NULL, post INTEGER NOT NULL, parent INTEGER NOT NULL'
+ . ', PRIMARY KEY(id)'
. ', CONSTRAINT FK_8D93D64923A0E66 FOREIGN KEY (article) REFERENCES article (id) DEFERRABLE INITIALLY IMMEDIATE'
. ', CONSTRAINT FK_8D93D6495A8A6C8D FOREIGN KEY (post) REFERENCES post (id) NOT DEFERRABLE INITIALLY DEFERRED'
. ', CONSTRAINT FK_8D93D6493D8E604F FOREIGN KEY (parent) REFERENCES user (id) DEFERRABLE INITIALLY DEFERRED'
@@ -229,6 +233,50 @@ public function testCreateTableWithDeferredForeignKeys()
$this->assertEquals($sql, $this->_platform->getCreateTableSQL($table));
}
+ public function testAlterTable()
+ {
+ $table = new Table('user');
+ $table->addColumn('id', 'integer');
+ $table->addColumn('article', 'integer');
+ $table->addColumn('post', 'integer');
+ $table->addColumn('parent', 'integer');
+ $table->setPrimaryKey(array('id'));
+ $table->addForeignKeyConstraint('article', array('article'), array('id'), array('deferrable' => true));
+ $table->addForeignKeyConstraint('post', array('post'), array('id'), array('deferred' => true));
+ $table->addForeignKeyConstraint('user', array('parent'), array('id'), array('deferrable' => true, 'deferred' => true));
+ $table->addIndex(array('article', 'post'), 'index1');
+
+ $diff = new TableDiff('user');
+ $diff->fromTable = $table;
+ $diff->newName = 'client';
+ $diff->renamedColumns['id'] = new \Doctrine\DBAL\Schema\Column('key', \Doctrine\DBAL\Types\Type::getType('integer'), array());
+ $diff->renamedColumns['post'] = new \Doctrine\DBAL\Schema\Column('comment', \Doctrine\DBAL\Types\Type::getType('integer'), array());
+ $diff->removedColumns['parent'] = new \Doctrine\DBAL\Schema\Column('comment', \Doctrine\DBAL\Types\Type::getType('integer'), array());
+ $diff->removedIndexes['index1'] = $table->getIndex('index1');
+
+ $sql = array(
+ 'DROP INDEX IDX_8D93D64923A0E66',
+ 'DROP INDEX IDX_8D93D6495A8A6C8D',
+ 'DROP INDEX IDX_8D93D6493D8E604F',
+ 'DROP INDEX index1',
+ 'CREATE TEMPORARY TABLE __temp__user AS SELECT id, article, post FROM user',
+ 'DROP TABLE user',
+ 'CREATE TABLE user ('
+ . '"key" INTEGER NOT NULL, article INTEGER NOT NULL, comment INTEGER NOT NULL'
+ . ', PRIMARY KEY("key")'
+ . ', CONSTRAINT FK_8D93D64923A0E66 FOREIGN KEY (article) REFERENCES article (id) DEFERRABLE INITIALLY IMMEDIATE'
+ . ', CONSTRAINT FK_8D93D6495A8A6C8D FOREIGN KEY (comment) REFERENCES post (id) NOT DEFERRABLE INITIALLY DEFERRED'
+ . ')',
+ 'INSERT INTO user ("key", article, comment) SELECT id, article, post FROM __temp__user',
+ 'DROP TABLE __temp__user',
+ 'ALTER TABLE user RENAME TO client',
+ 'CREATE INDEX IDX_8D93D64923A0E66 ON client (article)',
+ 'CREATE INDEX IDX_8D93D6495A8A6C8D ON client (comment)',
+ );
+
+ $this->assertEquals($sql, $this->_platform->getAlterTableSQL($diff));
+ }
+
protected function getQuotedColumnInPrimaryKeySQL()
{
return array(
Please sign in to comment.
Something went wrong with that request. Please try again.