Commit c63692f7 authored by alexpott's avatar alexpott

Issue #2209049 by tstoeckler, lokapujya: Allow field schemas to contain unique keys.

parent f43fb591
......@@ -1454,6 +1454,14 @@ public static function _fieldSqlSchema(FieldConfigInterface $field, array $schem
$current['fields'][$real_name] = $attributes;
}
// Add unique keys.
foreach ($schema['unique keys'] as $unique_key_name => $columns) {
$real_name = static::_fieldIndexName($field, $unique_key_name);
foreach ($columns as $column_name) {
$current['unique keys'][$real_name][] = static::_fieldColumnName($field, $column_name);
}
}
// Add indexes.
foreach ($schema['indexes'] as $index_name => $columns) {
$real_name = static::_fieldIndexName($field, $index_name);
......
......@@ -325,13 +325,6 @@ protected function initializeBaseTable() {
'foreign keys' => array(),
);
if ($this->entityType->hasKey('uuid')) {
$uuid_key = $this->entityType->getKey('uuid');
$schema['unique keys'] = array(
$this->getEntityIndexName($uuid_key) => array($uuid_key),
);
}
if ($this->entityType->hasKey('revision')) {
$revision_key = $this->entityType->getKey('revision');
$key_name = $this->getEntityIndexName($revision_key);
......@@ -342,6 +335,8 @@ protected function initializeBaseTable() {
);
}
$this->addTableDefaults($schema);
return $schema;
}
......@@ -370,6 +365,8 @@ protected function initializeRevisionTable() {
$schema['indexes'][$this->getEntityIndexName($id_key)] = array($id_key);
$this->addTableDefaults($schema);
return $schema;
}
......@@ -402,6 +399,8 @@ protected function initializeDataTable() {
$schema['indexes'][$this->getEntityIndexName($key)] = array($key);
}
$this->addTableDefaults($schema);
return $schema;
}
......@@ -434,9 +433,26 @@ protected function initializeRevisionDataTable() {
),
);
$this->addTableDefaults($schema);
return $schema;
}
/**
* Adds defaults to a table schema definition.
*
* @param $schema
* The schema definition array for a single table, passed by reference.
*/
protected function addTableDefaults(&$schema) {
$schema += array(
'fields' => array(),
'unique keys' => array(),
'indexes' => array(),
'foreign keys' => array(),
);
}
/**
* Processes the gathered schema for a base table.
*
......
......@@ -480,6 +480,7 @@ public function getSchema() {
// Fill in default values.
$schema += array(
'columns' => array(),
'unique keys' => array(),
'indexes' => array(),
'foreign keys' => array(),
);
......
......@@ -69,6 +69,8 @@ public static function mainPropertyName();
* definitions depend on field settings when possible. No assumptions
* should be made on how storage engines internally use the original
* column name to structure their storage.
* - unique keys: (optional) An array of Schema API unique key definitions.
* Only columns that appear in the 'columns' array are allowed.
* - indexes: (optional) An array of Schema API index definitions. Only
* columns that appear in the 'columns' array are allowed. Those indexes
* will be used as default indexes. Callers of field_create_field() can
......
......@@ -7,6 +7,8 @@
namespace Drupal\Core\Field\Plugin\Field\FieldType;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
/**
* Defines the 'uuid' entity field type.
*
......@@ -39,4 +41,14 @@ public function applyDefaultValue($notify = TRUE) {
$this->setValue(array('value' => $uuid->generate()), $notify);
return $this;
}
/**
* {@inheritdoc}
*/
public static function schema(FieldStorageDefinitionInterface $field_definition) {
$schema = parent::schema($field_definition);
$schema['unique keys']['value'] = array('value');
return $schema;
}
}
......@@ -456,7 +456,11 @@ public function getSchema() {
$class = $this->getFieldItemClass();
$schema = $class::schema($this);
// Fill in default values for optional entries.
$schema += array('indexes' => array(), 'foreign keys' => array());
$schema += array(
'unique keys' => array(),
'indexes' => array(),
'foreign keys' => array(),
);
// Check that the schema does not include forbidden column names.
if (array_intersect(array_keys($schema['columns']), static::getReservedColumns())) {
......
......@@ -94,6 +94,7 @@ public function testTestItem() {
'not null' => FALSE,
),
),
'unique keys' => array(),
'indexes' => array(
'value' => array('value'),
),
......
......@@ -291,6 +291,7 @@ public function testGetSchema() {
),
),
'primary key' => array('id'),
'unique keys' => array(),
'indexes' => array(),
'foreign keys' => array(),
),
......@@ -973,6 +974,7 @@ public function testFieldSqlSchemaForEntityWithStringIdentifier() {
'not null' => FALSE,
),
),
'unique keys' => array(),
'indexes' => array(),
'foreign keys' => array(),
);
......
......@@ -95,13 +95,11 @@ public function setUp() {
/**
* Tests the schema for non-revisionable, non-translatable entities.
*
* @param bool $uuid_key
* Whether or not the tested entity type should have a UUID key.
*
* @covers ::__construct()
* @covers ::getSchema()
* @covers ::getTables()
* @covers ::initializeBaseTable()
* @covers ::addTableDefaults()
* @covers ::getEntityIndexName()
* @covers ::addFieldSchema()
* @covers ::getFieldIndexes()
......@@ -111,16 +109,11 @@ public function setUp() {
* @covers ::addDefaultLangcodeSchema()
* @covers ::processBaseTable()
* @covers ::processIdentifierSchema()
*
* @dataProvider providerTestGetSchemaLayoutBase
*/
public function testGetSchemaBase($uuid_key) {
public function testGetSchemaBase() {
$this->entityType = new ContentEntityType(array(
'id' => 'entity_test',
'entity_keys' => array(
'id' => 'id',
'uuid' => $uuid_key ? 'uuid' : NULL,
),
'entity_keys' => array('id' => 'id'),
));
// Add a field with a 'length' constraint.
......@@ -132,7 +125,20 @@ public function testGetSchemaBase($uuid_key) {
),
),
));
if ($uuid_key) {
// Add a multi-column field.
$this->setUpStorageDefinition('description', array(
'columns' => array(
'value' => array(
'type' => 'text',
'description' => 'The text value',
),
'format' => array(
'type' => 'varchar',
'description' => 'The text description',
),
),
));
// Add a field with a unique key.
$this->setUpStorageDefinition('uuid', array(
'columns' => array(
'value' => array(
......@@ -140,26 +146,43 @@ public function testGetSchemaBase($uuid_key) {
'length' => 128,
),
),
'unique keys' => array(
'value' => array('value'),
),
));
}
// Add a multi-column field.
$this->setUpStorageDefinition('description', array(
// Add a field with a unique key, specified as column name and length.
$this->setUpStorageDefinition('hash', array(
'columns' => array(
'value' => array(
'type' => 'text',
'description' => 'The text value',
'type' => 'varchar',
'length' => 20,
),
'format' => array(
),
'unique keys' => array(
'value' => array(array('value', 10)),
),
));
// Add a field with a multi-column unique key.
$this->setUpStorageDefinition('email', array(
'columns' => array(
'username' => array(
'type' => 'varchar',
'description' => 'The text description',
),
'hostname' => array(
'type' => 'varchar',
),
'domain' => array(
'type' => 'varchar',
)
),
'unique keys' => array(
'email' => array('username', 'hostname', array('domain', 3)),
),
));
// Add a field with an index.
$this->setUpStorageDefinition('owner', array(
'columns' => array(
'target_id' => array(
'description' => 'The ID of the target entity.',
'type' => 'int',
),
),
......@@ -171,7 +194,6 @@ public function testGetSchemaBase($uuid_key) {
$this->setUpStorageDefinition('translator', array(
'columns' => array(
'target_id' => array(
'description' => 'The ID of the target entity.',
'type' => 'int',
),
),
......@@ -260,6 +282,28 @@ public function testGetSchemaBase($uuid_key) {
'description' => 'The description field.',
'type' => 'varchar',
),
'uuid' => array(
'description' => 'The uuid field.',
'type' => 'varchar',
'length' => 128,
),
'hash' => array(
'description' => 'The hash field.',
'type' => 'varchar',
'length' => 20,
),
'email__username' => array(
'description' => 'The email field.',
'type' => 'varchar',
),
'email__hostname' => array(
'description' => 'The email field.',
'type' => 'varchar',
),
'email__domain' => array(
'description' => 'The email field.',
'type' => 'varchar',
),
'owner' => array(
'description' => 'The owner field.',
'type' => 'int',
......@@ -301,6 +345,15 @@ public function testGetSchemaBase($uuid_key) {
),
),
'primary key' => array('id'),
'unique keys' => array(
'entity_test_field__uuid__value' => array('uuid'),
'entity_test_field__hash__value' => array(array('hash', 10)),
'entity_test_field__email__email' => array(
'email__username',
'email__hostname',
array('email__domain', 3),
),
),
'indexes' => array(
'entity_test_field__owner__target_id' => array('owner'),
'entity_test_field__translator__target_id' => array(
......@@ -324,35 +377,11 @@ public function testGetSchemaBase($uuid_key) {
),
),
);
if ($uuid_key) {
$expected['entity_test']['fields']['uuid'] = array(
'type' => 'varchar',
'length' => 128,
'description' => 'The uuid field.',
'not null' => TRUE,
);
$expected['entity_test']['unique keys']['entity_test__uuid'] = array('uuid');
}
$actual = $this->schemaHandler->getSchema();
$this->assertEquals($expected, $actual);
}
/**
* Provides data for testGetSchemaLayoutBase().
*
* @return array
* Returns a nested array where each inner array returns a boolean,
* indicating whether or not the tested entity type should include a UUID
* key.
*/
public function providerTestGetSchemaLayoutBase() {
return array(
array(FALSE),
array(TRUE),
);
}
/**
* Tests the schema for revisionable, non-translatable entities.
*
......@@ -361,6 +390,7 @@ public function providerTestGetSchemaLayoutBase() {
* @covers ::getTables()
* @covers ::initializeBaseTable()
* @covers ::initializeRevisionTable()
* @covers ::addTableDefaults()
* @covers ::getEntityIndexName()
* @covers ::processRevisionTable()
* @covers ::processIdentifierSchema()
......@@ -411,6 +441,9 @@ public function testGetSchemaRevisionable() {
)
),
'primary key' => array('id'),
'unique keys' => array(
'entity_test__revision_id' => array('revision_id'),
),
'indexes' => array(),
'foreign keys' => array(
'entity_test__revision' => array(
......@@ -418,9 +451,6 @@ public function testGetSchemaRevisionable() {
'columns' => array('revision_id' => 'revision_id'),
)
),
'unique keys' => array(
'entity_test__revision_id' => array('revision_id'),
),
),
'entity_test_revision' => array(
'description' => 'The revision table for entity_test entities.',
......@@ -436,6 +466,7 @@ public function testGetSchemaRevisionable() {
),
),
'primary key' => array('revision_id'),
'unique keys' => array(),
'indexes' => array(
'entity_test__id' => array('id'),
),
......@@ -460,6 +491,7 @@ public function testGetSchemaRevisionable() {
* @covers ::getSchema()
* @covers ::getTables()
* @covers ::initializeDataTable()
* @covers ::addTableDefaults()
* @covers ::getEntityIndexName()
* @covers ::processDataTable()
*/
......@@ -509,6 +541,7 @@ public function testGetSchemaTranslatable() {
)
),
'primary key' => array('id'),
'unique keys' => array(),
'indexes' => array(),
'foreign keys' => array(),
),
......@@ -527,6 +560,7 @@ public function testGetSchemaTranslatable() {
),
),
'primary key' => array('id', 'langcode'),
'unique keys' => array(),
'indexes' => array(),
'foreign keys' => array(
'entity_test' => array(
......@@ -549,6 +583,7 @@ public function testGetSchemaTranslatable() {
* @covers ::getSchema()
* @covers ::getTables()
* @covers ::initializeDataTable()
* @covers ::addTableDefaults()
* @covers ::getEntityIndexName()
* @covers ::initializeRevisionDataTable()
* @covers ::processRevisionDataTable()
......@@ -619,10 +654,10 @@ public function testGetSchemaRevisionableTranslatable() {
)
),
'primary key' => array('id'),
'indexes' => array(),
'unique keys' => array(
'entity_test__revision_id' => array('revision_id'),
),
'indexes' => array(),
'foreign keys' => array(
'entity_test__revision' => array(
'table' => 'entity_test_revision',
......@@ -649,6 +684,7 @@ public function testGetSchemaRevisionableTranslatable() {
),
),
'primary key' => array('revision_id'),
'unique keys' => array(),
'indexes' => array(
'entity_test__id' => array('id'),
),
......@@ -678,6 +714,7 @@ public function testGetSchemaRevisionableTranslatable() {
),
),
'primary key' => array('id', 'langcode'),
'unique keys' => array(),
'indexes' => array(
'entity_test__revision_id' => array('revision_id'),
),
......@@ -707,6 +744,7 @@ public function testGetSchemaRevisionableTranslatable() {
),
),
'primary key' => array('revision_id', 'langcode'),
'unique keys' => array(),
'indexes' => array(),
'foreign keys' => array(
'entity_test' => array(
......
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