visit_database.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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," 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // True when we have indexed data for this visit. 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "is_indexed BOOLEAN," 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "visit_duration INTEGER DEFAULT 0 NOT NULL)")) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!GetDB().DoesColumnExist("visits", "is_indexed")) { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Old versions don't have the is_indexed column, we can just add that and 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not worry about different database revisions, since old ones will 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // continue to work. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(brettw) this should be removed once we think everybody has been 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // updated (added early Mar 2008). 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().Execute("ALTER TABLE visits ADD COLUMN is_indexed BOOLEAN")) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Visit source table contains the source information for all the visits. To 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // save space, we do not record those user browsed visits which would be the 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // majority in this table. Only other sources are recorded. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Due to the tight relationship between visit_source and visits table, they 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should be created and dropped at the same time. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().DoesTableExist("visit_source")) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().Execute("CREATE TABLE visit_source(" 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "id INTEGER PRIMARY KEY,source INTEGER NOT NULL)")) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Index over url so we can quickly find visits for a page. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().Execute( 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "CREATE INDEX IF NOT EXISTS visits_url_index ON visits (url)")) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an index over from visits so that we can efficiently find 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // referrers and redirects. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().Execute( 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "CREATE INDEX IF NOT EXISTS visits_from_index ON " 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "visits (from_visit)")) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create an index over time so that we can efficiently find the visits in a 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // given time range (most history views are time-based). 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().Execute( 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "CREATE INDEX IF NOT EXISTS visits_time_index ON " 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "visits (visit_time)")) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::DropVisitTable() { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This will also drop the indices over the table. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetDB().Execute("DROP TABLE IF EXISTS visit_source") && 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetDB().Execute("DROP TABLE visits"); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Must be in sync with HISTORY_VISIT_ROW_FIELDS. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitDatabase::FillVisitRow(sql::Statement& statement, VisitRow* visit) { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit->visit_id = statement.ColumnInt64(0); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit->url_id = statement.ColumnInt64(1); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit->visit_time = base::Time::FromInternalValue(statement.ColumnInt64(2)); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit->referring_visit = statement.ColumnInt64(3); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit->transition = content::PageTransitionFromInt(statement.ColumnInt(4)); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit->segment_id = statement.ColumnInt64(5); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit->is_indexed = !!statement.ColumnInt(6); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit->visit_duration = 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromInternalValue(statement.ColumnInt64(7)); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::FillVisitVector(sql::Statement& statement, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.is_valid()) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (statement.Step()) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history::VisitRow visit; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FillVisitRow(statement, &visit); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->push_back(visit); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return statement.Succeeded(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VisitID VisitDatabase::AddVisit(VisitRow* visit, VisitSource source) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "INSERT INTO visits " 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "(url, visit_time, from_visit, transition, segment_id, is_indexed, " 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "visit_duration) VALUES (?,?,?,?,?,?,?)")); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, visit->url_id); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(1, visit->visit_time.ToInternalValue()); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(2, visit->referring_visit); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(3, visit->transition); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(4, visit->segment_id); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(5, visit->is_indexed); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(6, visit->visit_duration.ToInternalValue()); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.Run()) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Failed to execute visit insert statement: " 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "url_id = " << visit->url_id; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visit->visit_id = GetDB().GetLastInsertRowId(); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (source != SOURCE_BROWSED) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record the source of this visit when it is not browsed. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement1(GetDB().GetCachedStatement(SQL_FROM_HERE, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "INSERT INTO visit_source (id, source) VALUES (?,?)")); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement1.BindInt64(0, visit->visit_id); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement1.BindInt64(1, source); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement1.Run()) { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(0) << "Failed to execute visit_source insert statement: " 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "id = " << visit->visit_id; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return visit->visit_id; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitDatabase::DeleteVisit(const VisitRow& visit) { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Patch around this visit. Any visits that this went to will now have their 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "source" be the deleted visit's source. 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement update_chain(GetDB().GetCachedStatement(SQL_FROM_HERE, 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "UPDATE visits SET from_visit=? WHERE from_visit=?")); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update_chain.BindInt64(0, visit.referring_visit); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update_chain.BindInt64(1, visit.visit_id); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!update_chain.Run()) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now delete the actual visit. 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement del(GetDB().GetCachedStatement(SQL_FROM_HERE, 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "DELETE FROM visits WHERE id=?")); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) del.BindInt64(0, visit.visit_id); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!del.Run()) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try to delete the entry in visit_source table as well. 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the visit was browsed, there is no corresponding entry in visit_source 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // table, and nothing will be deleted. 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) del.Assign(GetDB().GetCachedStatement(SQL_FROM_HERE, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "DELETE FROM visit_source WHERE id=?")); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) del.BindInt64(0, visit.visit_id); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) del.Run(); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetRowForVisit(VisitID visit_id, VisitRow* out_visit) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits WHERE id=?")); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, visit_id); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.Step()) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FillVisitRow(statement, out_visit); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We got a different visit than we asked for, something is wrong. 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(visit_id, out_visit->visit_id); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_id != out_visit->visit_id) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::UpdateVisitRow(const VisitRow& visit) { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't store inconsistent data to the database. 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(visit.visit_id, visit.referring_visit); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit.visit_id == visit.referring_visit) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "UPDATE visits SET " 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "url=?,visit_time=?,from_visit=?,transition=?,segment_id=?,is_indexed=?," 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "visit_duration=? WHERE id=?")); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, visit.url_id); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(1, visit.visit_time.ToInternalValue()); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(2, visit.referring_visit); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(3, visit.transition); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(4, visit.segment_id); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(5, visit.is_indexed); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(6, visit.visit_duration.ToInternalValue()); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(7, visit.visit_id); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return statement.Run(); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetVisitsForURL(URLID url_id, VisitVector* visits) { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->clear(); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "FROM visits " 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE url=? " 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ORDER BY visit_time ASC")); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, url_id); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FillVisitVector(statement, visits); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetIndexedVisitsForURL(URLID url_id, VisitVector* visits) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->clear(); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "FROM visits " 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE url=? AND is_indexed=1")); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, url_id); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FillVisitVector(statement, visits); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VisitDatabase::GetVisitsForTimes(const std::vector<base::Time>& times, 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VisitVector* visits) { 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) visits->clear(); 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::vector<base::Time>::const_iterator it = times.begin(); 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != times.end(); ++it) { 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "WHERE visit_time == ?")); 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement.BindInt64(0, it->ToInternalValue()); 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!FillVisitVector(statement, visits)) 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetAllVisitsInRange(base::Time begin_time, 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time end_time, 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_results, 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits) { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->clear(); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE visit_time >= ? AND visit_time < ?" 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ORDER BY visit_time LIMIT ?")); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See GetVisibleVisitsInRange for more info on how these times are bound. 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 end = end_time.ToInternalValue(); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, begin_time.ToInternalValue()); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(1, end ? end : std::numeric_limits<int64>::max()); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(2, 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_results ? max_results : std::numeric_limits<int64>::max()); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FillVisitVector(statement, visits); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetVisitsInRangeForTransition( 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time begin_time, 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time end_time, 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_results, 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition, 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits) { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(visits); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->clear(); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE visit_time >= ? AND visit_time < ? " 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND (transition & ?) == ?" 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ORDER BY visit_time LIMIT ?")); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See GetVisibleVisitsInRange for more info on how these times are bound. 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 end = end_time.ToInternalValue(); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, begin_time.ToInternalValue()); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(1, end ? end : std::numeric_limits<int64>::max()); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(2, content::PAGE_TRANSITION_CORE_MASK); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(3, transition); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(4, 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_results ? max_results : std::numeric_limits<int64>::max()); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FillVisitVector(statement, visits); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool VisitDatabase::GetVisibleVisitsInRange(const QueryOptions& options, 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits) { 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->clear(); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The visit_time values can be duplicated in a redirect chain, so we sort 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by id too, to ensure a consistent ordering just in case. 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE visit_time >= ? AND visit_time < ? " 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND (transition & ?) != 0 " // CHAIN_END 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND (transition & ?) NOT IN (?, ?, ?) " // NO SUBFRAME or 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // KEYWORD_GENERATED 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ORDER BY visit_time DESC, id DESC")); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement.BindInt64(0, options.EffectiveBeginTime()); 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement.BindInt64(1, options.EffectiveEndTime()); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(2, content::PAGE_TRANSITION_CHAIN_END); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(3, content::PAGE_TRANSITION_CORE_MASK); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(4, content::PAGE_TRANSITION_AUTO_SUBFRAME); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(5, content::PAGE_TRANSITION_MANUAL_SUBFRAME); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(6, content::PAGE_TRANSITION_KEYWORD_GENERATED); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<URLID> found_urls; 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Keeps track of the day that |found_urls| is holding the URLs for, in order 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to handle removing per-day duplicates. 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time found_urls_midnight; 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (statement.Step()) { 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FillVisitRow(statement, &visit); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (options.duplicate_policy != QueryOptions::KEEP_ALL_DUPLICATES) { 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (options.duplicate_policy == QueryOptions::REMOVE_DUPLICATES_PER_DAY && 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) found_urls_midnight != visit.visit_time.LocalMidnight()) { 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) found_urls.clear(); 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) found_urls_midnight = visit.visit_time.LocalMidnight(); 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Make sure the URL this visit corresponds to is unique. 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (found_urls.find(visit.url_id) != found_urls.end()) 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) found_urls.insert(visit.url_id); 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (static_cast<int>(visits->size()) >= options.EffectiveMaxCount()) 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) visits->push_back(visit); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitDatabase::GetDirectVisitsDuringTimes(const VisitFilter& time_filter, 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_results, 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits) { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->clear(); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (max_results) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->reserve(max_results); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (VisitFilter::TimeVector::const_iterator it = time_filter.times().begin(); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != time_filter.times().end(); ++it) { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE visit_time >= ? AND visit_time < ? " 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND (transition & ?) != 0 " // CHAIN_START 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND (transition & ?) IN (?, ?) " // TYPED or AUTO_BOOKMARK only 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ORDER BY visit_time DESC, id DESC")); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, it->first.ToInternalValue()); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(1, it->second.ToInternalValue()); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(2, content::PAGE_TRANSITION_CHAIN_START); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(3, content::PAGE_TRANSITION_CORE_MASK); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(4, content::PAGE_TRANSITION_TYPED); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(5, content::PAGE_TRANSITION_AUTO_BOOKMARK); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (statement.Step()) { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow visit; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FillVisitRow(statement, &visit); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->push_back(visit); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (max_results > 0 && static_cast<int>(visits->size()) >= max_results) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VisitID VisitDatabase::GetMostRecentVisitForURL(URLID url_id, 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow* visit_row) { 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The visit_time values can be duplicated in a redirect chain, so we sort 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by id too, to ensure a consistent ordering just in case. 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE url=? " 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ORDER BY visit_time DESC, id DESC " 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "LIMIT 1")); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, url_id); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.Step()) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; // No visits for this URL. 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visit_row) { 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FillVisitRow(statement, visit_row); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return visit_row->visit_id; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return statement.ColumnInt64(0); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetMostRecentVisitsForURL(URLID url_id, 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_results, 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitVector* visits) { 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visits->clear(); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The visit_time values can be duplicated in a redirect chain, so we sort 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by id too, to ensure a consistent ordering just in case. 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT" HISTORY_VISIT_ROW_FIELDS 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "FROM visits " 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE url=? " 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ORDER BY visit_time DESC, id DESC " 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "LIMIT ?")); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, url_id); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(1, max_results); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FillVisitVector(statement, visits); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetRedirectFromVisit(VisitID from_visit, 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID* to_visit, 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL* to_url) { 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT v.id,u.url " 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "FROM visits v JOIN urls u ON v.url = u.id " 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE v.from_visit = ? " 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND (v.transition & ?) != 0")); // IS_REDIRECT_MASK 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, from_visit); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(1, content::PAGE_TRANSITION_IS_REDIRECT_MASK); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.Step()) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // No redirect from this visit. (Or SQL error) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (to_visit) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *to_visit = statement.ColumnInt64(0); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (to_url) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *to_url = GURL(statement.ColumnString(1)); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetRedirectToVisit(VisitID to_visit, 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitID* from_visit, 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL* from_url) { 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitRow row; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetRowForVisit(to_visit, &row)) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (from_visit) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *from_visit = row.referring_visit; 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (from_url) { 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT u.url " 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "FROM visits v JOIN urls u ON v.url = u.id " 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE v.id = ?")); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, row.referring_visit); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.Step()) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *from_url = GURL(statement.ColumnString(0)); 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetVisibleVisitCountToHost(const GURL& url, 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* count, 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time* first_visit) { 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!url.SchemeIs(chrome::kHttpScheme) && !url.SchemeIs(chrome::kHttpsScheme)) 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to search for URLs with a matching host/port. One way to query for 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this is to use the LIKE operator, eg 'url LIKE http://google.com/%'. This 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is inefficient though in that it doesn't use the index and each entry must 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be visited. The same query can be executed by using >= and < operator. 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The query becomes: 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 'url >= http://google.com/' and url < http://google.com0'. 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0 is used as it is one character greater than '/'. 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string host_query_min = url.GetOrigin().spec(); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (host_query_min.empty()) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We also want to restrict ourselves to main frame navigations that are not 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in the middle of redirect chains, hence the transition checks. 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT MIN(v.visit_time), COUNT(*) " 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "FROM visits v INNER JOIN urls u ON v.url = u.id " 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE u.url >= ? AND u.url < ? " 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND (transition & ?) != 0 " 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND (transition & ?) NOT IN (?, ?, ?)")); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindString(0, host_query_min); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindString(1, 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_query_min.substr(0, host_query_min.size() - 1) + '0'); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(2, content::PAGE_TRANSITION_CHAIN_END); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(3, content::PAGE_TRANSITION_CORE_MASK); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(4, content::PAGE_TRANSITION_AUTO_SUBFRAME); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(5, content::PAGE_TRANSITION_MANUAL_SUBFRAME); 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt(6, content::PAGE_TRANSITION_KEYWORD_GENERATED); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.Step()) { 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We've never been to this page before. 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *count = 0; 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.Succeeded()) 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *first_visit = base::Time::FromInternalValue(statement.ColumnInt64(0)); 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *count = statement.ColumnInt(1); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::GetStartDate(base::Time* first_visit) { 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT MIN(visit_time) FROM visits WHERE visit_time != 0")); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.Step() || statement.ColumnInt64(0) == 0) { 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *first_visit = base::Time::Now(); 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *first_visit = base::Time::FromInternalValue(statement.ColumnInt64(0)); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitDatabase::GetVisitsSource(const VisitVector& visits, 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitSourceMap* sources) { 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(sources); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sources->clear(); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We query the source in batch. Here defines the batch size. 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t batch_size = 500; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t visits_size = visits.size(); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t start_index = 0, end_index = 0; 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (end_index < visits_size) { 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_index = end_index; 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) end_index = end_index + batch_size < visits_size ? end_index + batch_size 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : visits_size; 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compose the sql statement with a list of ids. 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string sql = "SELECT id,source FROM visit_source "; 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql.append("WHERE id IN ("); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Append all the ids in the statement. 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = start_index; j < end_index; j++) { 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (j != start_index) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql.push_back(','); 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql.append(base::Int64ToString(visits[j].visit_id)); 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql.append(") ORDER BY id"); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetUniqueStatement(sql.c_str())); 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the source entries out of the query result. 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (statement.Step()) { 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<VisitID, VisitSource> source_entry(statement.ColumnInt64(0), 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<VisitSource>(statement.ColumnInt(1))); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sources->insert(source_entry); 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VisitDatabase::MigrateVisitsWithoutDuration() { 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().DoesTableExist("visits")) { 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << " Visits table should exist before migration"; 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().DoesColumnExist("visits", "visit_duration")) { 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Old versions don't have the visit_duration column, we modify the table 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to add that field. 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetDB().Execute("ALTER TABLE visits " 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ADD COLUMN visit_duration INTEGER DEFAULT 0 NOT NULL")) 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void VisitDatabase::GetBriefVisitInfoOfMostRecentVisits( 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_visits, 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<BriefVisitInfo>* result_vector) { 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_vector->clear(); 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(GetDB().GetUniqueStatement( 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT url,visit_time,transition FROM visits " 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ORDER BY id DESC LIMIT ?")); 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, max_visits); 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.is_valid()) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (statement.Step()) { 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BriefVisitInfo info; 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.url_id = statement.ColumnInt64(0); 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.time = base::Time::FromInternalValue(statement.ColumnInt64(1)); 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.transition = content::PageTransitionFromInt(statement.ColumnInt(2)); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_vector->push_back(info); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace history 617