diff --git a/include/dba.php b/include/dba.php index 3f4d814821..f695902afe 100644 --- a/include/dba.php +++ b/include/dba.php @@ -756,15 +756,77 @@ class dba { /** * @brief Updates rows * + * Updates rows in the database. When $old_fields is set to an array, + * the system will only do an update if the fields in that array changed. + * + * Attention: + * Only the values in $old_fields are compared. + * This is an intentional behaviour. + * + * Example: + * We include the timestamp field in $fields but not in $old_fields. + * Then the row will only get the new timestamp when the other fields had changed. + * + * When $old_fields is set to a boolean value the system will do this compare itself. + * When $old_fields is set to "true" the system will do an insert if the row doesn't exists. + * + * Attention: + * Only set $old_fields to a boolean value when you are sure that you will update a single row. + * When you set $old_fields to "true" then $fields must contain all relevant fields! + * * @param string $table Table name * @param array $fields contains the fields that are updated * @param array $condition condition array with the key values + * @param array|boolean $old_fields array with the old field values that are about to be replaced * * @return boolean was the update successfull? */ - static public function update($table, $fields, $condition) { + static public function update($table, $fields, $condition, $old_fields = array()) { - $sql = "UPDATE `".self::$dbo->escape($table)."` SET `". + /** @todo We may use MySQL specific functions here: + * INSERT INTO `config` (`cat`, `k`, `v`) VALUES ('%s', '%s', '%s') ON DUPLICATE KEY UPDATE `v` = '%s'" + * But I think that it doesn't make sense here. + */ + + $table = self::$dbo->escape($table); + + if (is_bool($old_fields)) { + $sql = "SELECT * FROM `".$table."` WHERE `". + implode("` = ? AND `", array_keys($condition))."` = ? LIMIT 1"; + + $params = array(); + foreach ($condition AS $value) { + $params[] = $value; + } + + $do_insert = $old_fields; + + $old_fields = self::fetch_first($sql, $params); + if (is_bool($old_fields)) { + if ($do_insert) { + return self::insert($table, $fields); + } + $old_fields = array(); + } + } + + $do_update = (count($old_fields) == 0); + + foreach ($old_fields AS $fieldname => $content) { + if (isset($fields[$fieldname])) { + if ($fields[$fieldname] == $content) { + unset($fields[$fieldname]); + } else { + $do_update = true; + } + } + } + + if (!$do_update OR (count($fields) == 0)) { + return true; + } + + $sql = "UPDATE `".$table."` SET `". implode("` = ?, `", array_keys($fields))."` = ? WHERE `". implode("` = ? AND `", array_keys($condition))."` = ?"; diff --git a/include/items.php b/include/items.php index 9f948485a2..4d2a8ae52d 100644 --- a/include/items.php +++ b/include/items.php @@ -443,18 +443,16 @@ function store_conversation($arr) { $conversation['source'] = $arr['source']; } - $conv = dba::fetch_first("SELECT `protocol` FROM `conversation` WHERE `item-uri` = ?", $conversation['item-uri']); - if (dbm::is_result($conv)) { - if (($conv['protocol'] < $conversation['protocol']) AND ($conv['protocol'] != 0)) { + $old_conv = dba::fetch_first("SELECT `item-uri`, `reply-to-uri`, `conversation-uri`, `conversation-href`, `protocol`, `source` + FROM `conversation` WHERE `item-uri` = ?", $conversation['item-uri']); + if (dbm::is_result($old_conv)) { + if (($old_conv['protocol'] < $conversation['protocol']) AND ($old_conv['protocol'] != 0)) { unset($conversation['protocol']); unset($conversation['source']); } - // Replace the conversation entry when the new one is better - //if ((($conv['protocol'] == 0) OR ($conv['protocol'] >= $conversation['protocol'])) AND ($conversation['protocol'] > 0)) { - if (!dba::update('conversation', $conversation, array('item-uri' => $conversation['item-uri']))) { - logger('Conversation: update for '.$conversation['item-uri'].' from '.$conv['protocol'].' to '.$conversation['protocol'].' failed', LOGGER_DEBUG); - } - //} + if (!dba::update('conversation', $conversation, array('item-uri' => $conversation['item-uri']), $old_conv)) { + logger('Conversation: update for '.$conversation['item-uri'].' from '.$conv['protocol'].' to '.$conversation['protocol'].' failed', LOGGER_DEBUG); + } } else { if (!dba::insert('conversation', $conversation)) { logger('Conversation: insert for '.$conversation['item-uri'].' (protocol '.$conversation['protocol'].') failed', LOGGER_DEBUG);