| Index: chrome/browser/history/visit_database.cc
|
| diff --git a/chrome/browser/history/visit_database.cc b/chrome/browser/history/visit_database.cc
|
| index 2280a1b65df4ae965995d9be1ee86e54764cc685..252deccb64f03e9997160849b5b703088f029553 100644
|
| --- a/chrome/browser/history/visit_database.cc
|
| +++ b/chrome/browser/history/visit_database.cc
|
| @@ -368,6 +368,16 @@ bool VisitDatabase::InitVisitTable() {
|
| return false;
|
| }
|
|
|
| + // Visit details table contains some extra details about a visit such as
|
| + // the visit duration. In the future, more information such as active
|
| + // duration or language can be added too.
|
| + if (!GetDB().DoesTableExist("visit_details")) {
|
| + if (!GetDB().Execute("CREATE TABLE visit_details("
|
| + "id INTEGER PRIMARY KEY,"
|
| + "duration INTEGER DEFAULT 0 NOT NULL)"))
|
| + return false;
|
| + }
|
| +
|
| // Index over url so we can quickly find visits for a page.
|
| if (!GetDB().Execute(
|
| "CREATE INDEX IF NOT EXISTS visits_url_index ON visits (url)"))
|
| @@ -393,6 +403,7 @@ bool VisitDatabase::InitVisitTable() {
|
| bool VisitDatabase::DropVisitTable() {
|
| // This will also drop the indices over the table.
|
| return
|
| + GetDB().Execute("DROP TABLE IF EXISTS visit_details") &&
|
| GetDB().Execute("DROP TABLE IF EXISTS visit_source") &&
|
| GetDB().Execute("DROP TABLE visits");
|
| }
|
| @@ -454,11 +465,23 @@ VisitID VisitDatabase::AddVisit(VisitRow* visit, VisitSource source) {
|
|
|
| if (!statement1.Run()) {
|
| VLOG(0) << "Failed to execute visit_source insert statement: "
|
| - << "url_id = " << visit->visit_id;
|
| + << "id = " << visit->visit_id;
|
| return 0;
|
| }
|
| }
|
|
|
| + // Add the visit into visit_details table as well.
|
| + sql::Statement statement1(GetDB().GetCachedStatement(SQL_FROM_HERE,
|
| + "INSERT INTO visit_details (id, duration) VALUES (?,?)"));
|
| + statement1.BindInt64(0, visit->visit_id);
|
| + statement1.BindInt64(1, 0);
|
| +
|
| + if (!statement1.Run()) {
|
| + VLOG(0) << "Failed to execute visit_details insert statement: "
|
| + << "id = " << visit->visit_id;
|
| + return 0;
|
| + }
|
| +
|
| return visit->visit_id;
|
| }
|
|
|
| @@ -486,6 +509,15 @@ void VisitDatabase::DeleteVisit(const VisitRow& visit) {
|
| "DELETE FROM visit_source WHERE id=?"));
|
| del.BindInt64(0, visit.visit_id);
|
| del.Run();
|
| +
|
| + // Delete the entry in visit_details table as well.
|
| + // We don't care about archiving details information about visits. We will
|
| + // simply delete all the information for either archived or deleted visits
|
| + // when they are removed from visits database.
|
| + del.Assign(GetDB().GetCachedStatement(SQL_FROM_HERE,
|
| + "DELETE FROM visit_details WHERE id=?"));
|
| + del.BindInt64(0, visit.visit_id);
|
| + del.Run();
|
| }
|
|
|
| bool VisitDatabase::GetRowForVisit(VisitID visit_id, VisitRow* out_visit) {
|
| @@ -842,4 +874,51 @@ void VisitDatabase::GetVisitsSource(const VisitVector& visits,
|
| }
|
| }
|
|
|
| +bool VisitDatabase::UpdateVisitDetails(VisitID visit_id,
|
| + const base::TimeDelta duration) {
|
| + sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
|
| + "UPDATE visit_details SET duration=? WHERE id=?"));
|
| + statement.BindInt64(0, duration.ToInternalValue());
|
| + statement.BindInt64(1, visit_id);
|
| +
|
| + return statement.Run();
|
| +}
|
| +
|
| +void VisitDatabase::GetVisitDetails(const VisitVector& visits,
|
| + VisitDetailMap* details) {
|
| + DCHECK(details);
|
| + details->clear();
|
| +
|
| + // We query the details in batch. Here defines the batch size.
|
| + const size_t batch_size = 500;
|
| + size_t visits_size = visits.size();
|
| +
|
| + size_t start_index = 0, end_index = 0;
|
| + while (end_index < visits_size) {
|
| + start_index = end_index;
|
| + end_index = end_index + batch_size < visits_size ? end_index + batch_size
|
| + : visits_size;
|
| +
|
| + // Compose the sql statement with a list of ids.
|
| + std::string sql = "SELECT id,duration FROM visit_details ";
|
| + sql.append("WHERE id IN (");
|
| + // Append all the ids in the statement.
|
| + for (size_t j = start_index; j < end_index; j++) {
|
| + if (j != start_index)
|
| + sql.push_back(',');
|
| + sql.append(base::Int64ToString(visits[j].visit_id));
|
| + }
|
| + sql.append(") ORDER BY id");
|
| + sql::Statement statement(GetDB().GetUniqueStatement(sql.c_str()));
|
| +
|
| + // Get the source entries out of the query result.
|
| + while (statement.Step()) {
|
| + VisitDetailRow row =
|
| + {base::TimeDelta::FromInternalValue(statement.ColumnInt64(1))};
|
| + std::pair<VisitID, VisitDetailRow> entry(statement.ColumnInt64(0), row);
|
| + details->insert(entry);
|
| + }
|
| + }
|
| +}
|
| +
|
| } // namespace history
|
|
|