Chromium Code Reviews| Index: chrome/browser/extensions/activity_log/counting_policy.cc |
| diff --git a/chrome/browser/extensions/activity_log/counting_policy.cc b/chrome/browser/extensions/activity_log/counting_policy.cc |
| index f5998942230d3669874c087ac00aeaf06ca121a5..1c06d00e595304adb089171971532fb7846a16c5 100644 |
| --- a/chrome/browser/extensions/activity_log/counting_policy.cc |
| +++ b/chrome/browser/extensions/activity_log/counting_policy.cc |
| @@ -223,23 +223,27 @@ bool CountingPolicy::FlushDatabase(sql::Connection* db) { |
| if (!transaction.Begin()) |
| return false; |
| + std::string locate_str = |
| + "SELECT rowid FROM " + std::string(kTableName) + |
| + " WHERE time >= ? AND time < ?"; |
|
felt
2013/09/06 20:53:57
by the way, I recently discovered the existence of
mvrable
2013/09/06 21:48:33
I hadn't thought of using BETWEEN (I usually don't
|
| std::string insert_str = |
| "INSERT INTO " + std::string(kTableName) + "(count, time"; |
| std::string update_str = |
| "UPDATE " + std::string(kTableName) + |
| " SET count = count + ?, time = max(?, time)" |
| - " WHERE time >= ? AND time < ?"; |
| + " WHERE rowid = ?"; |
| for (size_t i = 0; i < arraysize(matched_columns); i++) { |
| + locate_str = base::StringPrintf( |
| + "%s AND %s IS ?", locate_str.c_str(), matched_columns[i]); |
| insert_str = |
| base::StringPrintf("%s, %s", insert_str.c_str(), matched_columns[i]); |
| - update_str = base::StringPrintf( |
| - "%s AND %s IS ?", update_str.c_str(), matched_columns[i]); |
| } |
| insert_str += ") VALUES (?, ?"; |
| for (size_t i = 0; i < arraysize(matched_columns); i++) { |
| insert_str += ", ?"; |
| } |
| + locate_str += " ORDER BY time DESC LIMIT 1"; |
| insert_str += ")"; |
| for (ActionQueue::iterator i = queue.begin(); i != queue.end(); ++i) { |
| @@ -315,14 +319,12 @@ bool CountingPolicy::FlushDatabase(sql::Connection* db) { |
| matched_values.push_back(-1); |
| } |
| - // Assume there is an existing row for this action, and try to update the |
| - // count. |
| - sql::Statement update_statement(db->GetCachedStatement( |
| - sql::StatementID(SQL_FROM_HERE), update_str.c_str())); |
| - update_statement.BindInt(0, count); |
| - update_statement.BindInt64(1, action.time().ToInternalValue()); |
| - update_statement.BindInt64(2, day_start.ToInternalValue()); |
| - update_statement.BindInt64(3, next_day.ToInternalValue()); |
| + // Search for a matching row for this action whose count can be |
| + // incremented. |
| + sql::Statement locate_statement(db->GetCachedStatement( |
| + sql::StatementID(SQL_FROM_HERE), locate_str.c_str())); |
| + locate_statement.BindInt64(0, day_start.ToInternalValue()); |
| + locate_statement.BindInt64(1, next_day.ToInternalValue()); |
| for (size_t j = 0; j < matched_values.size(); j++) { |
| // A call to BindNull when matched_values contains -1 is likely not |
| // necessary as parameters default to null before they are explicitly |
| @@ -330,35 +332,39 @@ bool CountingPolicy::FlushDatabase(sql::Connection* db) { |
| // ever comes with some values already bound, we bind all parameters |
| // (even null ones) explicitly. |
| if (matched_values[j] == -1) |
| - update_statement.BindNull(j + 4); |
| + locate_statement.BindNull(j + 2); |
| else |
| - update_statement.BindInt64(j + 4, matched_values[j]); |
| + locate_statement.BindInt64(j + 2, matched_values[j]); |
| } |
| - if (!update_statement.Run()) |
| - return false; |
| - // Check if the update succeeded (was the count of updated rows non-zero)? |
| - // If it failed because no matching row existed, fall back to inserting a |
| - // new record. |
| - if (db->GetLastChangeCount() > 0) { |
| - if (db->GetLastChangeCount() > 1) { |
| - LOG(WARNING) << "Found and updated multiple rows in the activity log " |
| - << "database; counts may be off!"; |
| + if (locate_statement.Step()) { |
| + // A matching row was found. Update the count and time. |
| + int64 rowid = locate_statement.ColumnInt64(0); |
| + sql::Statement update_statement(db->GetCachedStatement( |
| + sql::StatementID(SQL_FROM_HERE), update_str.c_str())); |
| + update_statement.BindInt(0, count); |
| + update_statement.BindInt64(1, action.time().ToInternalValue()); |
| + update_statement.BindInt64(2, rowid); |
| + if (!update_statement.Run()) |
| + return false; |
| + } else if (locate_statement.Succeeded()) { |
| + // No matching row was found, so we need to insert one. |
| + sql::Statement insert_statement(db->GetCachedStatement( |
| + sql::StatementID(SQL_FROM_HERE), insert_str.c_str())); |
| + insert_statement.BindInt(0, count); |
| + insert_statement.BindInt64(1, action.time().ToInternalValue()); |
| + for (size_t j = 0; j < matched_values.size(); j++) { |
| + if (matched_values[j] == -1) |
| + insert_statement.BindNull(j + 2); |
| + else |
| + insert_statement.BindInt64(j + 2, matched_values[j]); |
| } |
| - continue; |
| - } |
| - sql::Statement insert_statement(db->GetCachedStatement( |
| - sql::StatementID(SQL_FROM_HERE), insert_str.c_str())); |
| - insert_statement.BindInt(0, count); |
| - insert_statement.BindInt64(1, action.time().ToInternalValue()); |
| - for (size_t j = 0; j < matched_values.size(); j++) { |
| - if (matched_values[j] == -1) |
| - insert_statement.BindNull(j + 2); |
| - else |
| - insert_statement.BindInt64(j + 2, matched_values[j]); |
| - } |
| - if (!insert_statement.Run()) |
| + if (!insert_statement.Run()) |
| + return false; |
| + } else { |
| + // Database error. |
| return false; |
| + } |
| } |
| if (clean_database) { |