| Index: chrome/browser/extensions/activity_log/database_string_table.cc | 
| diff --git a/chrome/browser/extensions/activity_log/database_string_table.cc b/chrome/browser/extensions/activity_log/database_string_table.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..c9e832e70e3854ed204206cdac039242d4c1fd39 | 
| --- /dev/null | 
| +++ b/chrome/browser/extensions/activity_log/database_string_table.cc | 
| @@ -0,0 +1,103 @@ | 
| +// Copyright 2013 The Chromium Authors. All rights reserved. | 
| +// Use of this source code is governed by a BSD-style license that can be | 
| +// found in the LICENSE file. | 
| + | 
| +#include "chrome/browser/extensions/activity_log/database_string_table.h" | 
| + | 
| +#include "base/strings/stringprintf.h" | 
| +#include "sql/connection.h" | 
| +#include "sql/statement.h" | 
| + | 
| +using base::StringPrintf; | 
| + | 
| +namespace extensions { | 
| + | 
| +DatabaseStringTable::DatabaseStringTable(const std::string& table) | 
| +    : table_(table) {} | 
| + | 
| +DatabaseStringTable::~DatabaseStringTable() {} | 
| + | 
| +bool DatabaseStringTable::Initialize(sql::Connection* connection) { | 
| +  if (!connection->DoesTableExist(table_.c_str())) { | 
| +    return connection->Execute(StringPrintf( | 
| +        "CREATE TABLE %s (id INTEGER PRIMARY KEY, value TEXT NOT NULL); " | 
| +        "CREATE UNIQUE INDEX %s_index ON %s(value)", | 
| +        table_.c_str(), | 
| +        table_.c_str(), | 
| +        table_.c_str()).c_str()); | 
| +  } else { | 
| +    return true; | 
| +  } | 
| +} | 
| + | 
| +bool DatabaseStringTable::StringToInt(sql::Connection* connection, | 
| +                                      const std::string& value, | 
| +                                      int64* id) { | 
| +  std::map<std::string, int64>::const_iterator lookup = | 
| +      value_to_id_.find(value); | 
| +  if (lookup != value_to_id_.end()) { | 
| +    *id = lookup->second; | 
| +    return true; | 
| +  } | 
| + | 
| +  // Operate on the assumption that the cache does a good job on | 
| +  // frequently-used strings--if there is a cache miss, first act on the | 
| +  // assumption that the string is not in the database either. | 
| +  sql::Statement update(connection->GetUniqueStatement( | 
| +      StringPrintf("INSERT OR IGNORE INTO %s(value) VALUES (?)", table_.c_str()) | 
| +          .c_str())); | 
| +  update.BindString(0, value); | 
| +  if (!update.Run()) | 
| +    return false; | 
| + | 
| +  if (connection->GetLastChangeCount() == 1) { | 
| +    *id = connection->GetLastInsertRowId(); | 
| +    id_to_value_[*id] = value; | 
| +    value_to_id_[value] = *id; | 
| +    return true; | 
| +  } | 
| + | 
| +  // The specified string may have already existed in the database, in which | 
| +  // case the insert above will have been ignored.  If this happens, do a | 
| +  // lookup to find the old value. | 
| +  sql::Statement query(connection->GetUniqueStatement( | 
| +      StringPrintf("SELECT id FROM %s WHERE value = ?", table_.c_str()) | 
| +          .c_str())); | 
| +  query.BindString(0, value); | 
| +  if (!query.Step()) | 
| +    return false; | 
| +  *id = query.ColumnInt64(0); | 
| +  id_to_value_[*id] = value; | 
| +  value_to_id_[value] = *id; | 
| +  return true; | 
| +} | 
| + | 
| +bool DatabaseStringTable::IntToString(sql::Connection* connection, | 
| +                                      int64 id, | 
| +                                      std::string* value) { | 
| +  std::map<int64, std::string>::const_iterator lookup = | 
| +      id_to_value_.find(id); | 
| +  if (lookup != id_to_value_.end()) { | 
| +    *value = lookup->second; | 
| +    return true; | 
| +  } | 
| + | 
| +  sql::Statement query(connection->GetUniqueStatement( | 
| +      StringPrintf("SELECT value FROM %s WHERE id = ?", table_.c_str()) | 
| +          .c_str())); | 
| +  query.BindInt64(0, id); | 
| +  if (!query.Step()) | 
| +    return false; | 
| + | 
| +  *value = query.ColumnString(0); | 
| +  id_to_value_[id] = *value; | 
| +  value_to_id_[*value] = id; | 
| +  return true; | 
| +} | 
| + | 
| +void DatabaseStringTable::ClearCache() { | 
| +  id_to_value_.clear(); | 
| +  value_to_id_.clear(); | 
| +} | 
| + | 
| +}  // namespace extensions | 
|  |