| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <algorithm> | 5 #include <algorithm> |
| 6 #include <limits> | 6 #include <limits> |
| 7 #include <map> | 7 #include <map> |
| 8 #include <set> | 8 #include <set> |
| 9 | 9 |
| 10 #include "chrome/browser/history/visit_database.h" | 10 #include "chrome/browser/history/visit_database.h" |
| 11 #include "chrome/browser/history/visit_log.h" |
| 11 | 12 |
| 12 #include "chrome/browser/history/url_database.h" | 13 #include "chrome/browser/history/url_database.h" |
| 13 #include "chrome/common/page_transition_types.h" | 14 #include "chrome/common/page_transition_types.h" |
| 14 #include "chrome/common/url_constants.h" | 15 #include "chrome/common/url_constants.h" |
| 15 | 16 |
| 16 using base::Time; | 17 using base::Time; |
| 17 | 18 |
| 18 // Rows, in order, of the visit table. | 19 // Rows, in order, of the visit table. |
| 19 #define HISTORY_VISIT_ROW_FIELDS \ | 20 #define HISTORY_VISIT_ROW_FIELDS \ |
| 20 " id,url,visit_time,from_visit,transition,segment_id,is_indexed " | 21 " id,url,visit_time,from_visit,transition,segment_id,is_indexed " |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 "VALUES (?,?,?,?,?,?)"); | 109 "VALUES (?,?,?,?,?,?)"); |
| 109 if (!statement.is_valid()) | 110 if (!statement.is_valid()) |
| 110 return 0; | 111 return 0; |
| 111 | 112 |
| 112 statement->bind_int64(0, visit->url_id); | 113 statement->bind_int64(0, visit->url_id); |
| 113 statement->bind_int64(1, visit->visit_time.ToInternalValue()); | 114 statement->bind_int64(1, visit->visit_time.ToInternalValue()); |
| 114 statement->bind_int64(2, visit->referring_visit); | 115 statement->bind_int64(2, visit->referring_visit); |
| 115 statement->bind_int64(3, visit->transition); | 116 statement->bind_int64(3, visit->transition); |
| 116 statement->bind_int64(4, visit->segment_id); | 117 statement->bind_int64(4, visit->segment_id); |
| 117 statement->bind_int64(5, visit->is_indexed); | 118 statement->bind_int64(5, visit->is_indexed); |
| 119 AddEventToVisitLog(VisitLog::ADD_VISIT); |
| 118 if (statement->step() != SQLITE_DONE) | 120 if (statement->step() != SQLITE_DONE) |
| 119 return 0; | 121 return 0; |
| 120 | 122 |
| 121 visit->visit_id = sqlite3_last_insert_rowid(GetDB()); | 123 visit->visit_id = sqlite3_last_insert_rowid(GetDB()); |
| 122 return visit->visit_id; | 124 return visit->visit_id; |
| 123 } | 125 } |
| 124 | 126 |
| 125 void VisitDatabase::DeleteVisit(const VisitRow& visit) { | 127 void VisitDatabase::DeleteVisit(const VisitRow& visit) { |
| 126 // Patch around this visit. Any visits that this went to will now have their | 128 // Patch around this visit. Any visits that this went to will now have their |
| 127 // "source" be the deleted visit's source. | 129 // "source" be the deleted visit's source. |
| 128 SQLITE_UNIQUE_STATEMENT(update_chain, GetStatementCache(), | 130 SQLITE_UNIQUE_STATEMENT(update_chain, GetStatementCache(), |
| 129 "UPDATE visits SET from_visit=? " | 131 "UPDATE visits SET from_visit=? " |
| 130 "WHERE from_visit=?"); | 132 "WHERE from_visit=?"); |
| 131 if (!update_chain.is_valid()) | 133 if (!update_chain.is_valid()) |
| 132 return; | 134 return; |
| 133 update_chain->bind_int64(0, visit.referring_visit); | 135 update_chain->bind_int64(0, visit.referring_visit); |
| 134 update_chain->bind_int64(1, visit.visit_id); | 136 update_chain->bind_int64(1, visit.visit_id); |
| 137 AddEventToVisitLog(VisitLog::UPDATE_VISIT); |
| 135 update_chain->step(); | 138 update_chain->step(); |
| 136 | 139 |
| 137 // Now delete the actual visit. | 140 // Now delete the actual visit. |
| 138 SQLITE_UNIQUE_STATEMENT(del, GetStatementCache(), | 141 SQLITE_UNIQUE_STATEMENT(del, GetStatementCache(), |
| 139 "DELETE FROM visits WHERE id=?"); | 142 "DELETE FROM visits WHERE id=?"); |
| 140 if (!del.is_valid()) | 143 if (!del.is_valid()) |
| 141 return; | 144 return; |
| 142 del->bind_int64(0, visit.visit_id); | 145 del->bind_int64(0, visit.visit_id); |
| 146 AddEventToVisitLog(VisitLog::DELETE_VISIT); |
| 143 del->step(); | 147 del->step(); |
| 144 } | 148 } |
| 145 | 149 |
| 146 bool VisitDatabase::GetRowForVisit(VisitID visit_id, VisitRow* out_visit) { | 150 bool VisitDatabase::GetRowForVisit(VisitID visit_id, VisitRow* out_visit) { |
| 147 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), | 151 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), |
| 148 "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits WHERE id=?"); | 152 "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits WHERE id=?"); |
| 149 if (!statement.is_valid()) | 153 if (!statement.is_valid()) |
| 150 return false; | 154 return false; |
| 151 | 155 |
| 152 statement->bind_int64(0, visit_id); | 156 statement->bind_int64(0, visit_id); |
| 157 AddEventToVisitLog(VisitLog::SELECT_VISIT); |
| 153 if (statement->step() != SQLITE_ROW) | 158 if (statement->step() != SQLITE_ROW) |
| 154 return false; | 159 return false; |
| 155 | 160 |
| 156 FillVisitRow(*statement, out_visit); | 161 FillVisitRow(*statement, out_visit); |
| 157 return true; | 162 return true; |
| 158 } | 163 } |
| 159 | 164 |
| 160 bool VisitDatabase::UpdateVisitRow(const VisitRow& visit) { | 165 bool VisitDatabase::UpdateVisitRow(const VisitRow& visit) { |
| 161 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), | 166 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), |
| 162 "UPDATE visits SET " | 167 "UPDATE visits SET " |
| 163 "url=?,visit_time=?,from_visit=?,transition=?,segment_id=?,is_indexed=? " | 168 "url=?,visit_time=?,from_visit=?,transition=?,segment_id=?,is_indexed=? " |
| 164 "WHERE id=?"); | 169 "WHERE id=?"); |
| 165 if (!statement.is_valid()) | 170 if (!statement.is_valid()) |
| 166 return false; | 171 return false; |
| 167 | 172 |
| 168 statement->bind_int64(0, visit.url_id); | 173 statement->bind_int64(0, visit.url_id); |
| 169 statement->bind_int64(1, visit.visit_time.ToInternalValue()); | 174 statement->bind_int64(1, visit.visit_time.ToInternalValue()); |
| 170 statement->bind_int64(2, visit.referring_visit); | 175 statement->bind_int64(2, visit.referring_visit); |
| 171 statement->bind_int64(3, visit.transition); | 176 statement->bind_int64(3, visit.transition); |
| 172 statement->bind_int64(4, visit.segment_id); | 177 statement->bind_int64(4, visit.segment_id); |
| 173 statement->bind_int64(5, visit.is_indexed); | 178 statement->bind_int64(5, visit.is_indexed); |
| 174 statement->bind_int64(6, visit.visit_id); | 179 statement->bind_int64(6, visit.visit_id); |
| 180 AddEventToVisitLog(VisitLog::UPDATE_VISIT); |
| 175 return statement->step() == SQLITE_DONE; | 181 return statement->step() == SQLITE_DONE; |
| 176 } | 182 } |
| 177 | 183 |
| 178 bool VisitDatabase::GetVisitsForURL(URLID url_id, VisitVector* visits) { | 184 bool VisitDatabase::GetVisitsForURL(URLID url_id, VisitVector* visits) { |
| 179 visits->clear(); | 185 visits->clear(); |
| 180 | 186 |
| 181 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), | 187 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), |
| 182 "SELECT" HISTORY_VISIT_ROW_FIELDS | 188 "SELECT" HISTORY_VISIT_ROW_FIELDS |
| 183 "FROM visits " | 189 "FROM visits " |
| 184 "WHERE url=? " | 190 "WHERE url=? " |
| 185 "ORDER BY visit_time ASC"); | 191 "ORDER BY visit_time ASC"); |
| 186 if (!statement.is_valid()) | 192 if (!statement.is_valid()) |
| 187 return false; | 193 return false; |
| 188 | 194 |
| 189 statement->bind_int64(0, url_id); | 195 statement->bind_int64(0, url_id); |
| 196 AddEventToVisitLog(VisitLog::SELECT_VISIT); |
| 190 FillVisitVector(*statement, visits); | 197 FillVisitVector(*statement, visits); |
| 191 return true; | 198 return true; |
| 192 } | 199 } |
| 193 | 200 |
| 194 void VisitDatabase::GetAllVisitsInRange(Time begin_time, Time end_time, | 201 void VisitDatabase::GetAllVisitsInRange(Time begin_time, Time end_time, |
| 195 int max_results, | 202 int max_results, |
| 196 VisitVector* visits) { | 203 VisitVector* visits) { |
| 197 visits->clear(); | 204 visits->clear(); |
| 198 | 205 |
| 199 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), | 206 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), |
| 200 "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " | 207 "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " |
| 201 "WHERE visit_time >= ? AND visit_time < ?" | 208 "WHERE visit_time >= ? AND visit_time < ?" |
| 202 "ORDER BY visit_time LIMIT ?"); | 209 "ORDER BY visit_time LIMIT ?"); |
| 203 if (!statement.is_valid()) | 210 if (!statement.is_valid()) |
| 204 return; | 211 return; |
| 205 | 212 |
| 206 // See GetVisibleVisitsInRange for more info on how these times are bound. | 213 // See GetVisibleVisitsInRange for more info on how these times are bound. |
| 207 int64 end = end_time.ToInternalValue(); | 214 int64 end = end_time.ToInternalValue(); |
| 208 statement->bind_int64(0, begin_time.ToInternalValue()); | 215 statement->bind_int64(0, begin_time.ToInternalValue()); |
| 209 statement->bind_int64(1, end ? end : std::numeric_limits<int64>::max()); | 216 statement->bind_int64(1, end ? end : std::numeric_limits<int64>::max()); |
| 210 statement->bind_int64(2, | 217 statement->bind_int64(2, |
| 211 max_results ? max_results : std::numeric_limits<int64>::max()); | 218 max_results ? max_results : std::numeric_limits<int64>::max()); |
| 212 | 219 |
| 220 AddEventToVisitLog(VisitLog::SELECT_VISIT); |
| 213 FillVisitVector(*statement, visits); | 221 FillVisitVector(*statement, visits); |
| 214 } | 222 } |
| 215 | 223 |
| 216 void VisitDatabase::GetVisitsInRangeForTransition( | 224 void VisitDatabase::GetVisitsInRangeForTransition( |
| 217 Time begin_time, | 225 Time begin_time, |
| 218 Time end_time, | 226 Time end_time, |
| 219 int max_results, | 227 int max_results, |
| 220 PageTransition::Type transition, | 228 PageTransition::Type transition, |
| 221 VisitVector* visits) { | 229 VisitVector* visits) { |
| 222 DCHECK(visits); | 230 DCHECK(visits); |
| 223 visits->clear(); | 231 visits->clear(); |
| 224 | 232 |
| 225 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), | 233 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), |
| 226 "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " | 234 "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " |
| 227 "WHERE visit_time >= ? AND visit_time < ? " | 235 "WHERE visit_time >= ? AND visit_time < ? " |
| 228 "AND (transition & ?) == ?" | 236 "AND (transition & ?) == ?" |
| 229 "ORDER BY visit_time LIMIT ?"); | 237 "ORDER BY visit_time LIMIT ?"); |
| 230 if (!statement.is_valid()) | 238 if (!statement.is_valid()) |
| 231 return; | 239 return; |
| 232 | 240 |
| 233 // See GetVisibleVisitsInRange for more info on how these times are bound. | 241 // See GetVisibleVisitsInRange for more info on how these times are bound. |
| 234 int64 end = end_time.ToInternalValue(); | 242 int64 end = end_time.ToInternalValue(); |
| 235 statement->bind_int64(0, begin_time.ToInternalValue()); | 243 statement->bind_int64(0, begin_time.ToInternalValue()); |
| 236 statement->bind_int64(1, end ? end : std::numeric_limits<int64>::max()); | 244 statement->bind_int64(1, end ? end : std::numeric_limits<int64>::max()); |
| 237 statement->bind_int(2, PageTransition::CORE_MASK); | 245 statement->bind_int(2, PageTransition::CORE_MASK); |
| 238 statement->bind_int(3, transition); | 246 statement->bind_int(3, transition); |
| 239 statement->bind_int64(4, | 247 statement->bind_int64(4, |
| 240 max_results ? max_results : std::numeric_limits<int64>::max()); | 248 max_results ? max_results : std::numeric_limits<int64>::max()); |
| 241 | 249 |
| 250 AddEventToVisitLog(VisitLog::SELECT_VISIT); |
| 242 FillVisitVector(*statement, visits); | 251 FillVisitVector(*statement, visits); |
| 243 } | 252 } |
| 244 | 253 |
| 245 void VisitDatabase::GetVisibleVisitsInRange(Time begin_time, Time end_time, | 254 void VisitDatabase::GetVisibleVisitsInRange(Time begin_time, Time end_time, |
| 246 bool most_recent_visit_only, | 255 bool most_recent_visit_only, |
| 247 int max_count, | 256 int max_count, |
| 248 VisitVector* visits) { | 257 VisitVector* visits) { |
| 249 visits->clear(); | 258 visits->clear(); |
| 250 // The visit_time values can be duplicated in a redirect chain, so we sort | 259 // The visit_time values can be duplicated in a redirect chain, so we sort |
| 251 // by id too, to ensure a consistent ordering just in case. | 260 // by id too, to ensure a consistent ordering just in case. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 264 // same amount of work as just doing a query for everything with no qualifier. | 273 // same amount of work as just doing a query for everything with no qualifier. |
| 265 int64 end = end_time.ToInternalValue(); | 274 int64 end = end_time.ToInternalValue(); |
| 266 statement->bind_int64(0, begin_time.ToInternalValue()); | 275 statement->bind_int64(0, begin_time.ToInternalValue()); |
| 267 statement->bind_int64(1, end ? end : std::numeric_limits<int64>::max()); | 276 statement->bind_int64(1, end ? end : std::numeric_limits<int64>::max()); |
| 268 statement->bind_int(2, PageTransition::CHAIN_END); | 277 statement->bind_int(2, PageTransition::CHAIN_END); |
| 269 statement->bind_int(3, PageTransition::CORE_MASK); | 278 statement->bind_int(3, PageTransition::CORE_MASK); |
| 270 statement->bind_int(4, PageTransition::AUTO_SUBFRAME); | 279 statement->bind_int(4, PageTransition::AUTO_SUBFRAME); |
| 271 statement->bind_int(5, PageTransition::MANUAL_SUBFRAME); | 280 statement->bind_int(5, PageTransition::MANUAL_SUBFRAME); |
| 272 statement->bind_int(6, PageTransition::KEYWORD_GENERATED); | 281 statement->bind_int(6, PageTransition::KEYWORD_GENERATED); |
| 273 | 282 |
| 283 AddEventToVisitLog(VisitLog::SELECT_VISIT); |
| 274 std::set<URLID> found_urls; | 284 std::set<URLID> found_urls; |
| 275 while (statement->step() == SQLITE_ROW) { | 285 while (statement->step() == SQLITE_ROW) { |
| 276 VisitRow visit; | 286 VisitRow visit; |
| 277 FillVisitRow(*statement, &visit); | 287 FillVisitRow(*statement, &visit); |
| 278 if (most_recent_visit_only) { | 288 if (most_recent_visit_only) { |
| 279 // Make sure the URL this visit corresponds to is unique if required. | 289 // Make sure the URL this visit corresponds to is unique if required. |
| 280 if (found_urls.find(visit.url_id) != found_urls.end()) | 290 if (found_urls.find(visit.url_id) != found_urls.end()) |
| 281 continue; | 291 continue; |
| 282 found_urls.insert(visit.url_id); | 292 found_urls.insert(visit.url_id); |
| 283 } | 293 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 294 // by id too, to ensure a consistent ordering just in case. | 304 // by id too, to ensure a consistent ordering just in case. |
| 295 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), | 305 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), |
| 296 "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " | 306 "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits " |
| 297 "WHERE url=? " | 307 "WHERE url=? " |
| 298 "ORDER BY visit_time DESC, id DESC " | 308 "ORDER BY visit_time DESC, id DESC " |
| 299 "LIMIT 1"); | 309 "LIMIT 1"); |
| 300 if (!statement.is_valid()) | 310 if (!statement.is_valid()) |
| 301 return 0; | 311 return 0; |
| 302 | 312 |
| 303 statement->bind_int64(0, url_id); | 313 statement->bind_int64(0, url_id); |
| 314 AddEventToVisitLog(VisitLog::SELECT_VISIT); |
| 304 if (statement->step() != SQLITE_ROW) | 315 if (statement->step() != SQLITE_ROW) |
| 305 return 0; // No visits for this URL. | 316 return 0; // No visits for this URL. |
| 306 | 317 |
| 307 if (visit_row) { | 318 if (visit_row) { |
| 308 FillVisitRow(*statement, visit_row); | 319 FillVisitRow(*statement, visit_row); |
| 309 return visit_row->visit_id; | 320 return visit_row->visit_id; |
| 310 } | 321 } |
| 311 return statement->column_int64(0); | 322 return statement->column_int64(0); |
| 312 } | 323 } |
| 313 | 324 |
| 314 bool VisitDatabase::GetMostRecentVisitsForURL(URLID url_id, | 325 bool VisitDatabase::GetMostRecentVisitsForURL(URLID url_id, |
| 315 int max_results, | 326 int max_results, |
| 316 VisitVector* visits) { | 327 VisitVector* visits) { |
| 317 visits->clear(); | 328 visits->clear(); |
| 318 | 329 |
| 319 // The visit_time values can be duplicated in a redirect chain, so we sort | 330 // The visit_time values can be duplicated in a redirect chain, so we sort |
| 320 // by id too, to ensure a consistent ordering just in case. | 331 // by id too, to ensure a consistent ordering just in case. |
| 321 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), | 332 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), |
| 322 "SELECT" HISTORY_VISIT_ROW_FIELDS | 333 "SELECT" HISTORY_VISIT_ROW_FIELDS |
| 323 "FROM visits " | 334 "FROM visits " |
| 324 "WHERE url=? " | 335 "WHERE url=? " |
| 325 "ORDER BY visit_time DESC, id DESC " | 336 "ORDER BY visit_time DESC, id DESC " |
| 326 "LIMIT ?"); | 337 "LIMIT ?"); |
| 327 if (!statement.is_valid()) | 338 if (!statement.is_valid()) |
| 328 return false; | 339 return false; |
| 329 | 340 |
| 330 statement->bind_int64(0, url_id); | 341 statement->bind_int64(0, url_id); |
| 331 statement->bind_int(1, max_results); | 342 statement->bind_int(1, max_results); |
| 343 AddEventToVisitLog(VisitLog::SELECT_VISIT); |
| 332 FillVisitVector(*statement, visits); | 344 FillVisitVector(*statement, visits); |
| 333 return true; | 345 return true; |
| 334 } | 346 } |
| 335 | 347 |
| 336 bool VisitDatabase::GetRedirectFromVisit(VisitID from_visit, | 348 bool VisitDatabase::GetRedirectFromVisit(VisitID from_visit, |
| 337 VisitID* to_visit, | 349 VisitID* to_visit, |
| 338 GURL* to_url) { | 350 GURL* to_url) { |
| 339 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), | 351 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), |
| 340 "SELECT v.id,u.url " | 352 "SELECT v.id,u.url " |
| 341 "FROM visits v JOIN urls u ON v.url = u.id " | 353 "FROM visits v JOIN urls u ON v.url = u.id " |
| 342 "WHERE v.from_visit = ? " | 354 "WHERE v.from_visit = ? " |
| 343 "AND (v.transition & ?) != 0"); // IS_REDIRECT_MASK | 355 "AND (v.transition & ?) != 0"); // IS_REDIRECT_MASK |
| 344 if (!statement.is_valid()) | 356 if (!statement.is_valid()) |
| 345 return false; | 357 return false; |
| 346 | 358 |
| 347 statement->bind_int64(0, from_visit); | 359 statement->bind_int64(0, from_visit); |
| 348 statement->bind_int(1, PageTransition::IS_REDIRECT_MASK); | 360 statement->bind_int(1, PageTransition::IS_REDIRECT_MASK); |
| 349 | 361 |
| 362 AddEventToVisitLog(VisitLog::SELECT_VISIT); |
| 350 if (statement->step() != SQLITE_ROW) | 363 if (statement->step() != SQLITE_ROW) |
| 351 return false; // No redirect from this visit. | 364 return false; // No redirect from this visit. |
| 352 if (to_visit) | 365 if (to_visit) |
| 353 *to_visit = statement->column_int64(0); | 366 *to_visit = statement->column_int64(0); |
| 354 if (to_url) | 367 if (to_url) |
| 355 *to_url = GURL(statement->column_string(1)); | 368 *to_url = GURL(statement->column_string(1)); |
| 356 return true; | 369 return true; |
| 357 } | 370 } |
| 358 | 371 |
| 359 bool VisitDatabase::GetRedirectToVisit(VisitID to_visit, | 372 bool VisitDatabase::GetRedirectToVisit(VisitID to_visit, |
| 360 VisitID* from_visit, | 373 VisitID* from_visit, |
| 361 GURL* from_url) { | 374 GURL* from_url) { |
| 362 VisitRow row; | 375 VisitRow row; |
| 363 if (!GetRowForVisit(to_visit, &row)) | 376 if (!GetRowForVisit(to_visit, &row)) |
| 364 return false; | 377 return false; |
| 365 | 378 |
| 366 if (from_visit) | 379 if (from_visit) |
| 367 *from_visit = row.referring_visit; | 380 *from_visit = row.referring_visit; |
| 368 | 381 |
| 369 if (from_url) { | 382 if (from_url) { |
| 370 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), | 383 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), |
| 371 "SELECT u.url " | 384 "SELECT u.url " |
| 372 "FROM visits v JOIN urls u ON v.url = u.id " | 385 "FROM visits v JOIN urls u ON v.url = u.id " |
| 373 "WHERE v.id = ?"); | 386 "WHERE v.id = ?"); |
| 374 statement->bind_int64(0, row.referring_visit); | 387 statement->bind_int64(0, row.referring_visit); |
| 375 | 388 |
| 389 AddEventToVisitLog(VisitLog::SELECT_VISIT); |
| 376 if (statement->step() != SQLITE_ROW) | 390 if (statement->step() != SQLITE_ROW) |
| 377 return false; | 391 return false; |
| 378 | 392 |
| 379 *from_url = GURL(statement->column_string(0)); | 393 *from_url = GURL(statement->column_string(0)); |
| 380 } | 394 } |
| 381 return true; | 395 return true; |
| 382 } | 396 } |
| 383 | 397 |
| 384 bool VisitDatabase::GetVisitCountToHost(const GURL& url, | 398 bool VisitDatabase::GetVisitCountToHost(const GURL& url, |
| 385 int* count, | 399 int* count, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 406 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), | 420 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), |
| 407 "SELECT MIN(v.visit_time), COUNT(*) " | 421 "SELECT MIN(v.visit_time), COUNT(*) " |
| 408 "FROM visits v INNER JOIN urls u ON v.url = u.id " | 422 "FROM visits v INNER JOIN urls u ON v.url = u.id " |
| 409 "WHERE (u.url >= ? AND u.url < ?)"); | 423 "WHERE (u.url >= ? AND u.url < ?)"); |
| 410 if (!statement.is_valid()) | 424 if (!statement.is_valid()) |
| 411 return false; | 425 return false; |
| 412 | 426 |
| 413 statement->bind_string(0, host_query_min); | 427 statement->bind_string(0, host_query_min); |
| 414 statement->bind_string(1, host_query_max); | 428 statement->bind_string(1, host_query_max); |
| 415 | 429 |
| 430 AddEventToVisitLog(VisitLog::SELECT_VISIT); |
| 416 if (statement->step() != SQLITE_ROW) { | 431 if (statement->step() != SQLITE_ROW) { |
| 417 // We've never been to this page before. | 432 // We've never been to this page before. |
| 418 *count = 0; | 433 *count = 0; |
| 419 return true; | 434 return true; |
| 420 } | 435 } |
| 421 | 436 |
| 422 *first_visit = Time::FromInternalValue(statement->column_int64(0)); | 437 *first_visit = Time::FromInternalValue(statement->column_int64(0)); |
| 423 *count = statement->column_int(1); | 438 *count = statement->column_int(1); |
| 424 return true; | 439 return true; |
| 425 } | 440 } |
| 426 | 441 |
| 427 bool VisitDatabase::GetStartDate(Time* first_visit) { | 442 bool VisitDatabase::GetStartDate(Time* first_visit) { |
| 428 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), | 443 SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), |
| 429 "SELECT MIN(visit_time) FROM visits WHERE visit_time != 0"); | 444 "SELECT MIN(visit_time) FROM visits WHERE visit_time != 0"); |
| 445 AddEventToVisitLog(VisitLog::SELECT_VISIT); |
| 430 if (!statement.is_valid() || statement->step() != SQLITE_ROW || | 446 if (!statement.is_valid() || statement->step() != SQLITE_ROW || |
| 431 statement->column_int64(0) == 0) { | 447 statement->column_int64(0) == 0) { |
| 432 *first_visit = Time::Now(); | 448 *first_visit = Time::Now(); |
| 433 return false; | 449 return false; |
| 434 } | 450 } |
| 435 *first_visit = Time::FromInternalValue(statement->column_int64(0)); | 451 *first_visit = Time::FromInternalValue(statement->column_int64(0)); |
| 436 return true; | 452 return true; |
| 437 } | 453 } |
| 438 | 454 |
| 439 } // namespace history | 455 } // namespace history |
| OLD | NEW |