/** * Writes single cache record into DB. * * @param string $key Cache key name * @param mxied $data Serialized cache data * * @param boolean True on success, False on failure */ private function write_record($key, $data) { if (!$this->db) { return false; } if ($this->type == 'memcache' || $this->type == 'apc') { return $this->add_record($this->ckey($key), $data); } $key_exists = array_key_exists($key, $this->cache_sums); $key = $this->prefix . '.' . $key; // Remove NULL rows (here we don't need to check if the record exist) if ($data == 'N;') { $this->db->query("DELETE FROM " . $this->table . " WHERE user_id = ?" . " AND cache_key = ?", $this->userid, $key); return true; } // update existing cache record if ($key_exists) { $result = $this->db->query("UPDATE " . $this->table . " SET created = " . $this->db->now() . ", expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", data = ?" . " WHERE user_id = ?" . " AND cache_key = ?", $data, $this->userid, $key); } else { // for better performance we allow more records for one key // so, no need to check if record exist (see rcube_cache::read_record()) $result = $this->db->query("INSERT INTO " . $this->table . " (created, expires, user_id, cache_key, data)" . " VALUES (" . $this->db->now() . ", " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", ?, ?, ?)", $this->userid, $key, $data); } return $this->db->affected_rows($result); }
/** * Writes single cache record into DB. * * @param string $key Cache key name * @param mixed $data Serialized cache data * * @param boolean True on success, False on failure */ private function write_record($key, $data) { if (!$this->db) { return false; } // don't attempt to write too big data sets if (strlen($data) > $this->max_packet_size()) { trigger_error("rcube_cache: max_packet_size ({$this->max_packet}) exceeded for key {$key}. Tried to write " . strlen($data) . " bytes", E_USER_WARNING); return false; } if ($this->type == 'memcache' || $this->type == 'apc') { return $this->add_record($this->ckey($key), $data); } $key_exists = array_key_exists($key, $this->cache_sums); $key = $this->prefix . '.' . $key; // Remove NULL rows (here we don't need to check if the record exist) if ($data == 'N;') { $this->db->query("DELETE FROM {$this->table} WHERE `cache_key` = ?", $key); return true; } // update existing cache record if ($key_exists) { $result = $this->db->query("UPDATE {$this->table}" . " SET `created` = " . $this->db->now() . ", `expires` = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", `data` = ?" . " WHERE `cache_key` = ?", $data, $key); } else { // for better performance we allow more records for one key // so, no need to check if record exist (see rcube_cache::read_record()) $result = $this->db->query("INSERT INTO {$this->table}" . " (`created`, `expires`, `cache_key`, `data`)" . " VALUES (" . $this->db->now() . ", " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", ?, ?)", $key, $data); } return $this->db->affected_rows($result); }
/** * Saves the message in cache. * * @param string $mailbox Folder name * @param rcube_message_header $message Message data * @param bool $force Skips message in-cache existance check */ function add_message($mailbox, $message, $force = false) { if (!is_object($message) || empty($message->uid)) { return; } $msg = serialize($this->db->encode(clone $message)); $flags = 0; if (!empty($message->flags)) { foreach ($this->flags as $idx => $flag) { if (!empty($message->flags[$flag])) { $flags += $idx; } } } unset($msg->flags); // update cache record (even if it exists, the update // here will work as select, assume row exist if affected_rows=0) if (!$force) { $res = $this->db->query("UPDATE " . $this->db->table_name('cache_messages') . " SET flags = ?, data = ?, changed = " . $this->db->now() . " WHERE user_id = ?" . " AND mailbox = ?" . " AND uid = ?", $flags, $msg, $this->userid, $mailbox, (int) $message->uid); if ($this->db->affected_rows()) { return; } } // insert new record $this->db->query("INSERT INTO " . $this->db->table_name('cache_messages') . " (user_id, mailbox, uid, flags, changed, data)" . " VALUES (?, ?, ?, ?, " . $this->db->now() . ", ?)", $this->userid, $mailbox, (int) $message->uid, $flags, $msg); }
/** * Deletes given saved search record * * @param int $sid Search ID * * @return boolean True if deleted successfully, false if nothing changed */ function delete_search($sid) { if (!$this->ID) { return false; } $this->db->query("DELETE FROM " . $this->db->table_name('searches') . " WHERE user_id = ?" . " AND search_id = ?", (int) $this->ID, $sid); return $this->db->affected_rows(); }
/** * Remove the given contact records from a certain group * * @param string Group identifier * @param array List of contact identifiers to be removed * @return int Number of deleted group members */ function remove_from_group($group_id, $ids) { if (!is_array($ids)) { $ids = explode(self::SEPARATOR, $ids); } $ids = $this->db->array2list($ids, 'integer'); $sql_result = $this->db->query("DELETE FROM " . $this->db->table_name($this->db_groupmembers) . " WHERE contactgroup_id=?" . " AND contact_id IN ({$ids})", $group_id); return $this->db->affected_rows(); }
/** * Writes single cache record into DB. * * @param string $key Cache key name * @param mixed $data Serialized cache data * * @param boolean True on success, False on failure */ private function write_record($key, $data) { if (!$this->db) { return false; } // don't attempt to write too big data sets if (strlen($data) > $this->max_packet_size()) { trigger_error("rcube_cache: max_packet_size ({$this->max_packet}) exceeded for key {$key}. Tried to write " . strlen($data) . " bytes", E_USER_WARNING); return false; } if ($this->type == 'memcache' || $this->type == 'apc') { $result = $this->add_record($this->ckey($key), $data); // make sure index will be updated if ($result) { if (!array_key_exists($key, $this->cache_sums)) { $this->cache_sums[$key] = true; } $this->load_index(); if (!$this->index_changed && !in_array($key, $this->index)) { $this->index_changed = true; } } return $result; } $db_key = $this->prefix . '.' . $key; // Remove NULL rows (here we don't need to check if the record exist) if ($data == 'N;') { $result = $this->db->query("DELETE FROM {$this->table} WHERE `cache_key` = ?", $db_key); return !$this->db->is_error($result); } $key_exists = array_key_exists($key, $this->cache_sums); $expires = $this->ttl ? $this->db->now($this->ttl) : 'NULL'; if (!$key_exists) { // Try INSERT temporarily ignoring "duplicate key" errors $this->db->set_option('ignore_key_errors', true); $result = $this->db->query("INSERT INTO {$this->table} (`expires`, `cache_key`, `data`)" . " VALUES ({$expires}, ?, ?)", $db_key, $data); $this->db->set_option('ignore_key_errors', false); } // otherwise try UPDATE if (!isset($result) || !($count = $this->db->affected_rows($result))) { $result = $this->db->query("UPDATE {$this->table} SET `expires` = {$expires}, `data` = ?" . " WHERE `cache_key` = ?", $data, $db_key); $count = $this->db->affected_rows($result); } return $count > 0; }
/** * Saves thread data into database */ private function add_thread_row($mailbox, $data, $mbox_data = array(), $exists = false) { $data = array($this->db->encode($data, true), (int) $this->skip_deleted, (int) $mbox_data['UIDVALIDITY'], (int) $mbox_data['UIDNEXT']); $data = implode('@', $data); $expires = $this->ttl ? $this->db->now($this->ttl) : 'NULL'; if ($exists) { $res = $this->db->query("UPDATE {$this->thread_table}" . " SET `data` = ?, `expires` = {$expires}" . " WHERE `user_id` = ?" . " AND `mailbox` = ?", $data, $this->userid, $mailbox); if ($this->db->affected_rows($res)) { return; } } $this->db->set_option('ignore_key_errors', true); $res = $this->db->query("INSERT INTO {$this->thread_table}" . " (`user_id`, `mailbox`, `expires`, `data`)" . " VALUES (?, ?, {$expires}, ?)", $this->userid, $mailbox, $data); // race-condition, insert failed so try update (#1489146) // thanks to ignore_key_errors "duplicate row" errors will be ignored if (!$exists && !$res && !$this->db->is_error($res)) { $this->db->query("UPDATE {$this->thread_table}" . " SET `expires` = {$expires}, `data` = ?" . " WHERE `user_id` = ?" . " AND `mailbox` = ?", $data, $this->userid, $mailbox); } $this->db->set_option('ignore_key_errors', false); }