- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / predictors / autocomplete_action_predictor_table.cc
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 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