From e86cbd65fa683fedeea4d5199bd3871514e4d94c Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Sat, 30 Apr 2011 16:20:14 +0200 Subject: [PATCH 1/2] [DBAL-115] Bugfix in SchemaTool not quoting table names when dropping schema. --- lib/Doctrine/ORM/Tools/SchemaTool.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/SchemaTool.php b/lib/Doctrine/ORM/Tools/SchemaTool.php index f325ca55085..19323f981bb 100644 --- a/lib/Doctrine/ORM/Tools/SchemaTool.php +++ b/lib/Doctrine/ORM/Tools/SchemaTool.php @@ -563,9 +563,10 @@ public function getDropSchemaSQL(array $classes) $associationTables = $this->_getAssociationTables($commitOrder); // Drop association tables first - foreach ($associationTables as $associationTable) { - if (!in_array($associationTable, $orderedTables)) { - $orderedTables[] = $associationTable; + foreach ($associationTables as $quotedAssociationTableName) { + // avoid adding duplicates + if (!in_array($quotedAssociationTableName, $orderedTables)) { + $orderedTables[] = $quotedAssociationTableName; } } @@ -579,7 +580,7 @@ public function getDropSchemaSQL(array $classes) } if (!in_array($class->getTableName(), $orderedTables)) { - $orderedTables[] = $class->getTableName(); + $orderedTables[] = $class->getQuotedTableName($this->_platform); } } @@ -667,9 +668,10 @@ private function _getAssociationTables(array $classes) $associationTables = array(); foreach ($classes as $class) { + /* @var $class \Doctrine\ORM\Mapping\ClassMetadata */ foreach ($class->associationMappings as $assoc) { if ($assoc['isOwningSide'] && $assoc['type'] == ClassMetadata::MANY_TO_MANY) { - $associationTables[] = $assoc['joinTable']['name']; + $associationTables[] = $class->getQuotedJoinTableName($assoc, $this->_platform); } } } From 8d39f2a36dd04d8f186b377f7c6b3e0f9c102292 Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Sat, 30 Apr 2011 17:16:34 +0200 Subject: [PATCH 2/2] [DBAL-115] REALLY fix issues with SchemaTool::getDropSchemaSQL(). --- lib/Doctrine/ORM/Tools/SchemaTool.php | 105 ++++-------------- .../SchemaTool/CompanySchemaTest.php | 15 +++ 2 files changed, 35 insertions(+), 85 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/SchemaTool.php b/lib/Doctrine/ORM/Tools/SchemaTool.php index 19323f981bb..07aa119f32b 100644 --- a/lib/Doctrine/ORM/Tools/SchemaTool.php +++ b/lib/Doctrine/ORM/Tools/SchemaTool.php @@ -542,59 +542,35 @@ public function getDropDatabaseSQL() } /** - * + * Get SQL to drop the tables defined by the passed classes. + * * @param array $classes * @return array */ public function getDropSchemaSQL(array $classes) { - $sm = $this->_em->getConnection()->getSchemaManager(); - - $sql = array(); - $orderedTables = array(); - - foreach ($classes AS $class) { - if ($class->isIdGeneratorSequence() && !$class->isMappedSuperclass && $class->name == $class->rootEntityName && $this->_platform->supportsSequences()) { - $sql[] = $this->_platform->getDropSequenceSQL($class->sequenceGeneratorDefinition['sequenceName']); - } - } - - $commitOrder = $this->_getCommitOrder($classes); - $associationTables = $this->_getAssociationTables($commitOrder); - - // Drop association tables first - foreach ($associationTables as $quotedAssociationTableName) { - // avoid adding duplicates - if (!in_array($quotedAssociationTableName, $orderedTables)) { - $orderedTables[] = $quotedAssociationTableName; - } - } - - // Drop tables in reverse commit order - for ($i = count($commitOrder) - 1; $i >= 0; --$i) { - $class = $commitOrder[$i]; - - if (($class->isInheritanceTypeSingleTable() && $class->name != $class->rootEntityName) - || $class->isMappedSuperclass) { - continue; - } - - if (!in_array($class->getTableName(), $orderedTables)) { - $orderedTables[] = $class->getQuotedTableName($this->_platform); - } - } + $visitor = new \Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector($this->_platform); + $schema = $this->getSchemaFromMetadata($classes); - $dropTablesSql = array(); - foreach ($orderedTables AS $tableName) { - /* @var $sm \Doctrine\DBAL\Schema\AbstractSchemaManager */ - $foreignKeys = $sm->listTableForeignKeys($tableName); - foreach ($foreignKeys AS $foreignKey) { - $sql[] = $this->_platform->getDropForeignKeySQL($foreignKey, $tableName); + $sm = $this->_em->getConnection()->getSchemaManager(); + $fullSchema = $sm->createSchema(); + foreach ($fullSchema->getTables() AS $table) { + if (!$schema->hasTable($table->getName())) { + foreach ($table->getForeignKeys() AS $foreignKey) { + /* @var $foreignKey \Doctrine\DBAL\Schema\ForeignKeyConstraint */ + if ($schema->hasTable($foreignKey->getForeignTableName())) { + $visitor->acceptForeignKey($table, $foreignKey); + } + } + } else { + $visitor->acceptTable($table); + foreach ($table->getForeignKeys() AS $foreignKey) { + $visitor->acceptForeignKey($table, $foreignKey); + } } - $dropTablesSql[] = $this->_platform->getDropTableSQL($tableName); } - return array_merge($sql, $dropTablesSql); + return $visitor->getQueries(); } /** @@ -637,45 +613,4 @@ public function getUpdateSchemaSql(array $classes, $saveMode=false) return $schemaDiff->toSql($this->_platform); } } - - private function _getCommitOrder(array $classes) - { - $calc = new CommitOrderCalculator; - - // Calculate dependencies - foreach ($classes as $class) { - $calc->addClass($class); - - foreach ($class->associationMappings as $assoc) { - if ($assoc['isOwningSide']) { - $targetClass = $this->_em->getClassMetadata($assoc['targetEntity']); - - if ( ! $calc->hasClass($targetClass->name)) { - $calc->addClass($targetClass); - } - - // add dependency ($targetClass before $class) - $calc->addDependency($targetClass, $class); - } - } - } - - return $calc->getCommitOrder(); - } - - private function _getAssociationTables(array $classes) - { - $associationTables = array(); - - foreach ($classes as $class) { - /* @var $class \Doctrine\ORM\Mapping\ClassMetadata */ - foreach ($class->associationMappings as $assoc) { - if ($assoc['isOwningSide'] && $assoc['type'] == ClassMetadata::MANY_TO_MANY) { - $associationTables[] = $class->getQuotedJoinTableName($assoc, $this->_platform); - } - } - } - - return $associationTables; - } } diff --git a/tests/Doctrine/Tests/ORM/Functional/SchemaTool/CompanySchemaTest.php b/tests/Doctrine/Tests/ORM/Functional/SchemaTool/CompanySchemaTest.php index 3a14056eb36..797c202f6dd 100644 --- a/tests/Doctrine/Tests/ORM/Functional/SchemaTool/CompanySchemaTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/SchemaTool/CompanySchemaTest.php @@ -50,4 +50,19 @@ public function testSingleTableInheritance(Schema $schema) $this->assertFalse($table->getColumn('pricePerHour')->getNotnull()); $this->assertFalse($table->getColumn('maxPrice')->getNotnull()); } + + /** + * @group DBAL-115 + */ + public function testDropPartSchemaWithForeignKeys() + { + if (!$this->_em->getConnection()->getDatabasePlatform()->supportsForeignKeyConstraints()) { + $this->markTestSkipped("Foreign Key test"); + } + + $sql = $this->_schemaTool->getDropSchemaSQL(array( + $this->_em->getClassMetadata('Doctrine\Tests\Models\Company\CompanyManager'), + )); + $this->assertEquals(3, count($sql)); + } } \ No newline at end of file