Unverified Commit d4fec7cd authored by Guilherme Blanco's avatar Guilherme Blanco Committed by Sergei Morozov

Decouple unique index from unique constraint

parent 9dbec4b5
...@@ -23,6 +23,7 @@ use Doctrine\DBAL\Schema\Index; ...@@ -23,6 +23,7 @@ use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\Sequence; use Doctrine\DBAL\Schema\Sequence;
use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Schema\TableDiff;
use Doctrine\DBAL\Schema\UniqueConstraint;
use Doctrine\DBAL\TransactionIsolationLevel; use Doctrine\DBAL\TransactionIsolationLevel;
use Doctrine\DBAL\Types; use Doctrine\DBAL\Types;
use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Type;
...@@ -1534,15 +1535,30 @@ abstract class AbstractPlatform ...@@ -1534,15 +1535,30 @@ abstract class AbstractPlatform
$options['indexes'] = []; $options['indexes'] = [];
$options['primary'] = []; $options['primary'] = [];
if (($createFlags&self::CREATE_INDEXES) > 0) { if (($createFlags & self::CREATE_INDEXES) > 0) {
foreach ($table->getIndexes() as $index) { foreach ($table->getIndexes() as $index) {
/** @var $index Index */ /** @var $index Index */
if ($index->isPrimary()) { if (! $index->isPrimary()) {
$options['primary'] = $index->getQuotedColumns($this);
$options['primary_index'] = $index;
} else {
$options['indexes'][$index->getQuotedName($this)] = $index; $options['indexes'][$index->getQuotedName($this)] = $index;
continue;
} }
$options['primary'] = $index->getQuotedColumns($this);
$options['primary_index'] = $index;
}
foreach ($table->getUniqueConstraints() as $uniqueConstraint) {
/** @var UniqueConstraint $uniqueConstraint */
$options['uniqueConstraints'][$uniqueConstraint->getQuotedName($this)] = $uniqueConstraint;
}
}
if (($createFlags & self::CREATE_FOREIGNKEYS) > 0) {
$options['foreignKeys'] = [];
foreach ($table->getForeignKeys() as $fkConstraint) {
$options['foreignKeys'][] = $fkConstraint;
} }
} }
...@@ -1551,7 +1567,6 @@ abstract class AbstractPlatform ...@@ -1551,7 +1567,6 @@ abstract class AbstractPlatform
foreach ($table->getColumns() as $column) { foreach ($table->getColumns() as $column) {
/** @var Column $column */ /** @var Column $column */
if ($this->_eventManager !== null && $this->_eventManager->hasListeners(Events::onSchemaCreateTableColumn)) { if ($this->_eventManager !== null && $this->_eventManager->hasListeners(Events::onSchemaCreateTableColumn)) {
$eventArgs = new SchemaCreateTableColumnEventArgs($column, $table, $this); $eventArgs = new SchemaCreateTableColumnEventArgs($column, $table, $this);
$this->_eventManager->dispatchEvent(Events::onSchemaCreateTableColumn, $eventArgs); $this->_eventManager->dispatchEvent(Events::onSchemaCreateTableColumn, $eventArgs);
...@@ -1579,13 +1594,6 @@ abstract class AbstractPlatform ...@@ -1579,13 +1594,6 @@ abstract class AbstractPlatform
$columns[$columnData['name']] = $columnData; $columns[$columnData['name']] = $columnData;
} }
if (($createFlags&self::CREATE_FOREIGNKEYS) > 0) {
$options['foreignKeys'] = [];
foreach ($table->getForeignKeys() as $fkConstraint) {
$options['foreignKeys'][] = $fkConstraint;
}
}
if ($this->_eventManager !== null && $this->_eventManager->hasListeners(Events::onSchemaCreateTable)) { if ($this->_eventManager !== null && $this->_eventManager->hasListeners(Events::onSchemaCreateTable)) {
$eventArgs = new SchemaCreateTableEventArgs($table, $columns, $options, $this); $eventArgs = new SchemaCreateTableEventArgs($table, $columns, $options, $this);
$this->_eventManager->dispatchEvent(Events::onSchemaCreateTable, $eventArgs); $this->_eventManager->dispatchEvent(Events::onSchemaCreateTable, $eventArgs);
......
...@@ -893,10 +893,11 @@ class SqlitePlatform extends AbstractPlatform ...@@ -893,10 +893,11 @@ class SqlitePlatform extends AbstractPlatform
$sql = []; $sql = [];
$tableSql = []; $tableSql = [];
if (! $this->onSchemaAlterTable($diff, $tableSql)) { if (! $this->onSchemaAlterTable($diff, $tableSql)) {
$dataTable = new Table('__temp__' . $table->getName()); $dataTable = new Table('__temp__' . $table->getName());
$newTable = new Table($table->getQuotedName($this), $columns, $this->getPrimaryIndexInAlteredTable($diff), $this->getForeignKeysInAlteredTable($diff), 0, $table->getOptions()); $newTable = new Table($table->getQuotedName($this), $columns, $this->getPrimaryIndexInAlteredTable($diff), [], $this->getForeignKeysInAlteredTable($diff), 0, $table->getOptions());
$newTable->addOption('alter', true); $newTable->addOption('alter', true);
$sql = $this->getPreAlterTableIndexForeignKeySQL($diff); $sql = $this->getPreAlterTableIndexForeignKeySQL($diff);
......
...@@ -263,12 +263,14 @@ abstract class AbstractSchemaManager ...@@ -263,12 +263,14 @@ abstract class AbstractSchemaManager
{ {
$columns = $this->listTableColumns($tableName); $columns = $this->listTableColumns($tableName);
$foreignKeys = []; $foreignKeys = [];
if ($this->_platform->supportsForeignKeyConstraints()) { if ($this->_platform->supportsForeignKeyConstraints()) {
$foreignKeys = $this->listTableForeignKeys($tableName); $foreignKeys = $this->listTableForeignKeys($tableName);
} }
$indexes = $this->listTableIndexes($tableName); $indexes = $this->listTableIndexes($tableName);
return new Table($tableName, $columns, $indexes, $foreignKeys, false, []); return new Table($tableName, $columns, $indexes, [], $foreignKeys, false, []);
} }
/** /**
...@@ -587,6 +589,7 @@ abstract class AbstractSchemaManager ...@@ -587,6 +589,7 @@ abstract class AbstractSchemaManager
public function alterTable(TableDiff $tableDiff) public function alterTable(TableDiff $tableDiff)
{ {
$queries = $this->_platform->getAlterTableSQL($tableDiff); $queries = $this->_platform->getAlterTableSQL($tableDiff);
if (! is_array($queries) || ! count($queries)) { if (! is_array($queries) || ! count($queries)) {
return; return;
} }
......
...@@ -57,6 +57,7 @@ class Index extends AbstractAsset implements Constraint ...@@ -57,6 +57,7 @@ class Index extends AbstractAsset implements Constraint
$isUnique = $isUnique || $isPrimary; $isUnique = $isUnique || $isPrimary;
$this->_setName($indexName); $this->_setName($indexName);
$this->_isUnique = $isUnique; $this->_isUnique = $isUnique;
$this->_isPrimary = $isPrimary; $this->_isPrimary = $isPrimary;
$this->options = $options; $this->options = $options;
...@@ -64,6 +65,7 @@ class Index extends AbstractAsset implements Constraint ...@@ -64,6 +65,7 @@ class Index extends AbstractAsset implements Constraint
foreach ($columns as $column) { foreach ($columns as $column) {
$this->_addColumn($column); $this->_addColumn($column);
} }
foreach ($flags as $flag) { foreach ($flags as $flag) {
$this->addFlag($flag); $this->addFlag($flag);
} }
......
...@@ -18,7 +18,8 @@ class SchemaException extends DBALException ...@@ -18,7 +18,8 @@ class SchemaException extends DBALException
public const SEQUENCE_ALREADY_EXISTS = 80; public const SEQUENCE_ALREADY_EXISTS = 80;
public const INDEX_INVALID_NAME = 90; public const INDEX_INVALID_NAME = 90;
public const FOREIGNKEY_DOESNT_EXIST = 100; public const FOREIGNKEY_DOESNT_EXIST = 100;
public const NAMESPACE_ALREADY_EXISTS = 110; public const CONSTRAINT_DOESNT_EXIST = 110;
public const NAMESPACE_ALREADY_EXISTS = 120;
/** /**
* @param string $tableName * @param string $tableName
...@@ -142,6 +143,21 @@ class SchemaException extends DBALException ...@@ -142,6 +143,21 @@ class SchemaException extends DBALException
return new self("There exists no sequence with the name '" . $sequenceName . "'.", self::SEQUENCE_DOENST_EXIST); return new self("There exists no sequence with the name '" . $sequenceName . "'.", self::SEQUENCE_DOENST_EXIST);
} }
/**
* @param string $constraintName
* @param string $table
*
* @return self
*/
public static function uniqueConstraintDoesNotExist($constraintName, $table)
{
return new self(sprintf(
'There exists no unique constraint with the name "%s" on table "%s".',
$constraintName,
$table
), self::CONSTRAINT_DOESNT_EXIST);
}
/** /**
* @param string $fkName * @param string $fkName
* @param string $table * @param string $table
......
This diff is collapsed.
<?php
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use InvalidArgumentException;
use function array_keys;
use function array_map;
use function is_string;
use function strtolower;
/**
* Class for a unique constraint.
*/
class UniqueConstraint extends AbstractAsset implements Constraint
{
/**
* Asset identifier instances of the column names the unique constraint is associated with.
* array($columnName => Identifier)
*
* @var Identifier[]
*/
protected $columns = [];
/**
* Platform specific options
*
* @var mixed[]
*/
private $options = [];
/**
* @param string $indexName
* @param string[] $columns
* @param mixed[] $options
*/
public function __construct($indexName, array $columns, array $options = [])
{
$this->_setName($indexName);
$this->options = $options;
foreach ($columns as $column) {
$this->_addColumn($column);
}
}
/**
* @param string $column
*
* @return void
*
* @throws InvalidArgumentException
*/
protected function _addColumn($column)
{
if (! is_string($column)) {
throw new InvalidArgumentException('Expecting a string as Index Column');
}
$this->_columns[$column] = new Identifier($column);
}
/**
* {@inheritdoc}
*/
public function getColumns()
{
return array_keys($this->_columns);
}
/**
* {@inheritdoc}
*/
public function getQuotedColumns(AbstractPlatform $platform)
{
$columns = [];
foreach ($this->_columns as $column) {
$columns[] = $column->getQuotedName($platform);
}
return $columns;
}
/**
* @return string[]
*/
public function getUnquotedColumns()
{
return array_map([$this, 'trimQuotes'], $this->getColumns());
}
/**
* @param string $name
*
* @return bool
*/
public function hasOption($name)
{
return isset($this->options[strtolower($name)]);
}
/**
* @param string $name
*
* @return mixed
*/
public function getOption($name)
{
return $this->options[strtolower($name)];
}
/**
* @return mixed[]
*/
public function getOptions()
{
return $this->options;
}
}
...@@ -314,6 +314,7 @@ class ExceptionTest extends DbalFunctionalTestCase ...@@ -314,6 +314,7 @@ class ExceptionTest extends DbalFunctionalTestCase
$table->addColumn('id', 'integer'); $table->addColumn('id', 'integer');
$this->expectException($exceptionClass); $this->expectException($exceptionClass);
foreach ($schema->toSql($conn->getDatabasePlatform()) as $sql) { foreach ($schema->toSql($conn->getDatabasePlatform()) as $sql) {
$conn->exec($sql); $conn->exec($sql);
} }
......
...@@ -976,7 +976,7 @@ class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase ...@@ -976,7 +976,7 @@ class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase
protected function getTestTable($name, $options = []) protected function getTestTable($name, $options = [])
{ {
$table = new Table($name, [], [], [], false, $options); $table = new Table($name, [], [], [], [], false, $options);
$table->setSchemaConfig($this->schemaManager->createSchemaConfig()); $table->setSchemaConfig($this->schemaManager->createSchemaConfig());
$table->addColumn('id', 'integer', ['notnull' => true]); $table->addColumn('id', 'integer', ['notnull' => true]);
$table->setPrimaryKey(['id']); $table->setPrimaryKey(['id']);
...@@ -987,7 +987,7 @@ class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase ...@@ -987,7 +987,7 @@ class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase
protected function getTestCompositeTable($name) protected function getTestCompositeTable($name)
{ {
$table = new Table($name, [], [], [], false, []); $table = new Table($name, [], [], [], [], false, []);
$table->setSchemaConfig($this->schemaManager->createSchemaConfig()); $table->setSchemaConfig($this->schemaManager->createSchemaConfig());
$table->addColumn('id', 'integer', ['notnull' => true]); $table->addColumn('id', 'integer', ['notnull' => true]);
$table->addColumn('other_id', 'integer', ['notnull' => true]); $table->addColumn('other_id', 'integer', ['notnull' => true]);
...@@ -999,14 +999,17 @@ class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase ...@@ -999,14 +999,17 @@ class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase
protected function assertHasTable($tables, $tableName) protected function assertHasTable($tables, $tableName)
{ {
$foundTable = false; $foundTable = false;
foreach ($tables as $table) { foreach ($tables as $table) {
self::assertInstanceOf(Table::class, $table, 'No Table instance was found in tables array.'); self::assertInstanceOf(Table::class, $table, 'No Table instance was found in tables array.');
if (strtolower($table->getName()) !== 'list_tables_test_new_name') { if (strtolower($table->getName()) !== 'list_tables_test_new_name') {
continue; continue;
} }
$foundTable = true; $foundTable = true;
} }
self::assertTrue($foundTable, 'Could not find new table'); self::assertTrue($foundTable, 'Could not find new table');
} }
......
...@@ -1272,6 +1272,7 @@ class ComparatorTest extends TestCase ...@@ -1272,6 +1272,7 @@ class ComparatorTest extends TestCase
'id_table1' => new Column('id_table1', Type::getType('integer')), 'id_table1' => new Column('id_table1', Type::getType('integer')),
], ],
[], [],
[],
[ [
new ForeignKeyConstraint(['id_table1'], 'table1', ['id'], 'fk_table2_table1'), new ForeignKeyConstraint(['id_table1'], 'table1', ['id'], 'fk_table2_table1'),
] ]
...@@ -1285,6 +1286,7 @@ class ComparatorTest extends TestCase ...@@ -1285,6 +1286,7 @@ class ComparatorTest extends TestCase
'id_table3' => new Column('id_table3', Type::getType('integer')), 'id_table3' => new Column('id_table3', Type::getType('integer')),
], ],
[], [],
[],
[ [
new ForeignKeyConstraint(['id_table3'], 'table3', ['id'], 'fk_table2_table3'), new ForeignKeyConstraint(['id_table3'], 'table3', ['id'], 'fk_table2_table3'),
] ]
......
...@@ -200,7 +200,7 @@ class TableTest extends DbalTestCase ...@@ -200,7 +200,7 @@ class TableTest extends DbalTestCase
{ {
$constraint = new ForeignKeyConstraint([], 'foo', []); $constraint = new ForeignKeyConstraint([], 'foo', []);
$tableA = new Table('foo', [], [], [$constraint]); $tableA = new Table('foo', [], [], [], [$constraint]);
$constraints = $tableA->getForeignKeys(); $constraints = $tableA->getForeignKeys();
self::assertCount(1, $constraints); self::assertCount(1, $constraints);
...@@ -209,7 +209,7 @@ class TableTest extends DbalTestCase ...@@ -209,7 +209,7 @@ class TableTest extends DbalTestCase
public function testOptions() public function testOptions()
{ {
$table = new Table('foo', [], [], [], false, ['foo' => 'bar']); $table = new Table('foo', [], [], [], [], false, ['foo' => 'bar']);
self::assertTrue($table->hasOption('foo')); self::assertTrue($table->hasOption('foo'));
self::assertEquals('bar', $table->getOption('foo')); self::assertEquals('bar', $table->getOption('foo'));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment