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

8.0.x
Alex Pott 2014-06-08 21:11:06 -05:00
parent f43fb5918c
commit c63692f769
9 changed files with 142 additions and 58 deletions

View File

@ -1454,6 +1454,14 @@ class ContentEntityDatabaseStorage extends ContentEntityStorageBase implements S
$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);

View File

@ -325,13 +325,6 @@ class ContentEntitySchemaHandler implements EntitySchemaHandlerInterface {
'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 @@ class ContentEntitySchemaHandler implements EntitySchemaHandlerInterface {
);
}
$this->addTableDefaults($schema);
return $schema;
}
@ -370,6 +365,8 @@ class ContentEntitySchemaHandler implements EntitySchemaHandlerInterface {
$schema['indexes'][$this->getEntityIndexName($id_key)] = array($id_key);
$this->addTableDefaults($schema);
return $schema;
}
@ -402,6 +399,8 @@ class ContentEntitySchemaHandler implements EntitySchemaHandlerInterface {
$schema['indexes'][$this->getEntityIndexName($key)] = array($key);
}
$this->addTableDefaults($schema);
return $schema;
}
@ -434,9 +433,26 @@ class ContentEntitySchemaHandler implements EntitySchemaHandlerInterface {
),
);
$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.
*

View File

@ -480,6 +480,7 @@ class FieldDefinition extends ListDataDefinition implements FieldDefinitionInter
// Fill in default values.
$schema += array(
'columns' => array(),
'unique keys' => array(),
'indexes' => array(),
'foreign keys' => array(),
);

View File

@ -69,6 +69,8 @@ interface FieldItemInterface extends ComplexDataInterface {
* 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

View File

@ -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 @@ class UuidItem extends StringItem {
$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;
}
}

View File

@ -456,7 +456,11 @@ class FieldConfig extends ConfigEntityBase implements FieldConfigInterface {
$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())) {

View File

@ -94,6 +94,7 @@ class TestItemTest extends FieldUnitTestBase {
'not null' => FALSE,
),
),
'unique keys' => array(),
'indexes' => array(
'value' => array('value'),
),

View File

@ -291,6 +291,7 @@ class ContentEntityDatabaseStorageTest extends UnitTestCase {
),
),
'primary key' => array('id'),
'unique keys' => array(),
'indexes' => array(),
'foreign keys' => array(),
),
@ -973,6 +974,7 @@ class ContentEntityDatabaseStorageTest extends UnitTestCase {
'not null' => FALSE,
),
),
'unique keys' => array(),
'indexes' => array(),
'foreign keys' => array(),
);

View File

@ -95,13 +95,11 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
/**
* 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 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
* @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,16 +125,6 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
),
),
));
if ($uuid_key) {
$this->setUpStorageDefinition('uuid', array(
'columns' => array(
'value' => array(
'type' => 'varchar',
'length' => 128,
),
),
));
}
// Add a multi-column field.
$this->setUpStorageDefinition('description', array(
'columns' => array(
@ -155,11 +138,51 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
),
),
));
// Add a field with a unique key.
$this->setUpStorageDefinition('uuid', array(
'columns' => array(
'value' => array(
'type' => 'varchar',
'length' => 128,
),
),
'unique keys' => array(
'value' => array('value'),
),
));
// Add a field with a unique key, specified as column name and length.
$this->setUpStorageDefinition('hash', array(
'columns' => array(
'value' => array(
'type' => 'varchar',
'length' => 20,
),
),
'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',
),
'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 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
$this->setUpStorageDefinition('translator', array(
'columns' => array(
'target_id' => array(
'description' => 'The ID of the target entity.',
'type' => 'int',
),
),
@ -260,6 +282,28 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
'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 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
),
),
'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 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
),
),
);
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 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
* @covers ::getTables()
* @covers ::initializeBaseTable()
* @covers ::initializeRevisionTable()
* @covers ::addTableDefaults()
* @covers ::getEntityIndexName()
* @covers ::processRevisionTable()
* @covers ::processIdentifierSchema()
@ -411,6 +441,9 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
)
),
'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 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
'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 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
),
),
'primary key' => array('revision_id'),
'unique keys' => array(),
'indexes' => array(
'entity_test__id' => array('id'),
),
@ -460,6 +491,7 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
* @covers ::getSchema()
* @covers ::getTables()
* @covers ::initializeDataTable()
* @covers ::addTableDefaults()
* @covers ::getEntityIndexName()
* @covers ::processDataTable()
*/
@ -509,6 +541,7 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
)
),
'primary key' => array('id'),
'unique keys' => array(),
'indexes' => array(),
'foreign keys' => array(),
),
@ -527,6 +560,7 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
),
),
'primary key' => array('id', 'langcode'),
'unique keys' => array(),
'indexes' => array(),
'foreign keys' => array(
'entity_test' => array(
@ -549,6 +583,7 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
* @covers ::getSchema()
* @covers ::getTables()
* @covers ::initializeDataTable()
* @covers ::addTableDefaults()
* @covers ::getEntityIndexName()
* @covers ::initializeRevisionDataTable()
* @covers ::processRevisionDataTable()
@ -619,10 +654,10 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
)
),
'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 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
),
),
'primary key' => array('revision_id'),
'unique keys' => array(),
'indexes' => array(
'entity_test__id' => array('id'),
),
@ -678,6 +714,7 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
),
),
'primary key' => array('id', 'langcode'),
'unique keys' => array(),
'indexes' => array(
'entity_test__revision_id' => array('revision_id'),
),
@ -707,6 +744,7 @@ class ContentEntitySchemaHandlerTest extends UnitTestCase {
),
),
'primary key' => array('revision_id', 'langcode'),
'unique keys' => array(),
'indexes' => array(),
'foreign keys' => array(
'entity_test' => array(