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.
5 #include "chrome/browser/predictors/autocomplete_action_predictor_table.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"
17 // TODO(shishir): Rename the table for consistency.
18 const char kAutocompletePredictorTableName
[] = "network_action_predictor";
20 // The maximum length allowed for strings in the database.
21 const size_t kMaxDataLength
= 2048;
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
);
34 bool StepAndInitializeRow(
35 sql::Statement
* statement
,
36 predictors::AutocompleteActionPredictorTable::Row
* row
) {
37 if (!statement
->Step())
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);
50 namespace predictors
{
52 AutocompleteActionPredictorTable::Row::Row()
57 AutocompleteActionPredictorTable::Row::Row(const Row::Id
& id
,
58 const base::string16
& user_text
,
65 number_of_hits(number_of_hits
),
66 number_of_misses(number_of_misses
) {
69 AutocompleteActionPredictorTable::Row::Row(const Row
& row
)
71 user_text(row
.user_text
),
73 number_of_hits(row
.number_of_hits
),
74 number_of_misses(row
.number_of_misses
) {
78 void AutocompleteActionPredictorTable::GetRow(const Row::Id
& id
, Row
* row
) {
79 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::DB
));
80 if (CantAccessDatabase())
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
);
88 bool success
= StepAndInitializeRow(&statement
, row
);
89 DCHECK(success
) << "Failed to get row " << id
<< " from "
90 << kAutocompletePredictorTableName
;
93 void AutocompleteActionPredictorTable::GetAllRows(Rows
* row_buffer
) {
94 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::DB
));
95 if (CantAccessDatabase())
100 sql::Statement
statement(DB()->GetCachedStatement(SQL_FROM_HERE
,
102 "SELECT * FROM %s", kAutocompletePredictorTableName
).c_str()));
103 if (!statement
.is_valid())
107 while (StepAndInitializeRow(&statement
, &row
))
108 row_buffer
->push_back(row
);
111 void AutocompleteActionPredictorTable::AddRow(
112 const AutocompleteActionPredictorTable::Row
& row
) {
113 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::DB
));
114 if (CantAccessDatabase())
117 AddAndUpdateRows(Rows(1, row
), Rows());
120 void AutocompleteActionPredictorTable::UpdateRow(
121 const AutocompleteActionPredictorTable::Row
& row
) {
122 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::DB
));
123 if (CantAccessDatabase())
126 AddAndUpdateRows(Rows(), Rows(1, row
));
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())
136 if (!DB()->BeginTransaction())
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
,
143 "(id, user_text, url, number_of_hits, number_of_misses) "
144 "VALUES (?,?,?,?,?)", kAutocompletePredictorTableName
).c_str()));
145 if (!statement
.is_valid()) {
146 DB()->RollbackTransaction();
150 BindRowToStatement(*it
, &statement
);
151 if (!statement
.Run()) {
152 DB()->RollbackTransaction();
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
,
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();
168 BindRowToStatement(*it
, &statement
);
169 if (!statement
.Run()) {
170 DB()->RollbackTransaction();
173 DCHECK_GT(DB()->GetLastChangeCount(), 0);
175 DB()->CommitTransaction();
178 void AutocompleteActionPredictorTable::DeleteRows(
179 const std::vector
<Row::Id
>& id_list
) {
180 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::DB
));
181 if (CantAccessDatabase())
184 if (!DB()->BeginTransaction())
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
,
190 "DELETE FROM %s WHERE id=?",
191 kAutocompletePredictorTableName
).c_str()));
192 if (!statement
.is_valid()) {
193 DB()->RollbackTransaction();
197 statement
.BindString(0, *it
);
198 if (!statement
.Run()) {
199 DB()->RollbackTransaction();
203 DB()->CommitTransaction();
206 void AutocompleteActionPredictorTable::DeleteAllRows() {
207 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::DB
));
208 if (CantAccessDatabase())
211 sql::Statement
statement(DB()->GetCachedStatement(SQL_FROM_HERE
,
212 base::StringPrintf("DELETE FROM %s",
213 kAutocompletePredictorTableName
).c_str()));
214 if (!statement
.is_valid())
220 AutocompleteActionPredictorTable::AutocompleteActionPredictorTable()
221 : PredictorTableBase() {
224 AutocompleteActionPredictorTable::~AutocompleteActionPredictorTable() {
227 void AutocompleteActionPredictorTable::CreateTableIfNonExistent() {
228 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::DB
));
229 if (CantAccessDatabase())
232 if (DB()->DoesTableExist(kAutocompletePredictorTableName
))
235 bool success
= DB()->Execute(base::StringPrintf(
237 "id TEXT PRIMARY KEY, "
240 "number_of_hits INTEGER, "
241 "number_of_misses INTEGER)", kAutocompletePredictorTableName
).c_str());
246 void AutocompleteActionPredictorTable::LogDatabaseStats() {
247 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::DB
));
248 if (CantAccessDatabase())
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())
256 UMA_HISTOGRAM_COUNTS("AutocompleteActionPredictor.DatabaseRowCount",
257 count_statement
.ColumnInt(0));
260 } // namespace predictors