Revert "Issue #1148856 by drunken monkey, stefan.r, bzrudi71, xatoo, Ben Coleman, jyotisankar, daffie, mondrake, andypost, Damien Tournoud, alexpott: Postgres schema doesn't support keylength on a unique index"

This reverts commit 5074bef03d.
merge-requests/3234/head
Lee Rowlands 2023-04-01 06:32:31 +10:00
parent 60af95fd8e
commit df52d5c823
No known key found for this signature in database
GPG Key ID: 2B829A3DF9204DC4
3 changed files with 4 additions and 148 deletions

View File

@ -340,9 +340,6 @@ use Drupal\Core\Database\Query\SelectInterface;
*
* A key column specifier is either a string naming a column or an array of two
* elements, column name and length, specifying a prefix of the named column.
* Note that some DBMS drivers may opt to ignore the prefix length configuration
* and still use the whole field value for the key. Code should therefore not
* rely on this functionality.
*
* As an example, this is the schema definition for the 'users_data' table. It
* shows five fields ('uid', 'module', 'name', 'value', and 'serialized'), the

View File

@ -286,11 +286,7 @@ EOD;
}
if (isset($table['unique keys']) && is_array($table['unique keys'])) {
foreach ($table['unique keys'] as $key_name => $key) {
// Use the createPrimaryKeySql(), which already discards any prefix
// lengths passed as part of the key column specifiers. (Postgres
// doesn't support setting a prefix length for PRIMARY or UNIQUE
// indices.)
$sql_keys[] = 'CONSTRAINT ' . $this->ensureIdentifiersLength($name, $key_name, 'key') . ' UNIQUE (' . $this->createPrimaryKeySql($key) . ')';
$sql_keys[] = 'CONSTRAINT ' . $this->ensureIdentifiersLength($name, $key_name, 'key') . ' UNIQUE (' . implode(', ', $key) . ')';
}
}
@ -475,7 +471,7 @@ EOD;
}
/**
* Create the SQL expression for primary and unique keys.
* Create the SQL expression for primary keys.
*
* Postgresql does not support key length. It does support fillfactor, but
* that requires a separate database lookup for each column in the key. The
@ -798,10 +794,8 @@ EOD;
throw new SchemaObjectExistsException("Cannot add unique key '$name' to table '$table': unique key already exists.");
}
// Use the createPrimaryKeySql(), which already discards any prefix lengths
// passed as part of the key column specifiers. (Postgres doesn't support
// setting a prefix length for PRIMARY or UNIQUE indices.)
$this->connection->query('ALTER TABLE {' . $table . '} ADD CONSTRAINT ' . $this->ensureIdentifiersLength($table, $name, 'key') . ' UNIQUE (' . $this->createPrimaryKeySql($fields) . ')');
$fields = array_map([$this->connection, 'escapeField'], $fields);
$this->connection->query('ALTER TABLE {' . $table . '} ADD CONSTRAINT ' . $this->ensureIdentifiersLength($table, $name, 'key') . ' UNIQUE (' . implode(',', $fields) . ')');
$this->resetTableInformation($table);
}

View File

@ -1,135 +0,0 @@
<?php
namespace Drupal\KernelTests\Core\Database;
use Drupal\Core\Database\DatabaseException;
/**
* Tests adding UNIQUE keys to tables.
*
* @coversDefaultClass \Drupal\Core\Database\Schema
*
* @group Database
*/
class SchemaUniquePrefixedKeysIndexTest extends DatabaseTestBase {
/**
* Tests UNIQUE keys put directly on the table definition.
*
* @covers ::createTable
*/
public function testCreateTable(): void {
$this->connection->schema()->createTable('test_unique', [
'fields' => [
'field' => [
'type' => 'varchar',
'length' => 50,
],
],
'unique keys' => [
'field' => [['field', 10]],
],
]);
$this->checkUniqueConstraintException('test_unique', 'field');
}
/**
* Tests adding a UNIQUE key to an existing table.
*
* @covers ::addUniqueKey
*/
public function testAddUniqueKey(): void {
$this->connection->schema()
->addUniqueKey('test_people', 'job', [['job', 10]]);
$this->checkUniqueConstraintException('test_people', 'job');
}
/**
* Tests adding a new field with UNIQUE key.
*
* @covers ::addField
*/
public function testAddField(): void {
$field_spec = [
'type' => 'varchar',
'length' => 50,
];
$keys_spec = [
'unique keys' => [
'field' => [['field', 10]],
],
];
$this->connection->schema()
->addField('test', 'field', $field_spec, $keys_spec);
$this->checkUniqueConstraintException('test', 'field');
}
/**
* Tests changing a field to add a UNIQUE key.
*
* @covers ::changeField
*/
public function testChangeField(): void {
$field_spec = [
'description' => "The person's job",
'type' => 'varchar_ascii',
'length' => 50,
'not null' => TRUE,
'default' => '',
];
$keys_spec = [
'unique keys' => [
'job' => [['job', 10]],
],
];
$this->connection->schema()
->changeField('test_people', 'job', 'job', $field_spec, $keys_spec);
$this->checkUniqueConstraintException('test_people', 'job');
}
/**
* Verifies that inserting the same value/prefix twice causes an exception.
*
* @param string $table
* The table to insert into.
* @param string $column
* The column on that table that has a UNIQUE index. If prefix lengths are
* accepted for UNIQUE keys on the current database, the prefix length for
* the field is expected to be set to 10 characters.
*/
protected function checkUniqueConstraintException(string $table, string $column): void {
$this->connection->insert($table)
->fields([
$column => '1234567890 foo',
])
->execute();
$this->expectException(DatabaseException::class);
$value = '1234567890 ' . ($this->supportsPrefixLength() ? 'bar' : 'foo');
$this->connection->insert($table)
->fields([
$column => $value,
])
->execute();
}
/**
* Determines whether the current database supports prefix lengths for keys.
*
* The basic syntax of passing an array (field, prefix length) as a key column
* specifier must always be accepted by the driver. However, due to technical
* limitations, some drivers may choose to ignore them.
*
* @return bool
* TRUE if the current database (driver) will conform to the prefix length
* specified as part of a key column specifier, FALSE if it will be ignored.
*/
protected function supportsPrefixLength(): bool {
return $this->connection->driver() === 'mysql';
}
}