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 11using base::StringPrintf; 12 13namespace extensions { 14 15DatabaseStringTable::DatabaseStringTable(const std::string& table) 16 : table_(table) {} 17 18DatabaseStringTable::~DatabaseStringTable() {} 19 20bool 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 33bool 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 75bool 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 98void DatabaseStringTable::ClearCache() { 99 id_to_value_.clear(); 100 value_to_id_.clear(); 101} 102 103} // namespace extensions 104