Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "chrome/browser/history/visitsegment_database.h" | 5 #include "chrome/browser/history/visitsegment_database.h" |
| 6 | 6 |
| 7 #include <math.h> | 7 #include <math.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 41 } | 41 } |
| 42 | 42 |
| 43 bool VisitSegmentDatabase::InitSegmentTables() { | 43 bool VisitSegmentDatabase::InitSegmentTables() { |
| 44 // Segments table. | 44 // Segments table. |
| 45 if (!GetDB().DoesTableExist("segments")) { | 45 if (!GetDB().DoesTableExist("segments")) { |
| 46 if (!GetDB().Execute("CREATE TABLE segments (" | 46 if (!GetDB().Execute("CREATE TABLE segments (" |
| 47 "id INTEGER PRIMARY KEY," | 47 "id INTEGER PRIMARY KEY," |
| 48 "name VARCHAR," | 48 "name VARCHAR," |
| 49 "url_id INTEGER NON NULL," | 49 "url_id INTEGER NON NULL," |
| 50 "pres_index INTEGER DEFAULT -1 NOT NULL)")) { | 50 "pres_index INTEGER DEFAULT -1 NOT NULL)")) { |
| 51 NOTREACHED(); | |
| 52 return false; | 51 return false; |
| 53 } | 52 } |
| 54 | 53 |
| 55 if (!GetDB().Execute("CREATE INDEX segments_name ON segments(name)")) { | 54 if (!GetDB().Execute( |
| 56 NOTREACHED(); | 55 "CREATE INDEX segments_name ON segments(name)")) { |
| 57 return false; | 56 return false; |
| 58 } | 57 } |
| 59 } | 58 } |
| 60 | 59 |
| 61 // This was added later, so we need to try to create it even if the table | 60 // This was added later, so we need to try to create it even if the table |
| 62 // already exists. | 61 // already exists. |
| 63 if (!GetDB().Execute("CREATE INDEX IF NOT EXISTS segments_url_id ON " | 62 if (!GetDB().Execute("CREATE INDEX IF NOT EXISTS segments_url_id ON " |
| 64 "segments(url_id)")) | 63 "segments(url_id)")) |
| 65 return false; | 64 return false; |
| 66 | 65 |
| 67 // Segment usage table. | 66 // Segment usage table. |
| 68 if (!GetDB().DoesTableExist("segment_usage")) { | 67 if (!GetDB().DoesTableExist("segment_usage")) { |
| 69 if (!GetDB().Execute("CREATE TABLE segment_usage (" | 68 if (!GetDB().Execute("CREATE TABLE segment_usage (" |
| 70 "id INTEGER PRIMARY KEY," | 69 "id INTEGER PRIMARY KEY," |
| 71 "segment_id INTEGER NOT NULL," | 70 "segment_id INTEGER NOT NULL," |
| 72 "time_slot INTEGER NOT NULL," | 71 "time_slot INTEGER NOT NULL," |
| 73 "visit_count INTEGER DEFAULT 0 NOT NULL)")) { | 72 "visit_count INTEGER DEFAULT 0 NOT NULL)")) { |
| 74 NOTREACHED(); | |
| 75 return false; | 73 return false; |
| 76 } | 74 } |
| 77 if (!GetDB().Execute( | 75 if (!GetDB().Execute( |
| 78 "CREATE INDEX segment_usage_time_slot_segment_id ON " | 76 "CREATE INDEX segment_usage_time_slot_segment_id ON " |
| 79 "segment_usage(time_slot, segment_id)")) { | 77 "segment_usage(time_slot, segment_id)")) { |
| 80 NOTREACHED(); | |
| 81 return false; | 78 return false; |
| 82 } | 79 } |
| 83 } | 80 } |
| 84 | 81 |
| 85 // Added in a later version, so we always need to try to creat this index. | 82 // Added in a later version, so we always need to try to creat this index. |
| 86 if (!GetDB().Execute("CREATE INDEX IF NOT EXISTS segments_usage_seg_id " | 83 if (!GetDB().Execute("CREATE INDEX IF NOT EXISTS segments_usage_seg_id " |
| 87 "ON segment_usage(segment_id)")) | 84 "ON segment_usage(segment_id)")) |
| 88 return false; | 85 return false; |
| 89 | 86 |
| 90 // Presentation index table. | 87 // Presentation index table. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 137 r.ClearRef(); | 134 r.ClearRef(); |
| 138 r.ClearPort(); | 135 r.ClearPort(); |
| 139 | 136 |
| 140 return url.ReplaceComponents(r).spec(); | 137 return url.ReplaceComponents(r).spec(); |
| 141 } | 138 } |
| 142 | 139 |
| 143 SegmentID VisitSegmentDatabase::GetSegmentNamed( | 140 SegmentID VisitSegmentDatabase::GetSegmentNamed( |
| 144 const std::string& segment_name) { | 141 const std::string& segment_name) { |
| 145 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 142 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 146 "SELECT id FROM segments WHERE name = ?")); | 143 "SELECT id FROM segments WHERE name = ?")); |
| 147 if (!statement) | 144 statement.BindString(0, segment_name); |
| 148 return 0; | |
| 149 | 145 |
| 150 statement.BindString(0, segment_name); | |
| 151 if (statement.Step()) | 146 if (statement.Step()) |
| 152 return statement.ColumnInt64(0); | 147 return statement.ColumnInt64(0); |
| 153 return 0; | 148 return 0; |
| 154 } | 149 } |
| 155 | 150 |
| 156 bool VisitSegmentDatabase::UpdateSegmentRepresentationURL(SegmentID segment_id, | 151 bool VisitSegmentDatabase::UpdateSegmentRepresentationURL(SegmentID segment_id, |
| 157 URLID url_id) { | 152 URLID url_id) { |
| 158 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 153 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 159 "UPDATE segments SET url_id = ? WHERE id = ?")); | 154 "UPDATE segments SET url_id = ? WHERE id = ?")); |
| 160 if (!statement) | |
| 161 return false; | |
| 162 | |
| 163 statement.BindInt64(0, url_id); | 155 statement.BindInt64(0, url_id); |
| 164 statement.BindInt64(1, segment_id); | 156 statement.BindInt64(1, segment_id); |
| 157 | |
| 165 return statement.Run(); | 158 return statement.Run(); |
| 166 } | 159 } |
| 167 | 160 |
| 168 URLID VisitSegmentDatabase::GetSegmentRepresentationURL(SegmentID segment_id) { | 161 URLID VisitSegmentDatabase::GetSegmentRepresentationURL(SegmentID segment_id) { |
| 169 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 162 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 170 "SELECT url_id FROM segments WHERE id = ?")); | 163 "SELECT url_id FROM segments WHERE id = ?")); |
| 171 if (!statement) | 164 statement.BindInt64(0, segment_id); |
| 172 return 0; | |
| 173 | 165 |
| 174 statement.BindInt64(0, segment_id); | |
| 175 if (statement.Step()) | 166 if (statement.Step()) |
| 176 return statement.ColumnInt64(0); | 167 return statement.ColumnInt64(0); |
| 177 return 0; | 168 return 0; |
| 178 } | 169 } |
| 179 | 170 |
| 180 SegmentID VisitSegmentDatabase::CreateSegment(URLID url_id, | 171 SegmentID VisitSegmentDatabase::CreateSegment(URLID url_id, |
| 181 const std::string& segment_name) { | 172 const std::string& segment_name) { |
| 182 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 173 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 183 "INSERT INTO segments (name, url_id) VALUES (?,?)")); | 174 "INSERT INTO segments (name, url_id) VALUES (?,?)")); |
| 184 if (!statement) | |
| 185 return false; | |
| 186 | |
| 187 statement.BindString(0, segment_name); | 175 statement.BindString(0, segment_name); |
| 188 statement.BindInt64(1, url_id); | 176 statement.BindInt64(1, url_id); |
| 177 | |
| 189 if (statement.Run()) | 178 if (statement.Run()) |
| 190 return GetDB().GetLastInsertRowId(); | 179 return GetDB().GetLastInsertRowId(); |
| 191 return false; | 180 return 0; |
| 192 } | 181 } |
| 193 | 182 |
| 194 bool VisitSegmentDatabase::IncreaseSegmentVisitCount(SegmentID segment_id, | 183 bool VisitSegmentDatabase::IncreaseSegmentVisitCount(SegmentID segment_id, |
| 195 base::Time ts, | 184 base::Time ts, |
| 196 int amount) { | 185 int amount) { |
| 197 base::Time t = ts.LocalMidnight(); | 186 base::Time t = ts.LocalMidnight(); |
| 198 | 187 |
| 199 sql::Statement select(GetDB().GetCachedStatement(SQL_FROM_HERE, | 188 sql::Statement select(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 200 "SELECT id, visit_count FROM segment_usage " | 189 "SELECT id, visit_count FROM segment_usage " |
| 201 "WHERE time_slot = ? AND segment_id = ?")); | 190 "WHERE time_slot = ? AND segment_id = ?")); |
| 202 if (!select) | 191 select.BindInt64(0, t.ToInternalValue()); |
| 192 select.BindInt64(1, segment_id); | |
| 193 | |
| 194 if (!select.is_valid()) | |
| 203 return false; | 195 return false; |
| 204 | 196 |
| 205 select.BindInt64(0, t.ToInternalValue()); | |
| 206 select.BindInt64(1, segment_id); | |
| 207 if (select.Step()) { | 197 if (select.Step()) { |
| 208 sql::Statement update(GetDB().GetCachedStatement(SQL_FROM_HERE, | 198 sql::Statement update(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 209 "UPDATE segment_usage SET visit_count = ? WHERE id = ?")); | 199 "UPDATE segment_usage SET visit_count = ? WHERE id = ?")); |
| 210 if (!update) | |
| 211 return false; | |
| 212 | |
| 213 update.BindInt64(0, select.ColumnInt64(1) + static_cast<int64>(amount)); | 200 update.BindInt64(0, select.ColumnInt64(1) + static_cast<int64>(amount)); |
| 214 update.BindInt64(1, select.ColumnInt64(0)); | 201 update.BindInt64(1, select.ColumnInt64(0)); |
| 202 | |
| 215 return update.Run(); | 203 return update.Run(); |
| 216 | |
| 217 } else { | 204 } else { |
| 218 sql::Statement insert(GetDB().GetCachedStatement(SQL_FROM_HERE, | 205 sql::Statement insert(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 219 "INSERT INTO segment_usage " | 206 "INSERT INTO segment_usage " |
| 220 "(segment_id, time_slot, visit_count) VALUES (?, ?, ?)")); | 207 "(segment_id, time_slot, visit_count) VALUES (?, ?, ?)")); |
| 221 if (!insert) | |
| 222 return false; | |
| 223 | |
| 224 insert.BindInt64(0, segment_id); | 208 insert.BindInt64(0, segment_id); |
| 225 insert.BindInt64(1, t.ToInternalValue()); | 209 insert.BindInt64(1, t.ToInternalValue()); |
| 226 insert.BindInt64(2, static_cast<int64>(amount)); | 210 insert.BindInt64(2, static_cast<int64>(amount)); |
| 211 | |
| 227 return insert.Run(); | 212 return insert.Run(); |
| 228 } | 213 } |
| 229 } | 214 } |
| 230 | 215 |
| 231 void VisitSegmentDatabase::QuerySegmentUsage( | 216 void VisitSegmentDatabase::QuerySegmentUsage( |
| 232 base::Time from_time, | 217 base::Time from_time, |
| 233 int max_result_count, | 218 int max_result_count, |
| 234 std::vector<PageUsageData*>* results) { | 219 std::vector<PageUsageData*>* results) { |
| 235 // This function gathers the highest-ranked segments in two queries. | 220 // This function gathers the highest-ranked segments in two queries. |
| 236 // The first gathers scores for all segments. | 221 // The first gathers scores for all segments. |
| 237 // The second gathers segment data (url, title, etc.) for the highest-ranked | 222 // The second gathers segment data (url, title, etc.) for the highest-ranked |
| 238 // segments. | 223 // segments. |
| 239 // TODO(evanm): this disregards the "presentation index", which was what was | 224 // TODO(evanm): this disregards the "presentation index", which was what was |
| 240 // used to lock results into position. But the rest of our code currently | 225 // used to lock results into position. But the rest of our code currently |
| 241 // does as well. | 226 // does as well. |
| 242 | 227 |
| 243 // Gather all the segment scores. | 228 // Gather all the segment scores. |
| 244 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 229 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 245 "SELECT segment_id, time_slot, visit_count " | 230 "SELECT segment_id, time_slot, visit_count " |
| 246 "FROM segment_usage WHERE time_slot >= ? " | 231 "FROM segment_usage WHERE time_slot >= ? " |
| 247 "ORDER BY segment_id")); | 232 "ORDER BY segment_id")); |
| 248 if (!statement) { | 233 if (!statement.is_valid()) |
| 249 NOTREACHED() << GetDB().GetErrorMessage(); | |
| 250 return; | 234 return; |
| 251 } | |
| 252 | 235 |
| 253 base::Time ts = from_time.LocalMidnight(); | 236 base::Time ts = from_time.LocalMidnight(); |
| 254 statement.BindInt64(0, ts.ToInternalValue()); | 237 statement.BindInt64(0, ts.ToInternalValue()); |
| 255 | 238 |
| 256 base::Time now = base::Time::Now(); | 239 base::Time now = base::Time::Now(); |
| 257 SegmentID last_segment_id = 0; | 240 SegmentID last_segment_id = 0; |
| 258 PageUsageData* pud = NULL; | 241 PageUsageData* pud = NULL; |
| 259 float score = 0; | 242 float score = 0; |
| 260 while (statement.Step()) { | 243 while (statement.Step()) { |
| 261 SegmentID segment_id = statement.ColumnInt64(0); | 244 SegmentID segment_id = statement.ColumnInt64(0); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 297 STLDeleteContainerPointers(results->begin() + max_result_count, | 280 STLDeleteContainerPointers(results->begin() + max_result_count, |
| 298 results->end()); | 281 results->end()); |
| 299 results->resize(max_result_count); | 282 results->resize(max_result_count); |
| 300 } | 283 } |
| 301 | 284 |
| 302 // Now fetch the details about the entries we care about. | 285 // Now fetch the details about the entries we care about. |
| 303 sql::Statement statement2(GetDB().GetCachedStatement(SQL_FROM_HERE, | 286 sql::Statement statement2(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 304 "SELECT urls.url, urls.title FROM urls " | 287 "SELECT urls.url, urls.title FROM urls " |
| 305 "JOIN segments ON segments.url_id = urls.id " | 288 "JOIN segments ON segments.url_id = urls.id " |
| 306 "WHERE segments.id = ?")); | 289 "WHERE segments.id = ?")); |
| 307 if (!statement2) { | 290 |
| 308 NOTREACHED() << GetDB().GetErrorMessage(); | 291 if (!statement2.is_valid()) |
| 309 return; | 292 return; |
| 310 } | 293 |
| 311 for (size_t i = 0; i < results->size(); ++i) { | 294 for (size_t i = 0; i < results->size(); ++i) { |
| 312 PageUsageData* pud = (*results)[i]; | 295 PageUsageData* pud = (*results)[i]; |
| 313 statement2.BindInt64(0, pud->GetID()); | 296 statement2.BindInt64(0, pud->GetID()); |
| 314 if (statement2.Step()) { | 297 if (statement2.Step()) { |
| 315 pud->SetURL(GURL(statement2.ColumnString(0))); | 298 pud->SetURL(GURL(statement2.ColumnString(0))); |
| 316 pud->SetTitle(UTF8ToUTF16(statement2.ColumnString(1))); | 299 pud->SetTitle(UTF8ToUTF16(statement2.ColumnString(1))); |
| 317 } | 300 } |
| 318 statement2.Reset(); | 301 statement2.Reset(); |
| 319 } | 302 } |
| 320 } | 303 } |
| 321 | 304 |
| 322 void VisitSegmentDatabase::DeleteSegmentData(base::Time older_than) { | 305 bool VisitSegmentDatabase::DeleteSegmentData(base::Time older_than) { |
| 323 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 306 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 324 "DELETE FROM segment_usage WHERE time_slot < ?")); | 307 "DELETE FROM segment_usage WHERE time_slot < ?")); |
| 325 if (!statement) | 308 statement.BindInt64(0, older_than.LocalMidnight().ToInternalValue()); |
| 326 return; | |
| 327 | 309 |
| 328 statement.BindInt64(0, older_than.LocalMidnight().ToInternalValue()); | 310 return statement.Run(); |
| 329 if (!statement.Run()) | |
| 330 NOTREACHED(); | |
| 331 } | 311 } |
| 332 | 312 |
| 333 void VisitSegmentDatabase::SetSegmentPresentationIndex(SegmentID segment_id, | 313 bool VisitSegmentDatabase::SetSegmentPresentationIndex(SegmentID segment_id, |
| 334 int index) { | 314 int index) { |
| 335 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 315 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 336 "UPDATE segments SET pres_index = ? WHERE id = ?")); | 316 "UPDATE segments SET pres_index = ? WHERE id = ?")); |
| 337 if (!statement) | |
| 338 return; | |
| 339 | |
| 340 statement.BindInt(0, index); | 317 statement.BindInt(0, index); |
| 341 statement.BindInt64(1, segment_id); | 318 statement.BindInt64(1, segment_id); |
| 342 if (!statement.Run()) | 319 |
| 343 NOTREACHED(); | 320 bool success = statement.Run(); |
| 344 else | 321 DCHECK_EQ(1, GetDB().GetLastChangeCount()); |
| 345 DCHECK_EQ(1, GetDB().GetLastChangeCount()); | 322 return success; |
| 346 } | 323 } |
| 347 | 324 |
| 348 bool VisitSegmentDatabase::DeleteSegmentForURL(URLID url_id) { | 325 bool VisitSegmentDatabase::DeleteSegmentForURL(URLID url_id) { |
| 349 sql::Statement select(GetDB().GetCachedStatement(SQL_FROM_HERE, | 326 sql::Statement delete_seg(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 350 "SELECT id FROM segments WHERE url_id = ?")); | 327 "DELETE FROM segments WHERE id IN " |
| 351 if (!select) | 328 "(SELECT id FROM segments WHERE url_id = ?)")); |
|
Scott Hess - ex-Googler
2012/01/10 22:29:49
I suspect you actually want to put this one after
Greg Billock
2012/01/11 23:42:12
Oy, good point. I see what you're saying. I think
| |
| 352 return false; | 329 delete_seg.BindInt64(0, url_id); |
| 353 | 330 |
| 354 sql::Statement delete_seg(GetDB().GetCachedStatement(SQL_FROM_HERE, | 331 if (!delete_seg.Run()) |
| 355 "DELETE FROM segments WHERE id = ?")); | |
| 356 if (!delete_seg) | |
| 357 return false; | 332 return false; |
| 358 | 333 |
| 359 sql::Statement delete_usage(GetDB().GetCachedStatement(SQL_FROM_HERE, | 334 sql::Statement delete_usage(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 360 "DELETE FROM segment_usage WHERE segment_id = ?")); | 335 "DELETE FROM segment_usage WHERE segment_id IN " |
| 361 if (!delete_usage) | 336 "(SELECT id FROM segments WHERE url_id = ?)")); |
| 362 return false; | 337 delete_usage.BindInt64(0, url_id); |
| 363 | 338 |
| 364 bool r = true; | 339 return delete_usage.Run(); |
| 365 select.BindInt64(0, url_id); | |
| 366 // In theory there could not be more than one segment using that URL but we | |
| 367 // loop anyway to cleanup any inconsistency. | |
| 368 while (select.Step()) { | |
| 369 SegmentID segment_id = select.ColumnInt64(0); | |
| 370 | |
| 371 delete_usage.BindInt64(0, segment_id); | |
| 372 if (!delete_usage.Run()) { | |
| 373 NOTREACHED(); | |
| 374 r = false; | |
| 375 } | |
| 376 | |
| 377 delete_seg.BindInt64(0, segment_id); | |
| 378 if (!delete_seg.Run()) { | |
| 379 NOTREACHED(); | |
| 380 r = false; | |
| 381 } | |
| 382 delete_usage.Reset(); | |
| 383 delete_seg.Reset(); | |
| 384 } | |
| 385 return r; | |
| 386 } | 340 } |
| 387 | 341 |
| 388 } // namespace history | 342 } // namespace history |
| OLD | NEW |