15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/visit_database.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/url_database.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/visit_filter.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/page_transition_types.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/statement.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace history { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VisitDatabase::VisitDatabase() { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VisitDatabase::~VisitDatabase() { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::InitVisitTable() { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().DoesTableExist("visits")) { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().Execute("CREATE TABLE visits(" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "id INTEGER PRIMARY KEY," 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "url INTEGER NOT NULL," // key of the URL this corresponds to 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "visit_time INTEGER NOT NULL," 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "from_visit INTEGER," 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "transition INTEGER DEFAULT 0 NOT NULL," 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "segment_id INTEGER," 37bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Some old DBs may have an "is_indexed" field here, but this is no 38bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // longer used and should NOT be read or written from any longer. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "visit_duration INTEGER DEFAULT 0 NOT NULL)")) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Visit source table contains the source information for all the visits. To 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // save space, we do not record those user browsed visits which would be the 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // majority in this table. Only other sources are recorded. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Due to the tight relationship between visit_source and visits table, they 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should be created and dropped at the same time. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().DoesTableExist("visit_source")) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().Execute("CREATE TABLE visit_source(" 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "id INTEGER PRIMARY KEY,source INTEGER NOT NULL)")) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Index over url so we can quickly find visits for a page. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().Execute( 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "CREATE INDEX IF NOT EXISTS visits_url_index ON visits (url)")) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an index over from visits so that we can efficiently find 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // referrers and redirects. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().Execute( 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "CREATE INDEX IF NOT EXISTS visits_from_index ON " 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "visits (from_visit)")) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an index over time so that we can efficiently find the visits in a 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // given time range (most history views are time-based). 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().Execute( 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "CREATE INDEX IF NOT EXISTS visits_time_index ON " 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "visits (visit_time)")) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::DropVisitTable() { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This will also drop the indices over the table. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetDB().Execute("DROP TABLE IF EXISTS visit_source") && 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetDB().Execute("DROP TABLE visits"); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Must be in sync with HISTORY_VISIT_ROW_FIELDS. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitDatabase::FillVisitRow(sql::Statement& statement, VisitRow* visit) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit->visit_id = statement.ColumnInt64(0); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit->url_id = statement.ColumnInt64(1); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit->visit_time = base::Time::FromInternalValue(statement.ColumnInt64(2)); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit->referring_visit = statement.ColumnInt64(3); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit->transition = content::PageTransitionFromInt(statement.ColumnInt(4)); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit->segment_id = statement.ColumnInt64(5); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit->visit_duration = 93bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch base::TimeDelta::FromInternalValue(statement.ColumnInt64(6)); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::FillVisitVector(sql::Statement& statement, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits) { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.is_valid()) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (statement.Step()) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::VisitRow visit; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FillVisitRow(statement, &visit); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->push_back(visit); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return statement.Succeeded(); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// static 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool VisitDatabase::FillVisitVectorWithOptions(sql::Statement& statement, 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const QueryOptions& options, 114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VisitVector* visits) { 115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::set<URLID> found_urls; 116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Keeps track of the day that |found_urls| is holding the URLs for, in order 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // to handle removing per-day duplicates. 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Time found_urls_midnight; 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch while (statement.Step()) { 122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VisitRow visit; 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch FillVisitRow(statement, &visit); 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (options.duplicate_policy != QueryOptions::KEEP_ALL_DUPLICATES) { 126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (options.duplicate_policy == QueryOptions::REMOVE_DUPLICATES_PER_DAY && 127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch found_urls_midnight != visit.visit_time.LocalMidnight()) { 128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch found_urls.clear(); 129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch found_urls_midnight = visit.visit_time.LocalMidnight(); 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Make sure the URL this visit corresponds to is unique. 132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (found_urls.find(visit.url_id) != found_urls.end()) 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch continue; 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch found_urls.insert(visit.url_id); 135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (static_cast<int>(visits->size()) >= options.EffectiveMaxCount()) 138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return true; 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch visits->push_back(visit); 140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VisitID VisitDatabase::AddVisit(VisitRow* visit, VisitSource source) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "INSERT INTO visits " 147bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch "(url, visit_time, from_visit, transition, segment_id, " 148bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch "visit_duration) VALUES (?,?,?,?,?,?)")); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, visit->url_id); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(1, visit->visit_time.ToInternalValue()); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(2, visit->referring_visit); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(3, visit->transition); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(4, visit->segment_id); 154bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch statement.BindInt64(5, visit->visit_duration.ToInternalValue()); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.Run()) { 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Failed to execute visit insert statement: " 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "url_id = " << visit->url_id; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit->visit_id = GetDB().GetLastInsertRowId(); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (source != SOURCE_BROWSED) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record the source of this visit when it is not browsed. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement1(GetDB().GetCachedStatement(SQL_FROM_HERE, 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "INSERT INTO visit_source (id, source) VALUES (?,?)")); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement1.BindInt64(0, visit->visit_id); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement1.BindInt64(1, source); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement1.Run()) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Failed to execute visit_source insert statement: " 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "id = " << visit->visit_id; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return visit->visit_id; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitDatabase::DeleteVisit(const VisitRow& visit) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Patch around this visit. Any visits that this went to will now have their 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "source" be the deleted visit's source. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement update_chain(GetDB().GetCachedStatement(SQL_FROM_HERE, 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "UPDATE visits SET from_visit=? WHERE from_visit=?")); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update_chain.BindInt64(0, visit.referring_visit); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update_chain.BindInt64(1, visit.visit_id); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!update_chain.Run()) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now delete the actual visit. 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement del(GetDB().GetCachedStatement(SQL_FROM_HERE, 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "DELETE FROM visits WHERE id=?")); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) del.BindInt64(0, visit.visit_id); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!del.Run()) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try to delete the entry in visit_source table as well. 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the visit was browsed, there is no corresponding entry in visit_source 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // table, and nothing will be deleted. 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) del.Assign(GetDB().GetCachedStatement(SQL_FROM_HERE, 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "DELETE FROM visit_source WHERE id=?")); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) del.BindInt64(0, visit.visit_id); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) del.Run(); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetRowForVisit(VisitID visit_id, VisitRow* out_visit) { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits WHERE id=?")); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, visit_id); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.Step()) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FillVisitRow(statement, out_visit); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We got a different visit than we asked for, something is wrong. 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(visit_id, out_visit->visit_id); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_id != out_visit->visit_id) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::UpdateVisitRow(const VisitRow& visit) { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't store inconsistent data to the database. 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(visit.visit_id, visit.referring_visit); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit.visit_id == visit.referring_visit) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "UPDATE visits SET " 233bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch "url=?,visit_time=?,from_visit=?,transition=?,segment_id=?," 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "visit_duration=? WHERE id=?")); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, visit.url_id); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(1, visit.visit_time.ToInternalValue()); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(2, visit.referring_visit); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(3, visit.transition); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(4, visit.segment_id); 240bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch statement.BindInt64(5, visit.visit_duration.ToInternalValue()); 241bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch statement.BindInt64(6, visit.visit_id); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return statement.Run(); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetVisitsForURL(URLID url_id, VisitVector* visits) { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->clear(); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "FROM visits " 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE url=? " 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ORDER BY visit_time ASC")); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, url_id); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FillVisitVector(statement, visits); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool VisitDatabase::GetVisitsForURLWithOptions(URLID url_id, 259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const QueryOptions& options, 260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VisitVector* visits) { 261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch visits->clear(); 262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (options.REMOVE_ALL_DUPLICATES) { 264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VisitRow visit_row; 265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VisitID visit_id = GetMostRecentVisitForURL(url_id, &visit_row); 266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (visit_id && options.EffectiveMaxCount() != 0) { 267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch visits->push_back(visit_row); 268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return options.EffectiveMaxCount() == 0 && visit_id; 270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "SELECT" HISTORY_VISIT_ROW_FIELDS 273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "FROM visits " 274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "WHERE url=? AND visit_time >= ? AND visit_time < ? " 275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "ORDER BY visit_time DESC")); 276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch statement.BindInt64(0, url_id); 277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch statement.BindInt64(1, options.EffectiveBeginTime()); 278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch statement.BindInt64(2, options.EffectiveEndTime()); 279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return FillVisitVectorWithOptions(statement, options, visits); 281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VisitDatabase::GetVisitsForTimes(const std::vector<base::Time>& times, 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VisitVector* visits) { 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) visits->clear(); 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::vector<base::Time>::const_iterator it = times.begin(); 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != times.end(); ++it) { 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "WHERE visit_time == ?")); 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement.BindInt64(0, it->ToInternalValue()); 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!FillVisitVector(statement, visits)) 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetAllVisitsInRange(base::Time begin_time, 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time end_time, 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_results, 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits) { 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->clear(); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE visit_time >= ? AND visit_time < ?" 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ORDER BY visit_time LIMIT ?")); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See GetVisibleVisitsInRange for more info on how these times are bound. 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 end = end_time.ToInternalValue(); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, begin_time.ToInternalValue()); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(1, end ? end : std::numeric_limits<int64>::max()); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(2, 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_results ? max_results : std::numeric_limits<int64>::max()); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FillVisitVector(statement, visits); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetVisitsInRangeForTransition( 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time begin_time, 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time end_time, 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_results, 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition, 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits) { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(visits); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->clear(); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE visit_time >= ? AND visit_time < ? " 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND (transition & ?) == ?" 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ORDER BY visit_time LIMIT ?")); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See GetVisibleVisitsInRange for more info on how these times are bound. 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 end = end_time.ToInternalValue(); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, begin_time.ToInternalValue()); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(1, end ? end : std::numeric_limits<int64>::max()); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(2, content::PAGE_TRANSITION_CORE_MASK); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(3, transition); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(4, 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_results ? max_results : std::numeric_limits<int64>::max()); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FillVisitVector(statement, visits); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VisitDatabase::GetVisibleVisitsInRange(const QueryOptions& options, 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits) { 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->clear(); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The visit_time values can be duplicated in a redirect chain, so we sort 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by id too, to ensure a consistent ordering just in case. 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE visit_time >= ? AND visit_time < ? " 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND (transition & ?) != 0 " // CHAIN_END 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND (transition & ?) NOT IN (?, ?, ?) " // NO SUBFRAME or 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // KEYWORD_GENERATED 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ORDER BY visit_time DESC, id DESC")); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement.BindInt64(0, options.EffectiveBeginTime()); 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement.BindInt64(1, options.EffectiveEndTime()); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(2, content::PAGE_TRANSITION_CHAIN_END); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(3, content::PAGE_TRANSITION_CORE_MASK); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(4, content::PAGE_TRANSITION_AUTO_SUBFRAME); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(5, content::PAGE_TRANSITION_MANUAL_SUBFRAME); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(6, content::PAGE_TRANSITION_KEYWORD_GENERATED); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return FillVisitVectorWithOptions(statement, options, visits); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitDatabase::GetDirectVisitsDuringTimes(const VisitFilter& time_filter, 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_results, 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits) { 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->clear(); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (max_results) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->reserve(max_results); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (VisitFilter::TimeVector::const_iterator it = time_filter.times().begin(); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != time_filter.times().end(); ++it) { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE visit_time >= ? AND visit_time < ? " 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND (transition & ?) != 0 " // CHAIN_START 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND (transition & ?) IN (?, ?) " // TYPED or AUTO_BOOKMARK only 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ORDER BY visit_time DESC, id DESC")); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, it->first.ToInternalValue()); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(1, it->second.ToInternalValue()); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(2, content::PAGE_TRANSITION_CHAIN_START); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(3, content::PAGE_TRANSITION_CORE_MASK); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(4, content::PAGE_TRANSITION_TYPED); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(5, content::PAGE_TRANSITION_AUTO_BOOKMARK); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (statement.Step()) { 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FillVisitRow(statement, &visit); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->push_back(visit); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (max_results > 0 && static_cast<int>(visits->size()) >= max_results) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VisitID VisitDatabase::GetMostRecentVisitForURL(URLID url_id, 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow* visit_row) { 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The visit_time values can be duplicated in a redirect chain, so we sort 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by id too, to ensure a consistent ordering just in case. 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE url=? " 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ORDER BY visit_time DESC, id DESC " 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "LIMIT 1")); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, url_id); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.Step()) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; // No visits for this URL. 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_row) { 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FillVisitRow(statement, visit_row); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return visit_row->visit_id; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return statement.ColumnInt64(0); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetMostRecentVisitsForURL(URLID url_id, 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_results, 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits) { 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->clear(); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The visit_time values can be duplicated in a redirect chain, so we sort 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by id too, to ensure a consistent ordering just in case. 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "FROM visits " 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE url=? " 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ORDER BY visit_time DESC, id DESC " 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "LIMIT ?")); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, url_id); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(1, max_results); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FillVisitVector(statement, visits); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetRedirectFromVisit(VisitID from_visit, 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID* to_visit, 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL* to_url) { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT v.id,u.url " 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "FROM visits v JOIN urls u ON v.url = u.id " 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE v.from_visit = ? " 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND (v.transition & ?) != 0")); // IS_REDIRECT_MASK 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, from_visit); 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(1, content::PAGE_TRANSITION_IS_REDIRECT_MASK); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.Step()) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // No redirect from this visit. (Or SQL error) 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (to_visit) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *to_visit = statement.ColumnInt64(0); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (to_url) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *to_url = GURL(statement.ColumnString(1)); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetRedirectToVisit(VisitID to_visit, 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID* from_visit, 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL* from_url) { 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow row; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetRowForVisit(to_visit, &row)) 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (from_visit) 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *from_visit = row.referring_visit; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (from_url) { 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT u.url " 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "FROM visits v JOIN urls u ON v.url = u.id " 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE v.id = ?")); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, row.referring_visit); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.Step()) 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *from_url = GURL(statement.ColumnString(0)); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetVisibleVisitCountToHost(const GURL& url, 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* count, 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time* first_visit) { 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url.SchemeIs(chrome::kHttpScheme) && !url.SchemeIs(chrome::kHttpsScheme)) 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to search for URLs with a matching host/port. One way to query for 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this is to use the LIKE operator, eg 'url LIKE http://google.com/%'. This 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is inefficient though in that it doesn't use the index and each entry must 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be visited. The same query can be executed by using >= and < operator. 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The query becomes: 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 'url >= http://google.com/' and url < http://google.com0'. 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0 is used as it is one character greater than '/'. 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string host_query_min = url.GetOrigin().spec(); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (host_query_min.empty()) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We also want to restrict ourselves to main frame navigations that are not 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in the middle of redirect chains, hence the transition checks. 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT MIN(v.visit_time), COUNT(*) " 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "FROM visits v INNER JOIN urls u ON v.url = u.id " 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE u.url >= ? AND u.url < ? " 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND (transition & ?) != 0 " 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND (transition & ?) NOT IN (?, ?, ?)")); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindString(0, host_query_min); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindString(1, 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_query_min.substr(0, host_query_min.size() - 1) + '0'); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(2, content::PAGE_TRANSITION_CHAIN_END); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(3, content::PAGE_TRANSITION_CORE_MASK); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(4, content::PAGE_TRANSITION_AUTO_SUBFRAME); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(5, content::PAGE_TRANSITION_MANUAL_SUBFRAME); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(6, content::PAGE_TRANSITION_KEYWORD_GENERATED); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.Step()) { 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We've never been to this page before. 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *count = 0; 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.Succeeded()) 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *first_visit = base::Time::FromInternalValue(statement.ColumnInt64(0)); 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *count = statement.ColumnInt(1); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetStartDate(base::Time* first_visit) { 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT MIN(visit_time) FROM visits WHERE visit_time != 0")); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.Step() || statement.ColumnInt64(0) == 0) { 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *first_visit = base::Time::Now(); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *first_visit = base::Time::FromInternalValue(statement.ColumnInt64(0)); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitDatabase::GetVisitsSource(const VisitVector& visits, 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSourceMap* sources) { 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(sources); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sources->clear(); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We query the source in batch. Here defines the batch size. 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t batch_size = 500; 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t visits_size = visits.size(); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t start_index = 0, end_index = 0; 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (end_index < visits_size) { 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_index = end_index; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) end_index = end_index + batch_size < visits_size ? end_index + batch_size 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : visits_size; 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compose the sql statement with a list of ids. 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string sql = "SELECT id,source FROM visit_source "; 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql.append("WHERE id IN ("); 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Append all the ids in the statement. 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = start_index; j < end_index; j++) { 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (j != start_index) 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql.push_back(','); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql.append(base::Int64ToString(visits[j].visit_id)); 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql.append(") ORDER BY id"); 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetUniqueStatement(sql.c_str())); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the source entries out of the query result. 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (statement.Step()) { 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<VisitID, VisitSource> source_entry(statement.ColumnInt64(0), 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<VisitSource>(statement.ColumnInt(1))); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sources->insert(source_entry); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::MigrateVisitsWithoutDuration() { 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().DoesTableExist("visits")) { 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << " Visits table should exist before migration"; 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().DoesColumnExist("visits", "visit_duration")) { 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Old versions don't have the visit_duration column, we modify the table 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to add that field. 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().Execute("ALTER TABLE visits " 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ADD COLUMN visit_duration INTEGER DEFAULT 0 NOT NULL")) 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitDatabase::GetBriefVisitInfoOfMostRecentVisits( 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_visits, 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<BriefVisitInfo>* result_vector) { 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_vector->clear(); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetUniqueStatement( 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT url,visit_time,transition FROM visits " 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ORDER BY id DESC LIMIT ?")); 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, max_visits); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.is_valid()) 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (statement.Step()) { 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BriefVisitInfo info; 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.url_id = statement.ColumnInt64(0); 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.time = base::Time::FromInternalValue(statement.ColumnInt64(1)); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.transition = content::PageTransitionFromInt(statement.ColumnInt(2)); 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_vector->push_back(info); 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace history 626