protected function Database::createFieldTable in Search API 8
Creates or modifies a table to add an indexed field.
Used as a helper method in fieldsUpdated().
Parameters
\Drupal\search_api\Item\FieldInterface|null $field: The field to add. Or NULL if only the initial table with an "item_id" column should be created.
array $db: Associative array containing the following:
- table: The table to use for the field.
- column: (optional) The column to use in that table. Defaults to "value". For creating a separate field table, it must be left empty!
string $type: (optional) The type of table being created. Either "index" (for the denormalized table for an entire index) or "field" (for field-specific tables).
Throws
\Drupal\search_api\SearchApiException Thrown if creating the table failed.
2 calls to Database::createFieldTable()
- Database::addIndex in modules/
search_api_db/ src/ Plugin/ search_api/ backend/ Database.php - Adds a new index to this server.
- Database::fieldsUpdated in modules/
search_api_db/ src/ Plugin/ search_api/ backend/ Database.php - Updates the storage tables when the field configuration changes.
File
- modules/
search_api_db/ src/ Plugin/ search_api/ backend/ Database.php, line 786
Class
- Database
- Indexes and searches items using the database.
Namespace
Drupal\search_api_db\Plugin\search_api\backendCode
protected function createFieldTable(FieldInterface $field = NULL, array $db = [], $type = 'field') {
// @todo Make $field required but nullable (and $db required again) once we
// depend on PHP 7.1+.
$new_table = !$this->database
->schema()
->tableExists($db['table']);
if ($new_table) {
$table = [
'name' => $db['table'],
'module' => 'search_api_db',
'fields' => [
'item_id' => [
'type' => 'varchar',
'length' => 150,
'description' => 'The primary identifier of the item',
'not null' => TRUE,
],
],
];
// For the denormalized index table, add a primary key right away. For
// newly created field tables we first need to add the "value" column.
if ($type === 'index') {
$table['primary key'] = [
'item_id',
];
}
$this->database
->schema()
->createTable($db['table'], $table);
$this->dbmsCompatibility
->alterNewTable($db['table'], $type);
}
// Stop here if we want to create a table with just the 'item_id' column.
if (!isset($field)) {
return;
}
$column = $db['column'] ?? 'value';
$db_field = $this
->sqlType($field
->getType());
$db_field += [
'description' => "The field's value for this item",
];
if ($new_table || $type === 'field') {
$db_field['not null'] = TRUE;
}
$this->database
->schema()
->addField($db['table'], $column, $db_field);
if ($db_field['type'] === 'varchar') {
$index_spec = [
[
$column,
10,
],
];
}
else {
$index_spec = [
$column,
];
}
// Create a table specification skeleton to pass to addIndex().
$table_spec = [
'fields' => [
$column => $db_field,
],
'indexes' => [
$column => $index_spec,
],
];
// This is a quick fix for a core bug, so we can run the tests with SQLite
// until this is fixed.
//
// In SQLite, indexes and tables can't have the same name, which is
// the case for Search API DB. We have following situation:
// - a table named search_api_db_default_index_title
// - a table named search_api_db_default_index
//
// The last table has an index on the title column, which results in an
// index with the same as the first table, which conflicts in SQLite.
//
// The core issue addressing this (https://www.drupal.org/node/1008128) was
// closed as it fixed the PostgreSQL part. The SQLite fix is added in
// https://www.drupal.org/node/2625664
// We prevent this by adding an extra underscore (which is also the proposed
// solution in the original core issue).
//
// @todo: Remove when #2625664 lands in Core. See #2625722 for a patch that
// implements this.
try {
$this->database
->schema()
->addIndex($db['table'], '_' . $column, $index_spec, $table_spec);
} catch (\PDOException $e) {
$variables['%column'] = $column;
$variables['%table'] = $db['table'];
$this
->logException($e, '%type while trying to add a database index for column %column to table %table: @message in %function (line %line of %file).', $variables, RfcLogLevel::WARNING);
} catch (DatabaseException $e) {
$variables['%column'] = $column;
$variables['%table'] = $db['table'];
$this
->logException($e, '%type while trying to add a database index for column %column to table %table: @message in %function (line %line of %file).', $variables, RfcLogLevel::WARNING);
}
// Add a covering index for field tables.
if ($new_table && $type == 'field') {
$this->database
->schema()
->addPrimaryKey($db['table'], [
'item_id',
$column,
]);
}
}