By inserting an error_log() statement in the _privatemsg_get_new_messages(), I saw that the database query (SELECT COUNT(*) FROM {privatemsg} WHERE recipient = %d AND newmsg = 1 AND recipient_del = 0) was being run whether I was logged in or not.

This doesn't make sense. There's no point in doing this query if the user is anonymous/not logged in.

I have written a patch to fix this. I'm sure there's a more "Drupal" way to do this, but I don't know all the ins and outs. This works, and maybe with a cleanup or two we can be on our way to saving privatemsg.module users a TON of unecessary db queries.

ps. Since http://drupal.org/node/166046 was sidelined due to being addressed to an out of date version, and the bug still remains, I'm resubmitting this, targeting the current 5.x-3.0 tree.

CommentFileSizeAuthor
privatemsg.30.logged_in_users_only.patch668 bytesapotek

Comments

apotek’s picture

To make it clearer what the patch does, I'll print out the change here, so people don't have to download the patch and analyse.

Basically the patch changes the _privatemsg_get_new_messages() function so that requests for private messages for uid 0 don't happen (there's no point in getting private messages for a non-logged-in user.

So the code was:

function _privatemsg_get_new_messages($uid = 0) {
  global $user;
  static $cache = array();
  if ($uid == 0) {
    $uid = $user->uid;
  }
  if (!isset($cache[$uid])) {
    $cache[$uid] = (int)db_result(db_query('SELECT COUNT(*) FROM {privatemsg} WHERE recipient = %d AND newmsg = 1 AND recipient_del = 0', $uid));
  }
  return $cache[$uid];
}

And was changed to:

function _privatemsg_get_new_messages($uid = 0) {
  global $user;
  static $cache = array();
  if ($uid == 0) {
    $uid = $user->uid;
  }
  
  /** Running the query to grab private messages for non-logged-in users is 
   * pointless and a performance drain. Only look for private messages for real
   * users.  */
  if ($uid == 0) {
  	return array();
  }
  if (!isset($cache[$uid])) {
    $cache[$uid] = (int)db_result(db_query('SELECT COUNT(*) FROM {privatemsg} WHERE recipient = %d AND newmsg = 1 AND recipient_del = 0', $uid));
  }
  return $cache[$uid];
}
apotek’s picture

Perhaps another approach:

  /** Running the query to grab private messages for non-logged-in users is
   * pointless and a performance drain. Only look for private messages for real
   * users.  */
  if ($uid == 0) {
      $cache[0] = 0;
  }

But I think there's something less clean about that. In some ways what we should be returning is a false for uid 0, but that would break the receiving code since it expects an int.

berdir’s picture

Status: Needs review » Closed (won't fix)

I'm closing old issues since Privatemsg for Drupal 5 is not maintained anymore. I suggest you switch to Drupal 6 if possible, many of the reported issues are probably already resolved there and if not, you're welcome to open a new issue.