Home | History | Annotate | Download | only in activity_log
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/extensions/activity_log/database_string_table.h"
      6 
      7 #include "base/strings/stringprintf.h"
      8 #include "sql/connection.h"
      9 #include "sql/statement.h"
     10 
     11 using base::StringPrintf;
     12 
     13 namespace extensions {
     14 
     15 DatabaseStringTable::DatabaseStringTable(const std::string& table)
     16     : table_(table) {}
     17 
     18 DatabaseStringTable::~DatabaseStringTable() {}
     19 
     20 bool DatabaseStringTable::Initialize(sql::Connection* connection) {
     21   if (!connection->DoesTableExist(table_.c_str())) {
     22     return connection->Execute(StringPrintf(
     23         "CREATE TABLE %s (id INTEGER PRIMARY KEY, value TEXT NOT NULL); "
     24         "CREATE UNIQUE INDEX %s_index ON %s(value)",
     25         table_.c_str(),
     26         table_.c_str(),
     27         table_.c_str()).c_str());
     28   } else {
     29     return true;
     30   }
     31 }
     32 
     33 bool DatabaseStringTable::StringToInt(sql::Connection* connection,
     34                                       const std::string& value,
     35                                       int64* id) {
     36   std::map<std::string, int64>::const_iterator lookup =
     37       value_to_id_.find(value);
     38   if (lookup != value_to_id_.end()) {
     39     *id = lookup->second;
     40     return true;
     41   }
     42 
     43   // Operate on the assumption that the cache does a good job on
     44   // frequently-used strings--if there is a cache miss, first act on the
     45   // assumption that the string is not in the database either.
     46   sql::Statement update(connection->GetUniqueStatement(
     47       StringPrintf("INSERT OR IGNORE INTO %s(value) VALUES (?)", table_.c_str())
     48           .c_str()));
     49   update.BindString(0, value);
     50   if (!update.Run())
     51     return false;
     52 
     53   if (connection->GetLastChangeCount() == 1) {
     54     *id = connection->GetLastInsertRowId();
     55     id_to_value_[*id] = value;
     56     value_to_id_[value] = *id;
     57     return true;
     58   }
     59 
     60   // The specified string may have already existed in the database, in which
     61   // case the insert above will have been ignored.  If this happens, do a
     62   // lookup to find the old value.
     63   sql::Statement query(connection->GetUniqueStatement(
     64       StringPrintf("SELECT id FROM %s WHERE value = ?", table_.c_str())
     65           .c_str()));
     66   query.BindString(0, value);
     67   if (!query.Step())
     68     return false;
     69   *id = query.ColumnInt64(0);
     70   id_to_value_[*id] = value;
     71   value_to_id_[value] = *id;
     72   return true;
     73 }
     74 
     75 bool DatabaseStringTable::IntToString(sql::Connection* connection,
     76                                       int64 id,
     77                                       std::string* value) {
     78   std::map<int64, std::string>::const_iterator lookup =
     79       id_to_value_.find(id);
     80   if (lookup != id_to_value_.end()) {
     81     *value = lookup->second;
     82     return true;
     83   }
     84 
     85   sql::Statement query(connection->GetUniqueStatement(
     86       StringPrintf("SELECT value FROM %s WHERE id = ?", table_.c_str())
     87           .c_str()));
     88   query.BindInt64(0, id);
     89   if (!query.Step())
     90     return false;
     91 
     92   *value = query.ColumnString(0);
     93   id_to_value_[id] = *value;
     94   value_to_id_[*value] = id;
     95   return true;
     96 }
     97 
     98 void DatabaseStringTable::ClearCache() {
     99   id_to_value_.clear();
    100   value_to_id_.clear();
    101 }
    102 
    103 }  // namespace extensions
    104