You are here

function privatemsg_update_6202 in Privatemsg 6.2

Remove duplicate entries in {pm_index}.

File

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

Code

function privatemsg_update_6202(&$sandbox) {

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

    // If privatemsg_filter is enabled, check if the updates that add the Inbox
    // tag did already run to make it possible to tag messages users sent to
    // themself.
    // We cannot detect if privatemsg_filter_update_6004 has been run, so we
    // assume that 6004 has been run if 6003 has been.
    if (module_exists('privatemsg_filter') && (!($tag_id = variable_get('privatemsg_filter_inbox_tag', '')) || !db_result(db_query('SELECT 1 FROM {pm_tags} WHERE tag_id = %d', $tag_id)))) {
      drupal_set_message(t('Some updates are still pending. Please return to <a href="@update-php">update.php</a> and run the remaining updates.', array(
        '@update-php' => base_path() . 'update.php?op=selection',
      )), 'error', FALSE);
      $ret['#abort'] = array(
        'success' => FALSE,
        'query' => t('Some updates are still pending.<br/>Please re-run the update script.'),
      );
      return $ret;
    }
    $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_result(db_query('SELECT MAX(thread_id) FROM {pm_index}'));
  }

  // Fetch the 10 next thread_ids.
  $result = db_query_range('SELECT DISTINCT thread_id FROM {pm_index} WHERE thread_id > %d ORDER BY thread_id ASC', $sandbox['current_thread_id'], 0, 20);
  $threads = array();
  while ($row = db_fetch_object($result)) {
    $threads[] = $row->thread_id;
  }
  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 (' . db_placeholders($threads) . ') GROUP BY pmi.recipient, pmi.type, pmi.mid, pmi.thread_id HAVING COUNT(*) > 1';
    $result = db_query($sql, $threads);
    while ($row = db_fetch_object($result)) {

      // Delete all occurences of these entries.
      db_query("DELETE FROM {pm_index} WHERE mid = %d AND recipient = %d AND type = '%s'", $row->mid, $row->recipient, $row->type);

      // Re-insert a single entry. We do this to explicitely keep messages
      // unread and undeleted if there are conflicting entries.
      db_query('INSERT INTO {pm_index} (mid, thread_id, recipient, type, is_new, deleted) VALUES (%d, %d, %d, "%s", %d, %d)', $row->mid, $row->thread_id, $row->recipient, $row->type, $row->is_new, $row->deleted);
    }
    $sandbox['current_thread_id'] = max($threads);
  }

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