Unverified Commit 822d9702 authored by Sergei Morozov's avatar Sergei Morozov Committed by GitHub

Merge pull request #2412 from bburnichon/feature/mysql-indexes-with-length

Add mysql specific indexes with lengths
parents 88b80bf3 e37fc54d
......@@ -1408,7 +1408,9 @@ abstract class AbstractPlatform
if ($table instanceof Table) {
$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.');
}
......@@ -1784,7 +1786,7 @@ abstract class AbstractPlatform
$table = $table->getQuotedName($this);
}
$name = $index->getQuotedName($this);
$columns = $index->getQuotedColumns($this);
$columns = $index->getColumns();
if (count($columns) === 0) {
throw new InvalidArgumentException("Incomplete definition. 'columns' required.");
......@@ -1795,7 +1797,7 @@ abstract class AbstractPlatform
}
$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;
}
......@@ -1833,7 +1835,7 @@ abstract class AbstractPlatform
*/
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
*/
public function getUniqueConstraintDeclarationSQL($name, Index $index)
{
$columns = $index->getQuotedColumns($this);
$columns = $index->getColumns();
$name = new Identifier($name);
if (count($columns) === 0) {
......@@ -2345,7 +2347,7 @@ abstract class AbstractPlatform
}
return 'CONSTRAINT ' . $name->getQuotedName($this) . ' UNIQUE ('
. $this->getIndexFieldDeclarationListSQL($columns)
. $this->getIndexFieldDeclarationListSQL($index)
. ')' . $this->getPartialIndexSQL($index);
}
......@@ -2362,7 +2364,7 @@ abstract class AbstractPlatform
*/
public function getIndexDeclarationSQL($name, Index $index)
{
$columns = $index->getQuotedColumns($this);
$columns = $index->getColumns();
$name = new Identifier($name);
if (count($columns) === 0) {
......@@ -2370,7 +2372,7 @@ abstract class AbstractPlatform
}
return $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name->getQuotedName($this) . ' ('
. $this->getIndexFieldDeclarationListSQL($columns)
. $this->getIndexFieldDeclarationListSQL($index)
. ')' . $this->getPartialIndexSQL($index);
}
......@@ -2392,17 +2394,23 @@ abstract class AbstractPlatform
* Obtains DBMS specific SQL code portion needed to set an index
* declaration to be used in statements like CREATE TABLE.
*
* @param mixed[][] $fields
*
* @return string
* @param mixed[]|Index $columnsOrIndex array declaration is deprecated, prefer passing Index to this method
*/
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 = [];
foreach ($fields as $field => $definition) {
foreach ($columnsOrIndex as $column => $definition) {
if (is_array($definition)) {
$ret[] = $field;
$ret[] = $column;
} else {
$ret[] = $definition;
}
......@@ -3073,6 +3081,14 @@ abstract class AbstractPlatform
return false;
}
/**
* Whether the platform supports indexes with column length definitions.
*/
public function supportsColumnLengthIndexes() : bool
{
return false;
}
/**
* Whether the platform supports altering tables.
*
......
......@@ -645,7 +645,7 @@ class MySqlPlatform extends AbstractPlatform
$query = 'ALTER TABLE ' . $table . ' DROP INDEX ' . $remIndex->getName() . ', ';
$query .= 'ADD ' . $indexClause;
$query .= ' (' . $this->getIndexFieldDeclarationListSQL($addIndex->getQuotedColumns($this)) . ')';
$query .= ' (' . $this->getIndexFieldDeclarationListSQL($addIndex) . ')';
$sql[] = $query;
......@@ -1132,4 +1132,12 @@ class MySqlPlatform extends AbstractPlatform
{
return TransactionIsolationLevel::REPEATABLE_READ;
}
/**
* {@inheritdoc}
*/
public function supportsColumnLengthIndexes() : bool
{
return true;
}
}
......@@ -320,7 +320,7 @@ SQL
$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
$keyName = strtolower($keyName);
if (! isset($result[$keyName])) {
$options = [
'lengths' => [],
];
if (isset($tableIndex['where'])) {
$options['where'] = $tableIndex['where'];
}
$result[$keyName] = [
'name' => $indexName,
'columns' => [$tableIndex['column_name']],
'columns' => [],
'unique' => $tableIndex['non_unique'] ? false : true,
'primary' => $tableIndex['primary'],
'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();
......
......@@ -7,6 +7,7 @@ use InvalidArgumentException;
use function array_keys;
use function array_map;
use function array_search;
use function array_shift;
use function count;
use function is_string;
use function strtolower;
......@@ -97,10 +98,21 @@ class Index extends AbstractAsset implements Constraint
*/
public function getQuotedColumns(AbstractPlatform $platform)
{
$subParts = $platform->supportsColumnLengthIndexes() && $this->hasOption('lengths')
? $this->getOption('lengths') : [];
$columns = [];
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;
......
......@@ -67,6 +67,8 @@ class MySqlSchemaManager extends AbstractSchemaManager
} elseif (strpos($v['index_type'], 'SPATIAL') !== false) {
$v['flags'] = ['SPATIAL'];
}
$v['length'] = $v['sub_part'] ?? null;
$tableIndexes[$k] = $v;
}
......
......@@ -1555,4 +1555,24 @@ class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase
$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