You are here

protected function SearchApiDbService::createFieldTable in Search API Database Search 7

Creates or modifies a table to add an indexed field.

Used as a helper method in fieldsUpdated().

Parameters

SearchApiIndex $index: Search API index for this field.

array $field: Single field definition from SearchApiIndex::getFields().

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".
1 call to SearchApiDbService::createFieldTable()
SearchApiDbService::fieldsUpdated in ./service.inc
Overrides SearchApiAbstractService::fieldsUpdated().

File

./service.inc, line 391
Contains SearchApiDbService.

Class

SearchApiDbService
Indexes and searches items using the database.

Code

protected function createFieldTable(SearchApiIndex $index, $field, &$db) {
  $type = search_api_extract_inner_type($field['type']);
  $new_table = !$this->connection
    ->schema()
    ->tableExists($db['table']);
  if ($new_table) {
    $table = array(
      'name' => $db['table'],
      'module' => 'search_api_db',
      'fields' => array(
        'item_id' => array(
          'description' => 'The primary identifier of the item.',
          'not null' => TRUE,
        ),
      ),
    );

    // The type of the item_id field depends on the ID field's type.
    $id_field = $index
      ->datasource()
      ->getIdFieldInfo();
    $table['fields']['item_id'] += $this
      ->sqlType($id_field['type'] == 'text' ? 'string' : $id_field['type']);
    if (isset($table['fields']['item_id']['length'])) {

      // A length of 255 is overkill for IDs. 50 should be more than enough.
      $table['fields']['item_id']['length'] = 50;
    }
    $this->connection
      ->schema()
      ->createTable($db['table'], $table);

    // Some DBMSs will need a character encoding and collation set.
    switch ($this->connection
      ->databaseType()) {
      case 'mysql':
        $this->connection
          ->query("ALTER TABLE {{$db['table']}} CONVERT TO CHARACTER SET 'utf8' COLLATE 'utf8_bin'");
        break;

      // @todo Add fixes for other DBMSs.
      case 'oracle':
      case 'pgsql':
      case 'sqlite':
      case 'sqlsrv':
        break;
    }
  }
  if (!isset($db['column'])) {
    $db['column'] = 'value';
  }
  $db_field = $this
    ->sqlType($type);
  $db_field += array(
    'description' => "The field's value for this item.",
  );
  if ($new_table && search_api_is_list_type($field['type'])) {
    $db_field['not null'] = TRUE;
  }
  $this->connection
    ->schema()
    ->addField($db['table'], $db['column'], $db_field);
  try {
    if ($db_field['type'] === 'varchar') {
      $this->connection
        ->schema()
        ->addIndex($db['table'], $db['column'], array(
        array(
          $db['column'],
          10,
        ),
      ));
    }
    else {
      $this->connection
        ->schema()
        ->addIndex($db['table'], $db['column'], array(
        $db['column'],
      ));
    }
  } catch (PDOException $e) {
    $variables['%field'] = $field['name'];
    $variables['%index'] = $index->name;
    watchdog_exception('search_api_db', $e, '%type while trying to add DBMS index for the column of field %field on index %index: !message in %function (line %line of %file).', $variables, WATCHDOG_WARNING);
  }
  if ($new_table) {
    if (search_api_is_list_type($field['type'])) {

      // Add a covering index for lists.
      $this->connection
        ->schema()
        ->addPrimaryKey($db['table'], array(
        'item_id',
        $db['column'],
      ));
    }
    else {

      // Otherwise, a denormalized table with many columns, where we can't
      // predict the best covering index.
      $this->connection
        ->schema()
        ->addPrimaryKey($db['table'], array(
        'item_id',
      ));
    }
  }
}