Commit e37fc54d authored by Benoît Burnichon's avatar Benoît Burnichon

Add mysql specific indexes with lengths

parent 88b80bf3
...@@ -1408,7 +1408,9 @@ abstract class AbstractPlatform ...@@ -1408,7 +1408,9 @@ abstract class AbstractPlatform
if ($table instanceof Table) { if ($table instanceof Table) {
$table = $table->getQuotedName($this); $table = $table->getQuotedName($this);
} elseif (! is_string($table)) { }
if (! is_string($table)) {
throw new InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); throw new InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.');
} }
...@@ -1784,7 +1786,7 @@ abstract class AbstractPlatform ...@@ -1784,7 +1786,7 @@ abstract class AbstractPlatform
$table = $table->getQuotedName($this); $table = $table->getQuotedName($this);
} }
$name = $index->getQuotedName($this); $name = $index->getQuotedName($this);
$columns = $index->getQuotedColumns($this); $columns = $index->getColumns();
if (count($columns) === 0) { if (count($columns) === 0) {
throw new InvalidArgumentException("Incomplete definition. 'columns' required."); throw new InvalidArgumentException("Incomplete definition. 'columns' required.");
...@@ -1795,7 +1797,7 @@ abstract class AbstractPlatform ...@@ -1795,7 +1797,7 @@ abstract class AbstractPlatform
} }
$query = 'CREATE ' . $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name . ' ON ' . $table; $query = 'CREATE ' . $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name . ' ON ' . $table;
$query .= ' (' . $this->getIndexFieldDeclarationListSQL($columns) . ')' . $this->getPartialIndexSQL($index); $query .= ' (' . $this->getIndexFieldDeclarationListSQL($index) . ')' . $this->getPartialIndexSQL($index);
return $query; return $query;
} }
...@@ -1833,7 +1835,7 @@ abstract class AbstractPlatform ...@@ -1833,7 +1835,7 @@ abstract class AbstractPlatform
*/ */
public function getCreatePrimaryKeySQL(Index $index, $table) public function getCreatePrimaryKeySQL(Index $index, $table)
{ {
return 'ALTER TABLE ' . $table . ' ADD PRIMARY KEY (' . $this->getIndexFieldDeclarationListSQL($index->getQuotedColumns($this)) . ')'; return 'ALTER TABLE ' . $table . ' ADD PRIMARY KEY (' . $this->getIndexFieldDeclarationListSQL($index) . ')';
} }
/** /**
...@@ -2337,7 +2339,7 @@ abstract class AbstractPlatform ...@@ -2337,7 +2339,7 @@ abstract class AbstractPlatform
*/ */
public function getUniqueConstraintDeclarationSQL($name, Index $index) public function getUniqueConstraintDeclarationSQL($name, Index $index)
{ {
$columns = $index->getQuotedColumns($this); $columns = $index->getColumns();
$name = new Identifier($name); $name = new Identifier($name);
if (count($columns) === 0) { if (count($columns) === 0) {
...@@ -2345,7 +2347,7 @@ abstract class AbstractPlatform ...@@ -2345,7 +2347,7 @@ abstract class AbstractPlatform
} }
return 'CONSTRAINT ' . $name->getQuotedName($this) . ' UNIQUE (' return 'CONSTRAINT ' . $name->getQuotedName($this) . ' UNIQUE ('
. $this->getIndexFieldDeclarationListSQL($columns) . $this->getIndexFieldDeclarationListSQL($index)
. ')' . $this->getPartialIndexSQL($index); . ')' . $this->getPartialIndexSQL($index);
} }
...@@ -2362,7 +2364,7 @@ abstract class AbstractPlatform ...@@ -2362,7 +2364,7 @@ abstract class AbstractPlatform
*/ */
public function getIndexDeclarationSQL($name, Index $index) public function getIndexDeclarationSQL($name, Index $index)
{ {
$columns = $index->getQuotedColumns($this); $columns = $index->getColumns();
$name = new Identifier($name); $name = new Identifier($name);
if (count($columns) === 0) { if (count($columns) === 0) {
...@@ -2370,7 +2372,7 @@ abstract class AbstractPlatform ...@@ -2370,7 +2372,7 @@ abstract class AbstractPlatform
} }
return $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name->getQuotedName($this) . ' (' return $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name->getQuotedName($this) . ' ('
. $this->getIndexFieldDeclarationListSQL($columns) . $this->getIndexFieldDeclarationListSQL($index)
. ')' . $this->getPartialIndexSQL($index); . ')' . $this->getPartialIndexSQL($index);
} }
...@@ -2392,17 +2394,23 @@ abstract class AbstractPlatform ...@@ -2392,17 +2394,23 @@ abstract class AbstractPlatform
* Obtains DBMS specific SQL code portion needed to set an index * Obtains DBMS specific SQL code portion needed to set an index
* declaration to be used in statements like CREATE TABLE. * declaration to be used in statements like CREATE TABLE.
* *
* @param mixed[][] $fields * @param mixed[]|Index $columnsOrIndex array declaration is deprecated, prefer passing Index to this method
*
* @return string
*/ */
public function getIndexFieldDeclarationListSQL(array $fields) public function getIndexFieldDeclarationListSQL($columnsOrIndex) : string
{ {
if ($columnsOrIndex instanceof Index) {
return implode(', ', $columnsOrIndex->getQuotedColumns($this));
}
if (! is_array($columnsOrIndex)) {
throw new InvalidArgumentException('Fields argument should be an Index or array.');
}
$ret = []; $ret = [];
foreach ($fields as $field => $definition) { foreach ($columnsOrIndex as $column => $definition) {
if (is_array($definition)) { if (is_array($definition)) {
$ret[] = $field; $ret[] = $column;
} else { } else {
$ret[] = $definition; $ret[] = $definition;
} }
...@@ -3073,6 +3081,14 @@ abstract class AbstractPlatform ...@@ -3073,6 +3081,14 @@ abstract class AbstractPlatform
return false; return false;
} }
/**
* Whether the platform supports indexes with column length definitions.
*/
public function supportsColumnLengthIndexes() : bool
{
return false;
}
/** /**
* Whether the platform supports altering tables. * Whether the platform supports altering tables.
* *
......
...@@ -645,7 +645,7 @@ class MySqlPlatform extends AbstractPlatform ...@@ -645,7 +645,7 @@ class MySqlPlatform extends AbstractPlatform
$query = 'ALTER TABLE ' . $table . ' DROP INDEX ' . $remIndex->getName() . ', '; $query = 'ALTER TABLE ' . $table . ' DROP INDEX ' . $remIndex->getName() . ', ';
$query .= 'ADD ' . $indexClause; $query .= 'ADD ' . $indexClause;
$query .= ' (' . $this->getIndexFieldDeclarationListSQL($addIndex->getQuotedColumns($this)) . ')'; $query .= ' (' . $this->getIndexFieldDeclarationListSQL($addIndex) . ')';
$sql[] = $query; $sql[] = $query;
...@@ -1132,4 +1132,12 @@ class MySqlPlatform extends AbstractPlatform ...@@ -1132,4 +1132,12 @@ class MySqlPlatform extends AbstractPlatform
{ {
return TransactionIsolationLevel::REPEATABLE_READ; return TransactionIsolationLevel::REPEATABLE_READ;
} }
/**
* {@inheritdoc}
*/
public function supportsColumnLengthIndexes() : bool
{
return true;
}
} }
...@@ -320,7 +320,7 @@ SQL ...@@ -320,7 +320,7 @@ SQL
$flags = ' NONCLUSTERED'; $flags = ' NONCLUSTERED';
} }
return 'ALTER TABLE ' . $table . ' ADD PRIMARY KEY' . $flags . ' (' . $this->getIndexFieldDeclarationListSQL($index->getQuotedColumns($this)) . ')'; return 'ALTER TABLE ' . $table . ' ADD PRIMARY KEY' . $flags . ' (' . $this->getIndexFieldDeclarationListSQL($index) . ')';
} }
/** /**
......
...@@ -843,17 +843,26 @@ abstract class AbstractSchemaManager ...@@ -843,17 +843,26 @@ abstract class AbstractSchemaManager
$keyName = strtolower($keyName); $keyName = strtolower($keyName);
if (! isset($result[$keyName])) { if (! isset($result[$keyName])) {
$options = [
'lengths' => [],
];
if (isset($tableIndex['where'])) {
$options['where'] = $tableIndex['where'];
}
$result[$keyName] = [ $result[$keyName] = [
'name' => $indexName, 'name' => $indexName,
'columns' => [$tableIndex['column_name']], 'columns' => [],
'unique' => $tableIndex['non_unique'] ? false : true, 'unique' => $tableIndex['non_unique'] ? false : true,
'primary' => $tableIndex['primary'], 'primary' => $tableIndex['primary'],
'flags' => $tableIndex['flags'] ?? [], 'flags' => $tableIndex['flags'] ?? [],
'options' => isset($tableIndex['where']) ? ['where' => $tableIndex['where']] : [], 'options' => $options,
]; ];
} else {
$result[$keyName]['columns'][] = $tableIndex['column_name'];
} }
$result[$keyName]['columns'][] = $tableIndex['column_name'];
$result[$keyName]['options']['lengths'][] = $tableIndex['length'] ?? null;
} }
$eventManager = $this->_platform->getEventManager(); $eventManager = $this->_platform->getEventManager();
......
...@@ -7,6 +7,7 @@ use InvalidArgumentException; ...@@ -7,6 +7,7 @@ use InvalidArgumentException;
use function array_keys; use function array_keys;
use function array_map; use function array_map;
use function array_search; use function array_search;
use function array_shift;
use function count; use function count;
use function is_string; use function is_string;
use function strtolower; use function strtolower;
...@@ -97,10 +98,21 @@ class Index extends AbstractAsset implements Constraint ...@@ -97,10 +98,21 @@ class Index extends AbstractAsset implements Constraint
*/ */
public function getQuotedColumns(AbstractPlatform $platform) public function getQuotedColumns(AbstractPlatform $platform)
{ {
$subParts = $platform->supportsColumnLengthIndexes() && $this->hasOption('lengths')
? $this->getOption('lengths') : [];
$columns = []; $columns = [];
foreach ($this->_columns as $column) { foreach ($this->_columns as $column) {
$columns[] = $column->getQuotedName($platform); $length = array_shift($subParts);
$quotedColumn = $column->getQuotedName($platform);
if ($length !== null) {
$quotedColumn .= '(' . $length . ')';
}
$columns[] = $quotedColumn;
} }
return $columns; return $columns;
......
...@@ -67,6 +67,8 @@ class MySqlSchemaManager extends AbstractSchemaManager ...@@ -67,6 +67,8 @@ class MySqlSchemaManager extends AbstractSchemaManager
} elseif (strpos($v['index_type'], 'SPATIAL') !== false) { } elseif (strpos($v['index_type'], 'SPATIAL') !== false) {
$v['flags'] = ['SPATIAL']; $v['flags'] = ['SPATIAL'];
} }
$v['length'] = $v['sub_part'] ?? null;
$tableIndexes[$k] = $v; $tableIndexes[$k] = $v;
} }
......
...@@ -1555,4 +1555,24 @@ class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase ...@@ -1555,4 +1555,24 @@ class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase
$this->assertGreaterThan($lastUsedIdBeforeDelete, $lastUsedIdAfterDelete); $this->assertGreaterThan($lastUsedIdBeforeDelete, $lastUsedIdAfterDelete);
} }
public function testGenerateAnIndexWithPartialColumnLength() : void
{
if (! $this->schemaManager->getDatabasePlatform()->supportsColumnLengthIndexes()) {
self::markTestSkipped('This test is only supported on platforms that support indexes with column length definitions.');
}
$table = new Table('test_partial_column_index');
$table->addColumn('long_column', 'string', ['length' => 40]);
$table->addColumn('standard_column', 'integer');
$table->addIndex(['long_column'], 'partial_long_column_idx', [], ['lengths' => [4]]);
$table->addIndex(['standard_column', 'long_column'], 'standard_and_partial_idx', [], ['lengths' => [null, 2]]);
$expected = $table->getIndexes();
$this->schemaManager->dropAndCreateTable($table);
$onlineTable = $this->schemaManager->listTableDetails('test_partial_column_index');
self::assertEquals($expected, $onlineTable->getIndexes());
}
} }
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