You are here

function search_api_db_update_7104 in Search API Database Search 7

Use a single full text table per index.

File

./search_api_db.install, line 117

Code

function search_api_db_update_7104() {
  $servers_query = db_select('search_api_server', 's')
    ->condition('s.class', 'search_api_db_service');
  $servers_query
    ->innerJoin('search_api_index', 'i', 'i.server = s.machine_name');
  $servers_query
    ->fields('s', array(
    'options',
  ));
  $servers_query
    ->fields('i', array(
    'server',
    'machine_name',
    'item_type',
  ));
  $servers = $servers_query
    ->execute();
  $server_options = array();
  foreach ($servers as $server) {
    if (!isset($server_options[$server->server])) {
      $server_options[$server->server] = unserialize($server->options);
    }
    $options = $server_options[$server->server];
    list($key, $target) = explode(':', $options['database'], 2);
    if (!empty($options['indexes'][$server->machine_name])) {
      $connection = Database::getConnection($target, $key);
      $schema = $connection
        ->schema();
      $text_table = NULL;

      // Migrate the index's fulltext data.
      foreach ($options['indexes'][$server->machine_name] as $name => $field) {
        if (search_api_is_text_type($field['type'])) {
          $field_name = strlen($name) > 255 ? md5($name) : $name;
          if (!isset($text_table)) {

            // Find a free name for the new table.
            $text_table = _search_api_db_update_find_free_table('search_api_db_' . $server->machine_name . '_text', $connection);

            // To avoid having to look up the index's ID field type, we just
            // rename the first fulltext table we come across and add a
            // "field_name" column.
            $schema
              ->renameTable($field['table'], $text_table);

            // First, set a default for the field for the existing data, then
            // remove it for future inserts.
            $spec = array(
              'description' => "The name of the field in which the token appears, or an MD5 hash of the field.",
              'not null' => TRUE,
              'type' => 'varchar',
              'length' => 255,
              'default' => $field_name,
            );
            $schema
              ->addField($text_table, 'field_name', $spec);
            unset($spec['default']);
            $schema
              ->changeField($text_table, 'field_name', 'field_name', $spec);

            // Finally, replace the primary key and "word" index with new ones.
            $schema
              ->dropIndex($text_table, 'word');
            $schema
              ->dropPrimaryKey($text_table);
            $schema
              ->addIndex($text_table, 'word_field', array(
              array(
                'word',
                20,
              ),
              'field_name',
            ));
            $schema
              ->addPrimaryKey($text_table, array(
              'item_id',
              'field_name',
              'word',
            ));
          }
          else {

            // Move the fulltext data to the new combined fulltext table, then
            // drop the old table.
            $query = $connection
              ->select($field['table'], 't')
              ->fields('t', array(
              'item_id',
              'word',
              'score',
            ));
            $query
              ->addExpression(':field_name', 'field_name', array(
              ':field_name' => $field_name,
            ));
            $connection
              ->insert($text_table)
              ->from($query)
              ->execute();
            $schema
              ->dropTable($field['table']);
          }
          $server_options[$server->server]['indexes'][$server->machine_name][$name]['table'] = $text_table;
        }
      }
    }
  }

  // Save changes to fields.
  foreach ($server_options as $server => $options) {
    db_update('search_api_server')
      ->condition('machine_name', $server)
      ->fields(array(
      'options' => serialize($options),
    ))
      ->execute();
  }
}