Home | History | Annotate | Download | only in predictors
      1 // Copyright (c) 2012 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/predictors/autocomplete_action_predictor_table.h"
      6 
      7 #include "base/guid.h"
      8 #include "base/logging.h"
      9 #include "base/metrics/histogram.h"
     10 #include "base/strings/stringprintf.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "content/public/browser/browser_thread.h"
     13 #include "sql/statement.h"
     14 
     15 namespace {
     16 
     17 // TODO(shishir): Rename the table for consistency.
     18 const char kAutocompletePredictorTableName[] = "network_action_predictor";
     19 
     20 // The maximum length allowed for strings in the database.
     21 const size_t kMaxDataLength = 2048;
     22 
     23 void BindRowToStatement(
     24     const predictors::AutocompleteActionPredictorTable::Row& row,
     25     sql::Statement* statement) {
     26   DCHECK(base::IsValidGUID(row.id));
     27   statement->BindString(0, row.id);
     28   statement->BindString16(1, row.user_text.substr(0, kMaxDataLength));
     29   statement->BindString(2, row.url.spec().substr(0, kMaxDataLength));
     30   statement->BindInt(3, row.number_of_hits);
     31   statement->BindInt(4, row.number_of_misses);
     32 }
     33 
     34 bool StepAndInitializeRow(
     35     sql::Statement* statement,
     36     predictors::AutocompleteActionPredictorTable::Row* row) {
     37   if (!statement->Step())
     38     return false;
     39 
     40   row->id = statement->ColumnString(0);
     41   row->user_text = statement->ColumnString16(1);
     42   row->url = GURL(statement->ColumnString(2));
     43   row->number_of_hits = statement->ColumnInt(3);
     44   row->number_of_misses = statement->ColumnInt(4);
     45   return true;
     46 }
     47 
     48 }  // namespace
     49 
     50 namespace predictors {
     51 
     52 AutocompleteActionPredictorTable::Row::Row()
     53     : number_of_hits(0),
     54       number_of_misses(0) {
     55 }
     56 
     57 AutocompleteActionPredictorTable::Row::Row(const Row::Id& id,
     58                                            const base::string16& user_text,
     59                                            const GURL& url,
     60                                            int number_of_hits,
     61                                            int number_of_misses)
     62     : id(id),
     63       user_text(user_text),
     64       url(url),
     65       number_of_hits(number_of_hits),
     66       number_of_misses(number_of_misses) {
     67 }
     68 
     69 AutocompleteActionPredictorTable::Row::Row(const Row& row)
     70     : id(row.id),
     71       user_text(row.user_text),
     72       url(row.url),
     73       number_of_hits(row.number_of_hits),
     74       number_of_misses(row.number_of_misses) {
     75 }
     76 
     77 
     78 void AutocompleteActionPredictorTable::GetRow(const Row::Id& id, Row* row) {
     79   CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::DB));
     80   if (CantAccessDatabase())
     81     return;
     82 
     83   sql::Statement statement(DB()->GetCachedStatement(SQL_FROM_HERE,
     84       base::StringPrintf("SELECT * FROM %s WHERE id=?",
     85                          kAutocompletePredictorTableName).c_str()));
     86   statement.BindString(0, id);
     87 
     88   bool success = StepAndInitializeRow(&statement, row);
     89   DCHECK(success) << "Failed to get row " << id << " from "
     90                   << kAutocompletePredictorTableName;
     91 }
     92 
     93 void AutocompleteActionPredictorTable::GetAllRows(Rows* row_buffer) {
     94   CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::DB));
     95   if (CantAccessDatabase())
     96     return;
     97 
     98   row_buffer->clear();
     99 
    100   sql::Statement statement(DB()->GetCachedStatement(SQL_FROM_HERE,
    101       base::StringPrintf(
    102           "SELECT * FROM %s", kAutocompletePredictorTableName).c_str()));
    103   if (!statement.is_valid())
    104     return;
    105 
    106   Row row;
    107   while (StepAndInitializeRow(&statement, &row))
    108     row_buffer->push_back(row);
    109 }
    110 
    111 void AutocompleteActionPredictorTable::AddRow(
    112     const AutocompleteActionPredictorTable::Row& row) {
    113   CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::DB));
    114   if (CantAccessDatabase())
    115     return;
    116 
    117   AddAndUpdateRows(Rows(1, row), Rows());
    118 }
    119 
    120 void AutocompleteActionPredictorTable::UpdateRow(
    121     const AutocompleteActionPredictorTable::Row& row) {
    122   CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::DB));
    123   if (CantAccessDatabase())
    124     return;
    125 
    126   AddAndUpdateRows(Rows(), Rows(1, row));
    127 }
    128 
    129 void AutocompleteActionPredictorTable::AddAndUpdateRows(
    130     const Rows& rows_to_add,
    131     const Rows& rows_to_update) {
    132   CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::DB));
    133   if (CantAccessDatabase())
    134     return;
    135 
    136   if (!DB()->BeginTransaction())
    137     return;
    138   for (Rows::const_iterator it = rows_to_add.begin();
    139        it != rows_to_add.end(); ++it) {
    140     sql::Statement statement(DB()->GetCachedStatement(SQL_FROM_HERE,
    141         base::StringPrintf(
    142             "INSERT INTO %s "
    143             "(id, user_text, url, number_of_hits, number_of_misses) "
    144             "VALUES (?,?,?,?,?)", kAutocompletePredictorTableName).c_str()));
    145     if (!statement.is_valid()) {
    146       DB()->RollbackTransaction();
    147       return;
    148     }
    149 
    150     BindRowToStatement(*it, &statement);
    151     if (!statement.Run()) {
    152       DB()->RollbackTransaction();
    153       return;
    154     }
    155   }
    156   for (Rows::const_iterator it = rows_to_update.begin();
    157        it != rows_to_update.end(); ++it) {
    158     sql::Statement statement(DB()->GetCachedStatement(SQL_FROM_HERE,
    159         base::StringPrintf(
    160             "UPDATE %s "
    161             "SET id=?, user_text=?, url=?, number_of_hits=?, number_of_misses=?"
    162             " WHERE id=?1", kAutocompletePredictorTableName).c_str()));
    163     if (!statement.is_valid()) {
    164       DB()->RollbackTransaction();
    165       return;
    166     }
    167 
    168     BindRowToStatement(*it, &statement);
    169     if (!statement.Run()) {
    170       DB()->RollbackTransaction();
    171       return;
    172     }
    173     DCHECK_GT(DB()->GetLastChangeCount(), 0);
    174   }
    175   DB()->CommitTransaction();
    176 }
    177 
    178 void AutocompleteActionPredictorTable::DeleteRows(
    179     const std::vector<Row::Id>& id_list) {
    180   CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::DB));
    181   if (CantAccessDatabase())
    182     return;
    183 
    184   if (!DB()->BeginTransaction())
    185     return;
    186   for (std::vector<Row::Id>::const_iterator it = id_list.begin();
    187        it != id_list.end(); ++it) {
    188     sql::Statement statement(DB()->GetCachedStatement(SQL_FROM_HERE,
    189         base::StringPrintf(
    190             "DELETE FROM %s WHERE id=?",
    191             kAutocompletePredictorTableName).c_str()));
    192     if (!statement.is_valid()) {
    193       DB()->RollbackTransaction();
    194       return;
    195     }
    196 
    197     statement.BindString(0, *it);
    198     if (!statement.Run()) {
    199       DB()->RollbackTransaction();
    200       return;
    201     }
    202   }
    203   DB()->CommitTransaction();
    204 }
    205 
    206 void AutocompleteActionPredictorTable::DeleteAllRows() {
    207   CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::DB));
    208   if (CantAccessDatabase())
    209     return;
    210 
    211   sql::Statement statement(DB()->GetCachedStatement(SQL_FROM_HERE,
    212       base::StringPrintf("DELETE FROM %s",
    213                          kAutocompletePredictorTableName).c_str()));
    214   if (!statement.is_valid())
    215     return;
    216 
    217   statement.Run();
    218 }
    219 
    220 AutocompleteActionPredictorTable::AutocompleteActionPredictorTable()
    221     : PredictorTableBase() {
    222 }
    223 
    224 AutocompleteActionPredictorTable::~AutocompleteActionPredictorTable() {
    225 }
    226 
    227 void AutocompleteActionPredictorTable::CreateTableIfNonExistent() {
    228   CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::DB));
    229   if (CantAccessDatabase())
    230     return;
    231 
    232   if (DB()->DoesTableExist(kAutocompletePredictorTableName))
    233     return;
    234 
    235   bool success = DB()->Execute(base::StringPrintf(
    236       "CREATE TABLE %s ( "
    237       "id TEXT PRIMARY KEY, "
    238       "user_text TEXT, "
    239       "url TEXT, "
    240       "number_of_hits INTEGER, "
    241       "number_of_misses INTEGER)", kAutocompletePredictorTableName).c_str());
    242   if (!success)
    243     ResetDB();
    244 }
    245 
    246 void AutocompleteActionPredictorTable::LogDatabaseStats()  {
    247   CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::DB));
    248   if (CantAccessDatabase())
    249     return;
    250 
    251   sql::Statement count_statement(DB()->GetUniqueStatement(
    252       base::StringPrintf("SELECT count(id) FROM %s",
    253                          kAutocompletePredictorTableName).c_str()));
    254   if (!count_statement.is_valid() || !count_statement.Step())
    255     return;
    256   UMA_HISTOGRAM_COUNTS("AutocompleteActionPredictor.DatabaseRowCount",
    257                        count_statement.ColumnInt(0));
    258 }
    259 
    260 }  // namespace predictors
    261