From 2c27435bb2c52dad5cd63fe065bda281c6a831b9 Mon Sep 17 00:00:00 2001 From: beberlei <beberlei@625475ce-881a-0410-a577-b389adb331d8> Date: Sat, 28 Nov 2009 10:48:51 +0000 Subject: [PATCH] [2.0] - DDC-169 - Completed refactoring of SchemaTool::getCreateSql() to use new DBAL Schema API, several internal optimizations in SchemaTool are now possible. Stripped out shared functionality with getUpdateSql() so that this part of SchemaTool is still completly working with the old API. --- lib/Doctrine/ORM/Tools/SchemaTool.php | 330 +++++++----------- .../SchemaTool/MySqlSchemaToolTest.php | 4 +- 2 files changed, 134 insertions(+), 200 deletions(-) diff --git a/lib/Doctrine/ORM/Tools/SchemaTool.php b/lib/Doctrine/ORM/Tools/SchemaTool.php index cbab1a4b6..15b7a9729 100644 --- a/lib/Doctrine/ORM/Tools/SchemaTool.php +++ b/lib/Doctrine/ORM/Tools/SchemaTool.php @@ -97,7 +97,6 @@ class SchemaTool { $sql = array(); // All SQL statements $processedClasses = array(); // Reminder for processed classes, used for hierarchies - $foreignKeyConstraints = array(); // FK SQL statements. Appended to $sql at the end. $sequences = array(); // Sequence SQL statements. Appended to $sql at the end. $schema = new \Doctrine\DBAL\Schema\Schema(); @@ -115,16 +114,14 @@ class SchemaTool $table->setIdGeneratorType(\Doctrine\DBAL\Schema\Table::ID_SEQUENCE); } - $options = array(); // table options $columns = array(); // table columns if ($class->isInheritanceTypeSingleTable()) { - $columns = $this->_gatherColumns($class, $options, $table); - $this->_gatherRelationsSql($class, $sql, $columns, $foreignKeyConstraints, $table, $schema); + $columns = $this->_gatherColumns($class, $table); + $this->_gatherRelationsSql($class, $sql, $columns, $table, $schema); // Add the discriminator column $discrColumnDef = $this->_getDiscriminatorColumnDefinition($class, $table); - $columns[$discrColumnDef['name']] = $discrColumnDef; // Aggregate all the information from all classes in the hierarchy foreach ($class->parentClasses as $parentClassName) { @@ -134,8 +131,8 @@ class SchemaTool foreach ($class->subClasses as $subClassName) { $subClass = $this->_em->getClassMetadata($subClassName); - $columns = array_merge($columns, $this->_gatherColumns($subClass, $options, $table)); - $this->_gatherRelationsSql($subClass, $sql, $columns, $foreignKeyConstraints, $table, $schema); + $this->_gatherColumns($subClass, $table); + $this->_gatherRelationsSql($subClass, $table, $schema); $processedClasses[$subClassName] = true; } } else if ($class->isInheritanceTypeJoined()) { @@ -144,7 +141,7 @@ class SchemaTool foreach ($class->fieldMappings as $fieldName => $mapping) { if ( ! isset($mapping['inherited'])) { $columnName = $class->getQuotedColumnName($mapping['fieldName'], $this->_platform); - $columns[$columnName] = $this->_gatherColumn($class, $mapping, $options, $table); + $this->_gatherColumn($class, $mapping, $table); if ($class->isIdentifier($fieldName)) { $pkColumns[] = $columnName; @@ -152,38 +149,28 @@ class SchemaTool } } - $this->_gatherRelationsSql($class, $sql, $columns, $foreignKeyConstraints, $table, $schema); + $this->_gatherRelationsSql($class, $table, $schema); // Add the discriminator column only to the root table if ($class->name == $class->rootEntityName) { $discrColumnDef = $this->_getDiscriminatorColumnDefinition($class, $table); - $columns[$discrColumnDef['name']] = $discrColumnDef; } else { // Add an ID FK column to child tables + /* @var Doctrine\ORM\Mapping\ClassMetadata $class */ $idMapping = $class->fieldMappings[$class->identifier[0]]; - $idColumn = $this->_gatherColumn($class, $idMapping, $options, $table); + $this->_gatherColumn($class, $idMapping, $table); + $columnName = $class->getQuotedColumnName($class->identifier[0], $this->_platform); - unset($idColumn['autoincrement']); - $pkColumns[] = $idColumn['name']; + $pkColumns[] = $columnName; if ($table->isIdGeneratorIdentity()) { $table->setIdGeneratorType(\Doctrine\DBAL\Schema\Table::ID_NONE); } - - $columns[$idColumn['name']] = $idColumn; // Add a FK constraint on the ID column - $constraint = array(); - $constraint['tableName'] = $class->getQuotedTableName($this->_platform); - $constraint['foreignTable'] = $this->_em->getClassMetadata($class->rootEntityName)->getQuotedTableName($this->_platform); - $constraint['local'] = array($idColumn['name']); - $constraint['foreign'] = array($idColumn['name']); - $constraint['onDelete'] = 'CASCADE'; - $foreignKeyConstraints[] = $constraint; - $table->addForeignKeyConstraint( $this->_em->getClassMetadata($class->rootEntityName)->getQuotedTableName($this->_platform), - $constraint['local'], $constraint['foreign'], null, - $constraint + array($columnName), array($columnName), null, + array('onDelete' => 'CASCADE') ); } @@ -192,80 +179,38 @@ class SchemaTool } else if ($class->isInheritanceTypeTablePerClass()) { throw DoctrineException::notSupported(); } else { - $columns = $this->_gatherColumns($class, $options, $table); - $this->_gatherRelationsSql($class, $sql, $columns, $foreignKeyConstraints, $table, $schema); + $this->_gatherColumns($class, $table); + $this->_gatherRelationsSql($class, $table, $schema); } if (isset($class->primaryTable['indexes'])) { - $options['indexes'] = $class->primaryTable['indexes']; - - foreach($class->primaryTable['indexes'] AS $indexName => $indexData) { + foreach ($class->primaryTable['indexes'] AS $indexName => $indexData) { $table->addIndex($indexData, $indexName); } } if (isset($class->primaryTable['uniqueConstraints'])) { - $options['uniqueConstraints'] = $class->primaryTable['uniqueConstraints']; - - foreach($class->primaryTable['uniqueConstraints'] AS $indexName => $indexData) { + foreach ($class->primaryTable['uniqueConstraints'] AS $indexName => $indexData) { $table->addUniqueIndex($indexData, $indexName); } } - $sql = array_merge($sql, $this->_platform->getCreateTableSql( - $class->getQuotedTableName($this->_platform), $columns, $options) - ); - $processedClasses[$class->name] = true; - // TODO if we're reusing the sequence previously defined (in another model), - // it should not attempt to create a new sequence. if ($class->isIdGeneratorSequence() && $class->name == $class->rootEntityName) { $seqDef = $class->getSequenceGeneratorDefinition(); - if(!$schema->hasSequence($seqDef['sequenceName'])) { + if (!$schema->hasSequence($seqDef['sequenceName'])) { $schema->createSequence( $seqDef['sequenceName'], $seqDef['allocationSize'], $seqDef['initialValue'] ); } - - $sequences[] = $this->_platform->getCreateSequenceSql( - $seqDef['sequenceName'], - $seqDef['initialValue'], - $seqDef['allocationSize'] - ); } } - - // Append the foreign key constraints SQL - if ($this->_platform->supportsForeignKeyConstraints()) { - foreach ($foreignKeyConstraints as $fkConstraint) { - $sql = array_merge($sql, (array) $this->_platform->getCreateForeignKeySql($fkConstraint['tableName'], $fkConstraint)); - } - } - - /*try { - $newSql = $schema->toSql($this->_platform); - #return $newSql; - } catch(\Exception $e) { - - }*/ - - // Append the sequence SQL - $sql = array_merge($sql, $sequences); - /*$sql2 = $sql; - sort($sql2); - sort($newSql); - - if($newSql !== $sql2) { - var_dump($newSql); - var_dump($sql2); - die(); - }*/ - - return $sql; + + return $schema->toSql($this->_platform); } /** @@ -285,13 +230,6 @@ class SchemaTool $discrColumn['type'], array('length' => $discrColumn['length'], 'notnull' => true) ); - - return array( - 'name' => $class->getQuotedDiscriminatorColumnName($this->_platform), - 'type' => Type::getType($discrColumn['type']), - 'length' => $discrColumn['length'], - 'notnull' => true - ); } /** @@ -299,22 +237,19 @@ class SchemaTool * found in the given class. * * @param ClassMetadata $class - * @param array $options The table options/constraints where any additional options/constraints - * that are required by columns should be appended. * @param Table $table * @return array The list of portable column definitions as required by the DBAL. */ - private function _gatherColumns($class, array &$options, $table) + private function _gatherColumns($class, $table) { $columns = array(); $pkColumns = array(); foreach ($class->fieldMappings as $fieldName => $mapping) { - $column = $this->_gatherColumn($class, $mapping, $options, $table); - $columns[$column['name']] = $column; - + $column = $this->_gatherColumn($class, $mapping, $table); + if ($class->isIdentifier($mapping['fieldName'])) { - $pkColumns[] = $column['name']; + $pkColumns[] = $class->getQuotedColumnName($mapping['fieldName'], $this->_platform); } } // For now, this is a hack required for single table inheritence, since this method is called @@ -323,7 +258,6 @@ class SchemaTool $table->setPrimaryKey($pkColumns); } - return $columns; } @@ -332,55 +266,44 @@ class SchemaTool * * @param ClassMetadata $class The class that owns the field mapping. * @param array $mapping The field mapping. - * @param array $options The table options/constraints where any additional options/constraints - * required by the column should be appended. * @param Table $table * @return array The portable column definition as required by the DBAL. */ - private function _gatherColumn($class, array $mapping, array &$options, $table) + private function _gatherColumn($class, array $mapping, $table) { - $column = array(); - $column['name'] = $class->getQuotedColumnName($mapping['fieldName'], $this->_platform); - $column['type'] = Type::getType($mapping['type']); - $column['length'] = isset($mapping['length']) ? $mapping['length'] : null; - $column['notnull'] = isset($mapping['nullable']) ? ! $mapping['nullable'] : true; - $column['unique'] = isset($mapping['unique']) ? $mapping['unique'] : false; - $column['version'] = $class->isVersioned && $class->versionField == $mapping['fieldName'] ? true : false; + $columnName = $class->getQuotedColumnName($mapping['fieldName'], $this->_platform); + $columnType = $mapping['type']; - if(strtolower($column['type']) == 'string' && $column['length'] === null) { - $column['length'] = 255; + $options = array(); + $options['length'] = isset($mapping['length']) ? $mapping['length'] : null; + $options['notnull'] = isset($mapping['nullable']) ? ! $mapping['nullable'] : true; + + $options['platformOptions'] = array(); + $options['platformOptions']['unique'] = isset($mapping['unique']) ? $mapping['unique'] : false; + $options['platformOptions']['version'] = $class->isVersioned && $class->versionField == $mapping['fieldName'] ? true : false; + + if(strtolower($columnType) == 'string' && $options['length'] === null) { + $options['length'] = 255; } if (isset($mapping['precision'])) { - $column['precision'] = $mapping['precision']; + $options['precision'] = $mapping['precision']; } if (isset($mapping['scale'])) { - $column['scale'] = $mapping['scale']; + $options['scale'] = $mapping['scale']; } if (isset($mapping['default'])) { - $column['default'] = $mapping['default']; + $options['default'] = $mapping['default']; } - $column['platformOptions']['unique'] = $column['unique']; - $column['platformOptions']['version'] = $column['version']; - if ($table->hasColumn($column['name'])) { - $table->changeColumn($column['name'], $column); + if ($table->hasColumn($columnName)) { + // required in some inheritence scenarios + $table->changeColumn($columnName, $options); } else { - $table->createColumn($column['name'], $mapping['type'], $column); + $table->createColumn($columnName, $columnType, $options); } - - if ($class->isIdentifier($mapping['fieldName'])) { - $column['primary'] = true; - $options['primary'][] = $mapping['columnName']; - - if ($class->isIdGeneratorIdentity()) { - $column['autoincrement'] = true; - } - } - - return $column; } /** @@ -395,7 +318,7 @@ class SchemaTool * required by relations should be appended. * @return void */ - private function _gatherRelationsSql($class, array &$sql, array &$columns, array &$constraints, $table, $schema) + private function _gatherRelationsSql($class, $table, $schema) { foreach ($class->associationMappings as $fieldName => $mapping) { if (isset($class->inheritedAssociationFields[$fieldName])) { @@ -405,15 +328,12 @@ class SchemaTool $foreignClass = $this->_em->getClassMetadata($mapping->targetEntityName); if ($mapping->isOneToOne() && $mapping->isOwningSide) { - $constraint = array(); - $constraint['tableName'] = $class->getQuotedTableName($this->_platform); - $constraint['foreignTable'] = $foreignClass->getQuotedTableName($this->_platform); - $constraint['local'] = array(); - $constraint['foreign'] = array(); + $options = array(); + $localColumns = array(); + $foreignColumns = array(); foreach ($mapping->getJoinColumns() as $joinColumn) { - $column = array(); - $column['name'] = $mapping->getQuotedJoinColumnName($joinColumn['name'], $this->_platform); + $columnName = $mapping->getQuotedJoinColumnName($joinColumn['name'], $this->_platform); $referencedColumnName = $joinColumn['referencedColumnName']; $referencedFieldName = $foreignClass->getFieldName($referencedColumnName); if (!$foreignClass->hasField($referencedFieldName)) { @@ -422,107 +342,82 @@ class SchemaTool "$mapping->sourceEntityName towards $mapping->targetEntityName does not exist." ); } - $column['type'] = Type::getType($foreignClass->getTypeOfField($referencedFieldName)); - $table->createColumn($column['name'], $foreignClass->getTypeOfField($referencedFieldName), array('notnull' => false)); + $table->createColumn( + $columnName, $foreignClass->getTypeOfField($referencedFieldName), array('notnull' => false) + ); - $columns[$column['name']] = $column; - $constraint['local'][] = $column['name']; - $constraint['foreign'][] = $joinColumn['referencedColumnName']; + $localColumns[] = $columnName; + $foreignColumns[] = $joinColumn['referencedColumnName']; if (isset($joinColumn['onUpdate'])) { - $constraint['onUpdate'] = $joinColumn['onUpdate']; + $options['onUpdate'] = $joinColumn['onUpdate']; } if (isset($joinColumn['onDelete'])) { - $constraint['onDelete'] = $joinColumn['onDelete']; + $options['onDelete'] = $joinColumn['onDelete']; } } $table->addForeignKeyConstraint( $foreignClass->getQuotedTableName($this->_platform), - $constraint['local'], $constraint['foreign'], null, - $constraint + $localColumns, $foreignColumns, null, $options ); - - $constraints[] = $constraint; } else if ($mapping->isOneToMany() && $mapping->isOwningSide) { //... create join table, one-many through join table supported later throw DoctrineException::notSupported(); } else if ($mapping->isManyToMany() && $mapping->isOwningSide) { // create join table - $joinTableColumns = array(); - $joinTableOptions = array('primary' => array(), 'uniqueConstraints' => array()); $joinTable = $mapping->getJoinTable(); - - // Build first FK constraint (relation table => source table) - $constraint1 = array( - 'tableName' => $mapping->getQuotedJoinTableName($this->_platform), - 'foreignTable' => $class->getQuotedTableName($this->_platform), - 'local' => array(), - 'foreign' => array() - ); + + $localColumns = array(); + $foreignColumns = array(); + $fkOptions = array(); $theJoinTable = $schema->createTable($mapping->getQuotedJoinTableName($this->_platform)); $primaryKeyColumns = array(); + $uniqueConstraints = array(); foreach ($joinTable['joinColumns'] as $joinColumn) { - $column = array(); - $column['primary'] = true; - $joinTableOptions['primary'][] = $joinColumn['name']; - $primaryKeyColumns[] = $joinColumn['name']; - $column['name'] = $mapping->getQuotedJoinColumnName($joinColumn['name'], $this->_platform); - $column['type'] = Type::getType($class->getTypeOfColumn($joinColumn['referencedColumnName'])); - $joinTableColumns[$column['name']] = $column; + $columnName = $mapping->getQuotedJoinColumnName($joinColumn['name'], $this->_platform); $theJoinTable->createColumn( - $mapping->getQuotedJoinColumnName($joinColumn['name'], $this->_platform), + $columnName, $class->getTypeOfColumn($joinColumn['referencedColumnName']), array('notnull' => false) ); - $constraint1['local'][] = $column['name']; - $constraint1['foreign'][] = $joinColumn['referencedColumnName']; + $primaryKeyColumns[] = $columnName; + + $localColumns[] = $columnName; + $foreignColumns[] = $joinColumn['referencedColumnName']; if(isset($joinColumn['unique']) && $joinColumn['unique'] == true) { - $joinTableOptions['uniqueConstraints'][] = array($joinColumn['name']); + $uniqueConstraints[] = array($joinColumn['name']); } if (isset($joinColumn['onUpdate'])) { - $constraint1['onUpdate'] = $joinColumn['onUpdate']; + $fkOptions['onUpdate'] = $joinColumn['onUpdate']; } if (isset($joinColumn['onDelete'])) { - $constraint1['onDelete'] = $joinColumn['onDelete']; + $fkOptions['onDelete'] = $joinColumn['onDelete']; } } + // Build first FK constraint (relation table => source table) $theJoinTable->addForeignKeyConstraint( - $class->getQuotedTableName($this->_platform), - $constraint1['local'], $constraint1['foreign'], null, - $constraint1 + $class->getQuotedTableName($this->_platform), $localColumns, $foreignColumns, null, $fkOptions ); - - $constraints[] = $constraint1; - - // Build second FK constraint (relation table => target table) - $constraint2 = array(); - $constraint2['tableName'] = $mapping->getQuotedJoinTableName($this->_platform); - $constraint2['foreignTable'] = $foreignClass->getQuotedTableName($this->_platform); - $constraint2['local'] = array(); - $constraint2['foreign'] = array(); + + $localColumns = array(); + $foreignColumns = array(); + $fkOptions = array(); foreach ($joinTable['inverseJoinColumns'] as $inverseJoinColumn) { - $column = array(); - $column['primary'] = true; - $joinTableOptions['primary'][] = $inverseJoinColumn['name']; $primaryKeyColumns[] = $inverseJoinColumn['name']; - $column['name'] = $inverseJoinColumn['name']; - $column['type'] = Type::getType($this->_em->getClassMetadata($mapping->getTargetEntityName()) - ->getTypeOfColumn($inverseJoinColumn['referencedColumnName'])); - $joinTableColumns[$inverseJoinColumn['name']] = $column; - $constraint2['local'][] = $inverseJoinColumn['name']; - $constraint2['foreign'][] = $inverseJoinColumn['referencedColumnName']; + $localColumns[] = $inverseJoinColumn['name']; + $foreignColumns[] = $inverseJoinColumn['referencedColumnName']; $theJoinTable->createColumn( $inverseJoinColumn['name'], @@ -532,36 +427,28 @@ class SchemaTool ); if(isset($inverseJoinColumn['unique']) && $inverseJoinColumn['unique'] == true) { - $joinTableOptions['uniqueConstraints'][] = array($inverseJoinColumn['name']); + $uniqueConstraints[] = array($inverseJoinColumn['name']); } if (isset($inverseJoinColumn['onUpdate'])) { - $constraint2['onUpdate'] = $inverseJoinColumn['onUpdate']; + $fkOptions['onUpdate'] = $inverseJoinColumn['onUpdate']; } if (isset($joinColumn['onDelete'])) { - $constraint2['onDelete'] = $inverseJoinColumn['onDelete']; + $fkOptions['onDelete'] = $inverseJoinColumn['onDelete']; } } - foreach($joinTableOptions['uniqueConstraints'] AS $unique) { + foreach($uniqueConstraints AS $unique) { $theJoinTable->addUniqueIndex($unique); } + // Build second FK constraint (relation table => target table) $theJoinTable->addForeignKeyConstraint( - $foreignClass->getQuotedTableName($this->_platform), - $constraint2['local'], $constraint2['foreign'], null, - $constraint2 + $foreignClass->getQuotedTableName($this->_platform), $localColumns, $foreignColumns, null, $fkOptions ); $theJoinTable->setPrimaryKey($primaryKeyColumns); - - $constraints[] = $constraint2; - - // Get the SQL for creating the join table and merge it with the others - $sql = array_merge($sql, $this->_platform->getCreateTableSql( - $mapping->getQuotedJoinTableName($this->_platform), $joinTableColumns, $joinTableOptions) - ); } } } @@ -862,7 +749,7 @@ class SchemaTool foreach ($newFields as $newField) { $options = array(); $table = new \Doctrine\DBAL\Schema\Table("foo"); - $changes['add'][$newField['columnName']] = $this->_gatherColumn($class, $newField, $options, $table); + $changes['add'][$newField['columnName']] = $this->_gatherUpdateColumn($class, $newField, $options, $table); } foreach ($newJoinColumns as $name => $joinColumn) { @@ -914,6 +801,53 @@ class SchemaTool return $sql; } + + /** + * Temporary method, required because schema update is not on par with schema create refactorings. + * + * @param <type> $class + * @param array $mapping + * @param array $options + * @param <type> $table + * @return <type> + */ + private function _gatherUpdateColumn($class, array $mapping, array &$options, $table) + { + $column = array(); + $column['name'] = $class->getQuotedColumnName($mapping['fieldName'], $this->_platform); + $column['type'] = Type::getType($mapping['type']); + $column['length'] = isset($mapping['length']) ? $mapping['length'] : null; + $column['notnull'] = isset($mapping['nullable']) ? ! $mapping['nullable'] : true; + $column['unique'] = isset($mapping['unique']) ? $mapping['unique'] : false; + $column['version'] = $class->isVersioned && $class->versionField == $mapping['fieldName'] ? true : false; + + if(strtolower($column['type']) == 'string' && $column['length'] === null) { + $column['length'] = 255; + } + + if (isset($mapping['precision'])) { + $column['precision'] = $mapping['precision']; + } + + if (isset($mapping['scale'])) { + $column['scale'] = $mapping['scale']; + } + + if (isset($mapping['default'])) { + $column['default'] = $mapping['default']; + } + + if ($class->isIdentifier($mapping['fieldName'])) { + $column['primary'] = true; + $options['primary'][] = $mapping['columnName']; + + if ($class->isIdGeneratorIdentity()) { + $column['autoincrement'] = true; + } + } + + return $column; + } private function _getCommitOrder(array $classes) { diff --git a/tests/Doctrine/Tests/ORM/Functional/SchemaTool/MySqlSchemaToolTest.php b/tests/Doctrine/Tests/ORM/Functional/SchemaTool/MySqlSchemaToolTest.php index 9ff2a8fc6..aa8533e21 100644 --- a/tests/Doctrine/Tests/ORM/Functional/SchemaTool/MySqlSchemaToolTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/SchemaTool/MySqlSchemaToolTest.php @@ -28,8 +28,8 @@ class MySqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase $sql = $tool->getCreateSchemaSql($classes); $this->assertEquals(count($sql), 8); $this->assertEquals("CREATE TABLE cms_addresses (id INT AUTO_INCREMENT NOT NULL, country VARCHAR(50) NOT NULL, zip VARCHAR(50) NOT NULL, city VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, PRIMARY KEY(id)) ENGINE = InnoDB", $sql[0]); - $this->assertEquals("CREATE TABLE cms_users_groups (user_id INT DEFAULT NULL, group_id INT DEFAULT NULL, PRIMARY KEY(user_id, group_id)) ENGINE = InnoDB", $sql[1]); - $this->assertEquals("CREATE TABLE cms_users (id INT AUTO_INCREMENT NOT NULL, status VARCHAR(50) NOT NULL, username VARCHAR(255) NOT NULL UNIQUE, name VARCHAR(255) NOT NULL, PRIMARY KEY(id)) ENGINE = InnoDB", $sql[2]); + $this->assertEquals("CREATE TABLE cms_users (id INT AUTO_INCREMENT NOT NULL, status VARCHAR(50) NOT NULL, username VARCHAR(255) NOT NULL UNIQUE, name VARCHAR(255) NOT NULL, PRIMARY KEY(id)) ENGINE = InnoDB", $sql[1]); + $this->assertEquals("CREATE TABLE cms_users_groups (user_id INT DEFAULT NULL, group_id INT DEFAULT NULL, PRIMARY KEY(user_id, group_id)) ENGINE = InnoDB", $sql[2]); $this->assertEquals("CREATE TABLE cms_phonenumbers (phonenumber VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, PRIMARY KEY(phonenumber)) ENGINE = InnoDB", $sql[3]); $this->assertEquals("ALTER TABLE cms_addresses ADD FOREIGN KEY (user_id) REFERENCES cms_users(id)", $sql[4]); $this->assertEquals("ALTER TABLE cms_users_groups ADD FOREIGN KEY (user_id) REFERENCES cms_users(id)", $sql[5]);