[2.0] Added support to drop many-to-many association tables in SchemaTool
This commit is contained in:
parent
f0da001770
commit
6368eb6a4a
@ -62,6 +62,7 @@ class SchemaTool
|
|||||||
{
|
{
|
||||||
$createSchemaSql = $this->getCreateSchemaSql($classes);
|
$createSchemaSql = $this->getCreateSchemaSql($classes);
|
||||||
$conn = $this->_em->getConnection();
|
$conn = $this->_em->getConnection();
|
||||||
|
|
||||||
foreach ($createSchemaSql as $sql) {
|
foreach ($createSchemaSql as $sql) {
|
||||||
$conn->execute($sql);
|
$conn->execute($sql);
|
||||||
}
|
}
|
||||||
@ -102,6 +103,7 @@ class SchemaTool
|
|||||||
// Parent class information is already contained in this class
|
// Parent class information is already contained in this class
|
||||||
$processedClasses[$parentClassName] = true;
|
$processedClasses[$parentClassName] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($class->subClasses as $subClassName) {
|
foreach ($class->subClasses as $subClassName) {
|
||||||
$subClass = $this->_em->getClassMetadata($subClassName);
|
$subClass = $this->_em->getClassMetadata($subClassName);
|
||||||
$columns = array_merge($columns, $this->_gatherColumns($subClass, $options));
|
$columns = array_merge($columns, $this->_gatherColumns($subClass, $options));
|
||||||
@ -127,8 +129,11 @@ class SchemaTool
|
|||||||
// Add an ID FK column to child tables
|
// Add an ID FK column to child tables
|
||||||
$idMapping = $class->fieldMappings[$class->identifier[0]];
|
$idMapping = $class->fieldMappings[$class->identifier[0]];
|
||||||
$idColumn = $this->_gatherColumn($class, $idMapping, $options);
|
$idColumn = $this->_gatherColumn($class, $idMapping, $options);
|
||||||
|
|
||||||
unset($idColumn['autoincrement']);
|
unset($idColumn['autoincrement']);
|
||||||
|
|
||||||
$columns[$idColumn['name']] = $idColumn;
|
$columns[$idColumn['name']] = $idColumn;
|
||||||
|
|
||||||
// Add a FK constraint on the ID column
|
// Add a FK constraint on the ID column
|
||||||
$constraint = array();
|
$constraint = array();
|
||||||
$constraint['tableName'] = $class->getQuotedTableName($this->_platform);
|
$constraint['tableName'] = $class->getQuotedTableName($this->_platform);
|
||||||
@ -148,12 +153,14 @@ class SchemaTool
|
|||||||
if (isset($class->primaryTable['indexes'])) {
|
if (isset($class->primaryTable['indexes'])) {
|
||||||
$options['indexes'] = $class->primaryTable['indexes'];
|
$options['indexes'] = $class->primaryTable['indexes'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($class->primaryTable['uniqueConstraints'])) {
|
if (isset($class->primaryTable['uniqueConstraints'])) {
|
||||||
$options['uniqueConstraints'] = $class->primaryTable['uniqueConstraints'];
|
$options['uniqueConstraints'] = $class->primaryTable['uniqueConstraints'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql = array_merge($sql, $this->_platform->getCreateTableSql(
|
$sql = array_merge($sql, $this->_platform->getCreateTableSql(
|
||||||
$class->getQuotedTableName($this->_platform), $columns, $options));
|
$class->getQuotedTableName($this->_platform), $columns, $options)
|
||||||
|
);
|
||||||
$processedClasses[$class->name] = true;
|
$processedClasses[$class->name] = true;
|
||||||
|
|
||||||
// TODO if we're reusing the sequence previously defined (in another model),
|
// TODO if we're reusing the sequence previously defined (in another model),
|
||||||
@ -192,6 +199,7 @@ class SchemaTool
|
|||||||
private function _getDiscriminatorColumnDefinition($class)
|
private function _getDiscriminatorColumnDefinition($class)
|
||||||
{
|
{
|
||||||
$discrColumn = $class->discriminatorColumn;
|
$discrColumn = $class->discriminatorColumn;
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'name' => $class->getQuotedDiscriminatorColumnName($this->_platform),
|
'name' => $class->getQuotedDiscriminatorColumnName($this->_platform),
|
||||||
'type' => Type::getType($discrColumn['type']),
|
'type' => Type::getType($discrColumn['type']),
|
||||||
@ -212,6 +220,7 @@ class SchemaTool
|
|||||||
private function _gatherColumns($class, array &$options)
|
private function _gatherColumns($class, array &$options)
|
||||||
{
|
{
|
||||||
$columns = array();
|
$columns = array();
|
||||||
|
|
||||||
foreach ($class->fieldMappings as $fieldName => $mapping) {
|
foreach ($class->fieldMappings as $fieldName => $mapping) {
|
||||||
$column = $this->_gatherColumn($class, $mapping, $options);
|
$column = $this->_gatherColumn($class, $mapping, $options);
|
||||||
$columns[$column['name']] = $column;
|
$columns[$column['name']] = $column;
|
||||||
@ -236,18 +245,23 @@ class SchemaTool
|
|||||||
$column['type'] = Type::getType($mapping['type']);
|
$column['type'] = Type::getType($mapping['type']);
|
||||||
$column['length'] = isset($mapping['length']) ? $mapping['length'] : null;
|
$column['length'] = isset($mapping['length']) ? $mapping['length'] : null;
|
||||||
$column['notnull'] = isset($mapping['nullable']) ? ! $mapping['nullable'] : false;
|
$column['notnull'] = isset($mapping['nullable']) ? ! $mapping['nullable'] : false;
|
||||||
|
|
||||||
if (isset($mapping['precision'])) {
|
if (isset($mapping['precision'])) {
|
||||||
$column['precision'] = $mapping['precision'];
|
$column['precision'] = $mapping['precision'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($mapping['scale'])) {
|
if (isset($mapping['scale'])) {
|
||||||
$column['scale'] = $mapping['scale'];
|
$column['scale'] = $mapping['scale'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($mapping['default'])) {
|
if (isset($mapping['default'])) {
|
||||||
$column['default'] = $mapping['default'];
|
$column['default'] = $mapping['default'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($class->isIdentifier($mapping['fieldName'])) {
|
if ($class->isIdentifier($mapping['fieldName'])) {
|
||||||
$column['primary'] = true;
|
$column['primary'] = true;
|
||||||
$options['primary'][] = $mapping['columnName'];
|
$options['primary'][] = $mapping['columnName'];
|
||||||
|
|
||||||
if ($class->isIdGeneratorIdentity()) {
|
if ($class->isIdGeneratorIdentity()) {
|
||||||
$column['autoincrement'] = true;
|
$column['autoincrement'] = true;
|
||||||
}
|
}
|
||||||
@ -276,12 +290,14 @@ class SchemaTool
|
|||||||
}
|
}
|
||||||
|
|
||||||
$foreignClass = $this->_em->getClassMetadata($mapping->targetEntityName);
|
$foreignClass = $this->_em->getClassMetadata($mapping->targetEntityName);
|
||||||
|
|
||||||
if ($mapping->isOneToOne() && $mapping->isOwningSide) {
|
if ($mapping->isOneToOne() && $mapping->isOwningSide) {
|
||||||
$constraint = array();
|
$constraint = array();
|
||||||
$constraint['tableName'] = $class->getQuotedTableName($this->_platform);
|
$constraint['tableName'] = $class->getQuotedTableName($this->_platform);
|
||||||
$constraint['foreignTable'] = $foreignClass->getQuotedTableName($this->_platform);
|
$constraint['foreignTable'] = $foreignClass->getQuotedTableName($this->_platform);
|
||||||
$constraint['local'] = array();
|
$constraint['local'] = array();
|
||||||
$constraint['foreign'] = array();
|
$constraint['foreign'] = array();
|
||||||
|
|
||||||
foreach ($mapping->getJoinColumns() as $joinColumn) {
|
foreach ($mapping->getJoinColumns() as $joinColumn) {
|
||||||
$column = array();
|
$column = array();
|
||||||
$column['name'] = $mapping->getQuotedJoinColumnName($joinColumn['name'], $this->_platform);
|
$column['name'] = $mapping->getQuotedJoinColumnName($joinColumn['name'], $this->_platform);
|
||||||
@ -289,13 +305,16 @@ class SchemaTool
|
|||||||
$columns[$column['name']] = $column;
|
$columns[$column['name']] = $column;
|
||||||
$constraint['local'][] = $column['name'];
|
$constraint['local'][] = $column['name'];
|
||||||
$constraint['foreign'][] = $joinColumn['referencedColumnName'];
|
$constraint['foreign'][] = $joinColumn['referencedColumnName'];
|
||||||
|
|
||||||
if (isset($joinColumn['onUpdate'])) {
|
if (isset($joinColumn['onUpdate'])) {
|
||||||
$constraint['onUpdate'] = $joinColumn['onUpdate'];
|
$constraint['onUpdate'] = $joinColumn['onUpdate'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($joinColumn['onDelete'])) {
|
if (isset($joinColumn['onDelete'])) {
|
||||||
$constraint['onDelete'] = $joinColumn['onDelete'];
|
$constraint['onDelete'] = $joinColumn['onDelete'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$constraints[] = $constraint;
|
$constraints[] = $constraint;
|
||||||
} else if ($mapping->isOneToMany() && $mapping->isOwningSide) {
|
} else if ($mapping->isOneToMany() && $mapping->isOwningSide) {
|
||||||
//... create join table, one-many through join table supported later
|
//... create join table, one-many through join table supported later
|
||||||
@ -313,6 +332,7 @@ class SchemaTool
|
|||||||
'local' => array(),
|
'local' => array(),
|
||||||
'foreign' => array()
|
'foreign' => array()
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach ($joinTable['joinColumns'] as $joinColumn) {
|
foreach ($joinTable['joinColumns'] as $joinColumn) {
|
||||||
$column = array();
|
$column = array();
|
||||||
$column['primary'] = true;
|
$column['primary'] = true;
|
||||||
@ -322,13 +342,16 @@ class SchemaTool
|
|||||||
$joinTableColumns[$column['name']] = $column;
|
$joinTableColumns[$column['name']] = $column;
|
||||||
$constraint1['local'][] = $column['name'];
|
$constraint1['local'][] = $column['name'];
|
||||||
$constraint1['foreign'][] = $joinColumn['referencedColumnName'];
|
$constraint1['foreign'][] = $joinColumn['referencedColumnName'];
|
||||||
|
|
||||||
if (isset($joinColumn['onUpdate'])) {
|
if (isset($joinColumn['onUpdate'])) {
|
||||||
$constraint1['onUpdate'] = $joinColumn['onUpdate'];
|
$constraint1['onUpdate'] = $joinColumn['onUpdate'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($joinColumn['onDelete'])) {
|
if (isset($joinColumn['onDelete'])) {
|
||||||
$constraint1['onDelete'] = $joinColumn['onDelete'];
|
$constraint1['onDelete'] = $joinColumn['onDelete'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$constraints[] = $constraint1;
|
$constraints[] = $constraint1;
|
||||||
|
|
||||||
// Build second FK constraint (relation table => target table)
|
// Build second FK constraint (relation table => target table)
|
||||||
@ -337,6 +360,7 @@ class SchemaTool
|
|||||||
$constraint2['foreignTable'] = $foreignClass->getQuotedTableName($this->_platform);
|
$constraint2['foreignTable'] = $foreignClass->getQuotedTableName($this->_platform);
|
||||||
$constraint2['local'] = array();
|
$constraint2['local'] = array();
|
||||||
$constraint2['foreign'] = array();
|
$constraint2['foreign'] = array();
|
||||||
|
|
||||||
foreach ($joinTable['inverseJoinColumns'] as $inverseJoinColumn) {
|
foreach ($joinTable['inverseJoinColumns'] as $inverseJoinColumn) {
|
||||||
$column = array();
|
$column = array();
|
||||||
$column['primary'] = true;
|
$column['primary'] = true;
|
||||||
@ -347,19 +371,22 @@ class SchemaTool
|
|||||||
$joinTableColumns[$inverseJoinColumn['name']] = $column;
|
$joinTableColumns[$inverseJoinColumn['name']] = $column;
|
||||||
$constraint2['local'][] = $inverseJoinColumn['name'];
|
$constraint2['local'][] = $inverseJoinColumn['name'];
|
||||||
$constraint2['foreign'][] = $inverseJoinColumn['referencedColumnName'];
|
$constraint2['foreign'][] = $inverseJoinColumn['referencedColumnName'];
|
||||||
|
|
||||||
if (isset($inverseJoinColumn['onUpdate'])) {
|
if (isset($inverseJoinColumn['onUpdate'])) {
|
||||||
$constraint2['onUpdate'] = $inverseJoinColumn['onUpdate'];
|
$constraint2['onUpdate'] = $inverseJoinColumn['onUpdate'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($joinColumn['onDelete'])) {
|
if (isset($joinColumn['onDelete'])) {
|
||||||
$constraint2['onDelete'] = $inverseJoinColumn['onDelete'];
|
$constraint2['onDelete'] = $inverseJoinColumn['onDelete'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$constraints[] = $constraint2;
|
$constraints[] = $constraint2;
|
||||||
|
|
||||||
// Get the SQL for creating the join table and merge it with the others
|
// Get the SQL for creating the join table and merge it with the others
|
||||||
$sql = array_merge($sql, $this->_platform->getCreateTableSql(
|
$sql = array_merge($sql, $this->_platform->getCreateTableSql(
|
||||||
$mapping->getQuotedJoinTableName($this->_platform), $joinTableColumns, $joinTableOptions)
|
$mapping->getQuotedJoinTableName($this->_platform), $joinTableColumns, $joinTableOptions)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -374,6 +401,7 @@ class SchemaTool
|
|||||||
{
|
{
|
||||||
$dropSchemaSql = $this->getDropSchemaSql($classes);
|
$dropSchemaSql = $this->getDropSchemaSql($classes);
|
||||||
$conn = $this->_em->getConnection();
|
$conn = $this->_em->getConnection();
|
||||||
|
|
||||||
foreach ($dropSchemaSql as $sql) {
|
foreach ($dropSchemaSql as $sql) {
|
||||||
$conn->execute($sql);
|
$conn->execute($sql);
|
||||||
}
|
}
|
||||||
@ -390,13 +418,21 @@ class SchemaTool
|
|||||||
$sql = array();
|
$sql = array();
|
||||||
|
|
||||||
$commitOrder = $this->_getCommitOrder($classes);
|
$commitOrder = $this->_getCommitOrder($classes);
|
||||||
|
$associationTables = $this->_getAssociationTables($commitOrder);
|
||||||
|
|
||||||
|
// Drop association tables first
|
||||||
|
foreach ($associationTables as $associationTable) {
|
||||||
|
$sql[] = $this->_platform->getDropTableSql($associationTable);
|
||||||
|
}
|
||||||
|
|
||||||
// Drop tables in reverse commit order
|
// Drop tables in reverse commit order
|
||||||
for ($i = count($commitOrder) - 1; $i >= 0; --$i) {
|
for ($i = count($commitOrder) - 1; $i >= 0; --$i) {
|
||||||
$class = $commitOrder[$i];
|
$class = $commitOrder[$i];
|
||||||
|
|
||||||
if ($class->isInheritanceTypeSingleTable() && $class->name != $class->rootEntityName) {
|
if ($class->isInheritanceTypeSingleTable() && $class->name != $class->rootEntityName) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql[] = $this->_platform->getDropTableSql($class->getTableName());
|
$sql[] = $this->_platform->getDropTableSql($class->getTableName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,6 +452,7 @@ class SchemaTool
|
|||||||
{
|
{
|
||||||
$updateSchemaSql = $this->getUpdateSchemaSql($classes);
|
$updateSchemaSql = $this->getUpdateSchemaSql($classes);
|
||||||
$conn = $this->_em->getConnection();
|
$conn = $this->_em->getConnection();
|
||||||
|
|
||||||
foreach ($updateSchemaSql as $sql) {
|
foreach ($updateSchemaSql as $sql) {
|
||||||
$conn->execute($sql);
|
$conn->execute($sql);
|
||||||
}
|
}
|
||||||
@ -440,13 +477,16 @@ class SchemaTool
|
|||||||
foreach ($classes as $class) {
|
foreach ($classes as $class) {
|
||||||
$tableName = $class->getTableName();
|
$tableName = $class->getTableName();
|
||||||
$tableExists = false;
|
$tableExists = false;
|
||||||
|
|
||||||
foreach ($tables as $index => $table) {
|
foreach ($tables as $index => $table) {
|
||||||
if ($tableName == $table) {
|
if ($tableName == $table) {
|
||||||
$tableExists = true;
|
$tableExists = true;
|
||||||
|
|
||||||
unset($tables[$index]);
|
unset($tables[$index]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! $tableExists) {
|
if ( ! $tableExists) {
|
||||||
$newClasses[] = $class;
|
$newClasses[] = $class;
|
||||||
} else {
|
} else {
|
||||||
@ -456,6 +496,7 @@ class SchemaTool
|
|||||||
|
|
||||||
foreach ($class->fieldMappings as $fieldMapping) {
|
foreach ($class->fieldMappings as $fieldMapping) {
|
||||||
$exists = false;
|
$exists = false;
|
||||||
|
|
||||||
foreach ($currentColumns as $index => $column) {
|
foreach ($currentColumns as $index => $column) {
|
||||||
if ($column['name'] == $fieldMapping['columnName']) {
|
if ($column['name'] == $fieldMapping['columnName']) {
|
||||||
// Column exists, check for changes
|
// Column exists, check for changes
|
||||||
@ -470,6 +511,7 @@ class SchemaTool
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! $exists) {
|
if ( ! $exists) {
|
||||||
$newFields[] = $fieldMapping;
|
$newFields[] = $fieldMapping;
|
||||||
}
|
}
|
||||||
@ -479,6 +521,7 @@ class SchemaTool
|
|||||||
if ($assoc->isOwningSide && $assoc->isOneToOne()) {
|
if ($assoc->isOwningSide && $assoc->isOneToOne()) {
|
||||||
foreach ($assoc->targetToSourceKeyColumns as $targetColumn => $sourceColumn) {
|
foreach ($assoc->targetToSourceKeyColumns as $targetColumn => $sourceColumn) {
|
||||||
$exists = false;
|
$exists = false;
|
||||||
|
|
||||||
foreach ($currentColumns as $index => $column) {
|
foreach ($currentColumns as $index => $column) {
|
||||||
if ($column['name'] == $sourceColumn) {
|
if ($column['name'] == $sourceColumn) {
|
||||||
// Column exists, check for changes
|
// Column exists, check for changes
|
||||||
@ -490,6 +533,7 @@ class SchemaTool
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! $exists) {
|
if ( ! $exists) {
|
||||||
$newJoinColumns[$sourceColumn] = array(
|
$newJoinColumns[$sourceColumn] = array(
|
||||||
'name' => $sourceColumn,
|
'name' => $sourceColumn,
|
||||||
@ -502,23 +546,28 @@ class SchemaTool
|
|||||||
|
|
||||||
if ($newFields || $newJoinColumns) {
|
if ($newFields || $newJoinColumns) {
|
||||||
$changes = array();
|
$changes = array();
|
||||||
|
|
||||||
foreach ($newFields as $newField) {
|
foreach ($newFields as $newField) {
|
||||||
$options = array();
|
$options = array();
|
||||||
$changes['add'][$newField['columnName']] = $this->_gatherColumn($class, $newField, $options);
|
$changes['add'][$newField['columnName']] = $this->_gatherColumn($class, $newField, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($newJoinColumns as $name => $joinColumn) {
|
foreach ($newJoinColumns as $name => $joinColumn) {
|
||||||
$changes['add'][$name] = $joinColumn;
|
$changes['add'][$name] = $joinColumn;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql[] = $this->_platform->getAlterTableSql($tableName, $changes);
|
$sql[] = $this->_platform->getAlterTableSql($tableName, $changes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drop any remaining columns
|
// Drop any remaining columns
|
||||||
if ($currentColumns) {
|
if ($currentColumns) {
|
||||||
$changes = array();
|
$changes = array();
|
||||||
|
|
||||||
foreach ($currentColumns as $column) {
|
foreach ($currentColumns as $column) {
|
||||||
$options = array();
|
$options = array();
|
||||||
$changes['remove'][$column['name']] = $column;
|
$changes['remove'][$column['name']] = $column;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sql[] = $this->_platform->getAlterTableSql($tableName, $changes);
|
$sql[] = $this->_platform->getAlterTableSql($tableName, $changes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -546,12 +595,15 @@ class SchemaTool
|
|||||||
// Calculate dependencies
|
// Calculate dependencies
|
||||||
foreach ($classes as $class) {
|
foreach ($classes as $class) {
|
||||||
$calc->addClass($class);
|
$calc->addClass($class);
|
||||||
|
|
||||||
foreach ($class->associationMappings as $assoc) {
|
foreach ($class->associationMappings as $assoc) {
|
||||||
if ($assoc->isOwningSide) {
|
if ($assoc->isOwningSide) {
|
||||||
$targetClass = $this->_em->getClassMetadata($assoc->targetEntityName);
|
$targetClass = $this->_em->getClassMetadata($assoc->targetEntityName);
|
||||||
|
|
||||||
if ( ! $calc->hasClass($targetClass->name)) {
|
if ( ! $calc->hasClass($targetClass->name)) {
|
||||||
$calc->addClass($targetClass);
|
$calc->addClass($targetClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add dependency ($targetClass before $class)
|
// add dependency ($targetClass before $class)
|
||||||
$calc->addDependency($targetClass, $class);
|
$calc->addDependency($targetClass, $class);
|
||||||
}
|
}
|
||||||
@ -560,4 +612,19 @@ class SchemaTool
|
|||||||
|
|
||||||
return $calc->getCommitOrder();
|
return $calc->getCommitOrder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function _getAssociationTables(array $classes)
|
||||||
|
{
|
||||||
|
$associationTables = array();
|
||||||
|
|
||||||
|
foreach ($classes as $class) {
|
||||||
|
foreach ($class->associationMappings as $assoc) {
|
||||||
|
if ($assoc->isOwningSide && $assoc->isManyToMany()) {
|
||||||
|
$associationTables[] = $assoc->joinTable['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $associationTables;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user