| 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..0f10a47a17292d3e5d701cb06257d1d04fa013ec 100644
|
| --- a/chrome/browser/extensions/activity_log/counting_policy.cc
|
| +++ b/chrome/browser/extensions/activity_log/counting_policy.cc
|
| @@ -223,23 +223,35 @@ bool CountingPolicy::FlushDatabase(sql::Connection* db) {
|
| if (!transaction.Begin())
|
| return false;
|
|
|
| + // Adding an Action to the database is a two step process that depends on
|
| + // whether the count on an existing row can be incremented or a new row needs
|
| + // to be inserted.
|
| + // 1. Run the query in locate_str to search for a row which matches and can
|
| + // have the count incremented.
|
| + // 2a. If found, increment the count using update_str and the rowid found in
|
| + // step 1, or
|
| + // 2b. If not found, insert a new row using insert_str.
|
| + std::string locate_str =
|
| + "SELECT rowid FROM " + std::string(kTableName) +
|
| + " WHERE time >= ? AND time < ?";
|
| 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 +327,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 +340,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) {
|
|
|