| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/history/core/browser/visit_database.h" | 5 #include "components/history/core/browser/visit_database.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <map> | 9 #include <map> |
| 10 #include <set> | 10 #include <set> |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 if (!GetDB().DoesTableExist("visits")) { | 29 if (!GetDB().DoesTableExist("visits")) { |
| 30 if (!GetDB().Execute("CREATE TABLE visits(" | 30 if (!GetDB().Execute("CREATE TABLE visits(" |
| 31 "id INTEGER PRIMARY KEY," | 31 "id INTEGER PRIMARY KEY," |
| 32 "url INTEGER NOT NULL," // key of the URL this corresponds to | 32 "url INTEGER NOT NULL," // key of the URL this corresponds to |
| 33 "visit_time INTEGER NOT NULL," | 33 "visit_time INTEGER NOT NULL," |
| 34 "from_visit INTEGER," | 34 "from_visit INTEGER," |
| 35 "transition INTEGER DEFAULT 0 NOT NULL," | 35 "transition INTEGER DEFAULT 0 NOT NULL," |
| 36 "segment_id INTEGER," | 36 "segment_id INTEGER," |
| 37 // Some old DBs may have an "is_indexed" field here, but this is no | 37 // Some old DBs may have an "is_indexed" field here, but this is no |
| 38 // longer used and should NOT be read or written from any longer. | 38 // longer used and should NOT be read or written from any longer. |
| 39 "visit_duration INTEGER DEFAULT 0 NOT NULL)")) | 39 "visit_duration INTEGER DEFAULT 0 NOT NULL," |
| 40 "context INTEGER DEFAULT 0 NOT NULL)")) |
| 40 return false; | 41 return false; |
| 41 } | 42 } |
| 42 | 43 |
| 43 // Visit source table contains the source information for all the visits. To | 44 // Visit source table contains the source information for all the visits. To |
| 44 // save space, we do not record those user browsed visits which would be the | 45 // save space, we do not record those user browsed visits which would be the |
| 45 // majority in this table. Only other sources are recorded. | 46 // majority in this table. Only other sources are recorded. |
| 46 // Due to the tight relationship between visit_source and visits table, they | 47 // Due to the tight relationship between visit_source and visits table, they |
| 47 // should be created and dropped at the same time. | 48 // should be created and dropped at the same time. |
| 48 if (!GetDB().DoesTableExist("visit_source")) { | 49 if (!GetDB().DoesTableExist("visit_source")) { |
| 49 if (!GetDB().Execute("CREATE TABLE visit_source(" | 50 if (!GetDB().Execute("CREATE TABLE visit_source(" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 // static | 85 // static |
| 85 void VisitDatabase::FillVisitRow(sql::Statement& statement, VisitRow* visit) { | 86 void VisitDatabase::FillVisitRow(sql::Statement& statement, VisitRow* visit) { |
| 86 visit->visit_id = statement.ColumnInt64(0); | 87 visit->visit_id = statement.ColumnInt64(0); |
| 87 visit->url_id = statement.ColumnInt64(1); | 88 visit->url_id = statement.ColumnInt64(1); |
| 88 visit->visit_time = base::Time::FromInternalValue(statement.ColumnInt64(2)); | 89 visit->visit_time = base::Time::FromInternalValue(statement.ColumnInt64(2)); |
| 89 visit->referring_visit = statement.ColumnInt64(3); | 90 visit->referring_visit = statement.ColumnInt64(3); |
| 90 visit->transition = ui::PageTransitionFromInt(statement.ColumnInt(4)); | 91 visit->transition = ui::PageTransitionFromInt(statement.ColumnInt(4)); |
| 91 visit->segment_id = statement.ColumnInt64(5); | 92 visit->segment_id = statement.ColumnInt64(5); |
| 92 visit->visit_duration = | 93 visit->visit_duration = |
| 93 base::TimeDelta::FromInternalValue(statement.ColumnInt64(6)); | 94 base::TimeDelta::FromInternalValue(statement.ColumnInt64(6)); |
| 95 visit->context = static_cast<HistoryContext>(statement.ColumnInt(7)); |
| 94 } | 96 } |
| 95 | 97 |
| 96 // static | 98 // static |
| 97 bool VisitDatabase::FillVisitVector(sql::Statement& statement, | 99 bool VisitDatabase::FillVisitVector(sql::Statement& statement, |
| 98 VisitVector* visits) { | 100 VisitVector* visits) { |
| 99 if (!statement.is_valid()) | 101 if (!statement.is_valid()) |
| 100 return false; | 102 return false; |
| 101 | 103 |
| 102 while (statement.Step()) { | 104 while (statement.Step()) { |
| 103 VisitRow visit; | 105 VisitRow visit; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 return true; | 140 return true; |
| 139 visits->push_back(visit); | 141 visits->push_back(visit); |
| 140 } | 142 } |
| 141 return false; | 143 return false; |
| 142 } | 144 } |
| 143 | 145 |
| 144 VisitID VisitDatabase::AddVisit(VisitRow* visit, VisitSource source) { | 146 VisitID VisitDatabase::AddVisit(VisitRow* visit, VisitSource source) { |
| 145 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 147 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 146 "INSERT INTO visits " | 148 "INSERT INTO visits " |
| 147 "(url, visit_time, from_visit, transition, segment_id, " | 149 "(url, visit_time, from_visit, transition, segment_id, " |
| 148 "visit_duration) VALUES (?,?,?,?,?,?)")); | 150 "visit_duration, context) VALUES (?,?,?,?,?,?,?)")); |
| 149 statement.BindInt64(0, visit->url_id); | 151 statement.BindInt64(0, visit->url_id); |
| 150 statement.BindInt64(1, visit->visit_time.ToInternalValue()); | 152 statement.BindInt64(1, visit->visit_time.ToInternalValue()); |
| 151 statement.BindInt64(2, visit->referring_visit); | 153 statement.BindInt64(2, visit->referring_visit); |
| 152 statement.BindInt64(3, visit->transition); | 154 statement.BindInt64(3, visit->transition); |
| 153 statement.BindInt64(4, visit->segment_id); | 155 statement.BindInt64(4, visit->segment_id); |
| 154 statement.BindInt64(5, visit->visit_duration.ToInternalValue()); | 156 statement.BindInt64(5, visit->visit_duration.ToInternalValue()); |
| 157 statement.BindInt(6, static_cast<int>(visit->context)); |
| 155 | 158 |
| 156 if (!statement.Run()) { | 159 if (!statement.Run()) { |
| 157 DVLOG(0) << "Failed to execute visit insert statement: " | 160 DVLOG(0) << "Failed to execute visit insert statement: " |
| 158 << "url_id = " << visit->url_id; | 161 << "url_id = " << visit->url_id; |
| 159 return 0; | 162 return 0; |
| 160 } | 163 } |
| 161 | |
| 162 visit->visit_id = GetDB().GetLastInsertRowId(); | 164 visit->visit_id = GetDB().GetLastInsertRowId(); |
| 163 | 165 |
| 164 if (source != SOURCE_BROWSED) { | 166 if (source != SOURCE_BROWSED) { |
| 165 // Record the source of this visit when it is not browsed. | 167 // Record the source of this visit when it is not browsed. |
| 166 sql::Statement statement1(GetDB().GetCachedStatement(SQL_FROM_HERE, | 168 sql::Statement statement1(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 167 "INSERT INTO visit_source (id, source) VALUES (?,?)")); | 169 "INSERT INTO visit_source (id, source) VALUES (?,?)")); |
| 168 statement1.BindInt64(0, visit->visit_id); | 170 statement1.BindInt64(0, visit->visit_id); |
| 169 statement1.BindInt64(1, source); | 171 statement1.BindInt64(1, source); |
| 170 | 172 |
| 171 if (!statement1.Run()) { | 173 if (!statement1.Run()) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 | 226 |
| 225 bool VisitDatabase::UpdateVisitRow(const VisitRow& visit) { | 227 bool VisitDatabase::UpdateVisitRow(const VisitRow& visit) { |
| 226 // Don't store inconsistent data to the database. | 228 // Don't store inconsistent data to the database. |
| 227 DCHECK_NE(visit.visit_id, visit.referring_visit); | 229 DCHECK_NE(visit.visit_id, visit.referring_visit); |
| 228 if (visit.visit_id == visit.referring_visit) | 230 if (visit.visit_id == visit.referring_visit) |
| 229 return false; | 231 return false; |
| 230 | 232 |
| 231 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 233 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 232 "UPDATE visits SET " | 234 "UPDATE visits SET " |
| 233 "url=?,visit_time=?,from_visit=?,transition=?,segment_id=?," | 235 "url=?,visit_time=?,from_visit=?,transition=?,segment_id=?," |
| 234 "visit_duration=? WHERE id=?")); | 236 "visit_duration=?, context=? WHERE id=?")); |
| 235 statement.BindInt64(0, visit.url_id); | 237 statement.BindInt64(0, visit.url_id); |
| 236 statement.BindInt64(1, visit.visit_time.ToInternalValue()); | 238 statement.BindInt64(1, visit.visit_time.ToInternalValue()); |
| 237 statement.BindInt64(2, visit.referring_visit); | 239 statement.BindInt64(2, visit.referring_visit); |
| 238 statement.BindInt64(3, visit.transition); | 240 statement.BindInt64(3, visit.transition); |
| 239 statement.BindInt64(4, visit.segment_id); | 241 statement.BindInt64(4, visit.segment_id); |
| 240 statement.BindInt64(5, visit.visit_duration.ToInternalValue()); | 242 statement.BindInt64(5, visit.visit_duration.ToInternalValue()); |
| 241 statement.BindInt64(6, visit.visit_id); | 243 statement.BindInt(6, visit.context); |
| 244 statement.BindInt64(7, visit.visit_id); |
| 242 | 245 |
| 243 return statement.Run(); | 246 return statement.Run(); |
| 244 } | 247 } |
| 245 | 248 |
| 246 bool VisitDatabase::GetVisitsForURL(URLID url_id, VisitVector* visits) { | 249 bool VisitDatabase::GetVisitsForURL(URLID url_id, VisitVector* visits) { |
| 247 visits->clear(); | 250 visits->clear(); |
| 248 | 251 |
| 249 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 252 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 250 "SELECT" HISTORY_VISIT_ROW_FIELDS | 253 "SELECT" HISTORY_VISIT_ROW_FIELDS |
| 251 "FROM visits " | 254 "FROM visits " |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 max_results ? max_results : std::numeric_limits<int64>::max()); | 347 max_results ? max_results : std::numeric_limits<int64>::max()); |
| 345 | 348 |
| 346 return FillVisitVector(statement, visits); | 349 return FillVisitVector(statement, visits); |
| 347 } | 350 } |
| 348 | 351 |
| 349 bool VisitDatabase::GetVisibleVisitsInRange(const QueryOptions& options, | 352 bool VisitDatabase::GetVisibleVisitsInRange(const QueryOptions& options, |
| 350 VisitVector* visits) { | 353 VisitVector* visits) { |
| 351 visits->clear(); | 354 visits->clear(); |
| 352 // The visit_time values can be duplicated in a redirect chain, so we sort | 355 // The visit_time values can be duplicated in a redirect chain, so we sort |
| 353 // by id too, to ensure a consistent ordering just in case. | 356 // by id too, to ensure a consistent ordering just in case. |
| 357 if (static_cast<int>(options.context) < 1 || static_cast<int>(options.context)
> 5) { |
| 354 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 358 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 355 "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " | 359 "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " |
| 356 "WHERE visit_time >= ? AND visit_time < ? " | 360 "WHERE visit_time >= ? AND visit_time < ? " |
| 357 "AND (transition & ?) != 0 " // CHAIN_END | 361 "AND (transition & ?) != 0 " // CHAIN_END |
| 358 "AND (transition & ?) NOT IN (?, ?, ?) " // NO SUBFRAME or | 362 "AND (transition & ?) NOT IN (?, ?, ?) " // NO SUBFRAME or |
| 359 // KEYWORD_GENERATED | 363 // KEYWORD_GENERATED |
| 360 "ORDER BY visit_time DESC, id DESC")); | 364 "ORDER BY visit_time DESC, id DESC")); |
| 361 | |
| 362 statement.BindInt64(0, options.EffectiveBeginTime()); | 365 statement.BindInt64(0, options.EffectiveBeginTime()); |
| 363 statement.BindInt64(1, options.EffectiveEndTime()); | 366 statement.BindInt64(1, options.EffectiveEndTime()); |
| 364 statement.BindInt(2, ui::PAGE_TRANSITION_CHAIN_END); | 367 statement.BindInt(2, ui::PAGE_TRANSITION_CHAIN_END); |
| 365 statement.BindInt(3, ui::PAGE_TRANSITION_CORE_MASK); | 368 statement.BindInt(3, ui::PAGE_TRANSITION_CORE_MASK); |
| 366 statement.BindInt(4, ui::PAGE_TRANSITION_AUTO_SUBFRAME); | 369 statement.BindInt(4, ui::PAGE_TRANSITION_AUTO_SUBFRAME); |
| 367 statement.BindInt(5, ui::PAGE_TRANSITION_MANUAL_SUBFRAME); | 370 statement.BindInt(5, ui::PAGE_TRANSITION_MANUAL_SUBFRAME); |
| 368 statement.BindInt(6, ui::PAGE_TRANSITION_KEYWORD_GENERATED); | 371 statement.BindInt(6, ui::PAGE_TRANSITION_KEYWORD_GENERATED); |
| 369 | |
| 370 return FillVisitVectorWithOptions(statement, options, visits); | 372 return FillVisitVectorWithOptions(statement, options, visits); |
| 373 } else { |
| 374 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 375 "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " |
| 376 "WHERE visit_time >= ? AND visit_time < ? AND context == ? " |
| 377 "AND (transition & ?) != 0 " // CHAIN_END |
| 378 "AND (transition & ?) NOT IN (?, ?, ?) " // NO SUBFRAME or |
| 379 // KEYWORD_GENERATED |
| 380 "ORDER BY visit_time DESC, id DESC")); |
| 381 statement.BindInt64(0, options.EffectiveBeginTime()); |
| 382 statement.BindInt64(1, options.EffectiveEndTime()); |
| 383 statement.BindInt(2, static_cast<int>(options.context)); |
| 384 statement.BindInt(3, ui::PAGE_TRANSITION_CHAIN_END); |
| 385 statement.BindInt(4, ui::PAGE_TRANSITION_CORE_MASK); |
| 386 statement.BindInt(5, ui::PAGE_TRANSITION_AUTO_SUBFRAME); |
| 387 statement.BindInt(6, ui::PAGE_TRANSITION_MANUAL_SUBFRAME); |
| 388 statement.BindInt(7, ui::PAGE_TRANSITION_KEYWORD_GENERATED); |
| 389 return FillVisitVectorWithOptions(statement, options, visits); |
| 390 } |
| 371 } | 391 } |
| 372 | 392 |
| 373 void VisitDatabase::GetDirectVisitsDuringTimes(const VisitFilter& time_filter, | 393 void VisitDatabase::GetDirectVisitsDuringTimes(const VisitFilter& time_filter, |
| 374 int max_results, | 394 int max_results, |
| 375 VisitVector* visits) { | 395 VisitVector* visits) { |
| 376 visits->clear(); | 396 visits->clear(); |
| 377 if (max_results) | 397 if (max_results) |
| 378 visits->reserve(max_results); | 398 visits->reserve(max_results); |
| 379 for (VisitFilter::TimeVector::const_iterator it = time_filter.times().begin(); | 399 for (VisitFilter::TimeVector::const_iterator it = time_filter.times().begin(); |
| 380 it != time_filter.times().end(); ++it) { | 400 it != time_filter.times().end(); ++it) { |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 // Old versions don't have the visit_duration column, we modify the table | 613 // Old versions don't have the visit_duration column, we modify the table |
| 594 // to add that field. | 614 // to add that field. |
| 595 if (!GetDB().Execute("ALTER TABLE visits " | 615 if (!GetDB().Execute("ALTER TABLE visits " |
| 596 "ADD COLUMN visit_duration INTEGER DEFAULT 0 NOT NULL")) | 616 "ADD COLUMN visit_duration INTEGER DEFAULT 0 NOT NULL")) |
| 597 return false; | 617 return false; |
| 598 } | 618 } |
| 599 return true; | 619 return true; |
| 600 } | 620 } |
| 601 | 621 |
| 602 } // namespace history | 622 } // namespace history |
| OLD | NEW |