You are here

function privatemsg_update_7004 in Privatemsg 7

Same name and namespace in other branches
  1. 7.2 privatemsg.install \privatemsg_update_7004()

Remove duplicate entries in {pm_index}.

File

./privatemsg.install, line 269
Install file for privatemsg.module

Code

function privatemsg_update_7004(&$sandbox) {

  // If the primary key already exists, this doesn't need to run.
  if (db_index_exists('pm_index', 'PRIMARY')) {
    return;
  }

  // First run, initialize sandbox and check if we are ready to run.
  if (!isset($sandbox['current_thread_id'])) {
    $sandbox['current_thread_id'] = 0;

    // Assume that the thread ids are distributed more or less equally over the
    // whole data set. This allows us to calculate the approximate progress.
    $sandbox['max'] = db_query('SELECT MAX(thread_id) FROM {pm_index}')
      ->fetchField();
  }

  // Fetch the next 10 thread_ids.
  $result = db_query_range('SELECT DISTINCT thread_id FROM {pm_index} WHERE thread_id > :thread_id ORDER BY thread_id ASC', 0, 20, array(
    ':thread_id' => $sandbox['current_thread_id'],
  ));
  $threads = $result
    ->fetchCol();
  if (!empty($threads)) {

    // By limiting this slow query (having condition) on a specific set of
    // threads, this allows us to process the slow having part on a relatively
    // small subset of pm_index that can be selected based on the thread_id
    // index. There might also be cases where is_new and/or deleted are not
    // equal, use MAX(is_new) and MIN(deleted) for these cases.
    $sql = 'SELECT COUNT(*) AS count, pmi.recipient, pmi.type, pmi.mid, pmi.thread_id, MAX(pmi.is_new) As is_new, MIN(pmi.deleted) AS deleted FROM {pm_index} pmi WHERE thread_id IN (:threads) GROUP BY pmi.recipient, pmi.type, pmi.mid, pmi.thread_id HAVING COUNT(*) > 1';
    $result = db_query($sql, array(
      ':threads' => $threads,
    ));
    foreach ($result as $row) {

      // Delete all occurrences of these entries.
      db_delete('pm_index')
        ->condition('mid', $row->mid)
        ->condition('recipient', $row->recipient)
        ->condition('type', $row->type)
        ->execute();

      // Re-insert a single entry. We do this to explicitly keep messages
      // unread and undeleted if there are conflicting entries.
      db_insert('pm_index')
        ->fields(array(
        'mid' => $row->mid,
        'thread_id' => $row->thread_id,
        'recipient' => $row->recipient,
        'type' => $row->type,
        'is_new' => $row->is_new,
        'deleted' => $row->deleted,
      ))
        ->execute();
    }
    $sandbox['current_thread_id'] = max($threads);
  }

  // Set #finished based on sandbox.
  $sandbox['#finished'] = empty($sandbox['max']) ? 1 : $sandbox['current_thread_id'] / $sandbox['max'];
}