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/url_database.h" | 5 #include "chrome/browser/history/url_database.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 83 i->hidden_ = s.ColumnInt(6) != 0; | 83 i->hidden_ = s.ColumnInt(6) != 0; |
| 84 } | 84 } |
| 85 | 85 |
| 86 bool URLDatabase::GetURLRow(URLID url_id, URLRow* info) { | 86 bool URLDatabase::GetURLRow(URLID url_id, URLRow* info) { |
| 87 // TODO(brettw) We need check for empty URLs to handle the case where | 87 // TODO(brettw) We need check for empty URLs to handle the case where |
| 88 // there are old URLs in the database that are empty that got in before | 88 // there are old URLs in the database that are empty that got in before |
| 89 // we added any checks. We should eventually be able to remove it | 89 // we added any checks. We should eventually be able to remove it |
| 90 // when all inputs are using GURL (which prohibit empty input). | 90 // when all inputs are using GURL (which prohibit empty input). |
| 91 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 91 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 92 "SELECT" HISTORY_URL_ROW_FIELDS "FROM urls WHERE id=?")); | 92 "SELECT" HISTORY_URL_ROW_FIELDS "FROM urls WHERE id=?")); |
| 93 if (!statement) | 93 statement.BindInt64(0, url_id); |
| 94 return false; | |
| 95 | 94 |
| 96 statement.BindInt64(0, url_id); | |
| 97 if (statement.Step()) { | 95 if (statement.Step()) { |
| 98 FillURLRow(statement, info); | 96 FillURLRow(statement, info); |
| 99 return true; | 97 return true; |
| 100 } | 98 } |
| 101 return false; | 99 return false; |
| 102 } | 100 } |
| 103 | 101 |
| 104 bool URLDatabase::GetAllTypedUrls(std::vector<history::URLRow>* urls) { | 102 bool URLDatabase::GetAllTypedUrls(std::vector<history::URLRow>* urls) { |
| 105 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 103 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 106 "SELECT" HISTORY_URL_ROW_FIELDS "FROM urls WHERE typed_count > 0")); | 104 "SELECT" HISTORY_URL_ROW_FIELDS "FROM urls WHERE typed_count > 0")); |
| 107 if (!statement) | |
| 108 return false; | |
|
Scott Hess - ex-Googler
2012/01/03 23:41:57
This can now return true in case of empty results.
Greg Billock
2012/01/04 19:20:20
I think that's what this did before. The above sho
Scott Hess - ex-Googler
2012/01/10 22:04:56
As it stands, it's always returning true, so if it
| |
| 109 | 105 |
| 110 while (statement.Step()) { | 106 while (statement.Step()) { |
| 111 URLRow info; | 107 URLRow info; |
| 112 FillURLRow(statement, &info); | 108 FillURLRow(statement, &info); |
| 113 urls->push_back(info); | 109 urls->push_back(info); |
| 114 } | 110 } |
| 115 return true; | 111 return true; |
| 116 } | 112 } |
| 117 | 113 |
| 118 URLID URLDatabase::GetRowForURL(const GURL& url, history::URLRow* info) { | 114 URLID URLDatabase::GetRowForURL(const GURL& url, history::URLRow* info) { |
| 119 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 115 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 120 "SELECT" HISTORY_URL_ROW_FIELDS "FROM urls WHERE url=?")); | 116 "SELECT" HISTORY_URL_ROW_FIELDS "FROM urls WHERE url=?")); |
| 121 if (!statement) | |
| 122 return 0; | |
| 123 | |
| 124 std::string url_string = GURLToDatabaseURL(url); | 117 std::string url_string = GURLToDatabaseURL(url); |
| 125 statement.BindString(0, url_string); | 118 statement.BindString(0, url_string); |
| 119 | |
| 126 if (!statement.Step()) | 120 if (!statement.Step()) |
| 127 return 0; // no data | 121 return 0; // no data |
| 128 | 122 |
| 129 if (info) | 123 if (info) |
| 130 FillURLRow(statement, info); | 124 FillURLRow(statement, info); |
| 131 return statement.ColumnInt64(0); | 125 return statement.ColumnInt64(0); |
| 132 } | 126 } |
| 133 | 127 |
| 134 bool URLDatabase::UpdateURLRow(URLID url_id, | 128 bool URLDatabase::UpdateURLRow(URLID url_id, |
| 135 const history::URLRow& info) { | 129 const history::URLRow& info) { |
| 136 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 130 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 137 "UPDATE urls SET title=?,visit_count=?,typed_count=?,last_visit_time=?," | 131 "UPDATE urls SET title=?,visit_count=?,typed_count=?,last_visit_time=?," |
| 138 "hidden=?" | 132 "hidden=?" |
| 139 "WHERE id=?")); | 133 "WHERE id=?")); |
| 140 if (!statement) | |
| 141 return false; | |
| 142 | |
| 143 statement.BindString16(0, info.title()); | 134 statement.BindString16(0, info.title()); |
| 144 statement.BindInt(1, info.visit_count()); | 135 statement.BindInt(1, info.visit_count()); |
| 145 statement.BindInt(2, info.typed_count()); | 136 statement.BindInt(2, info.typed_count()); |
| 146 statement.BindInt64(3, info.last_visit().ToInternalValue()); | 137 statement.BindInt64(3, info.last_visit().ToInternalValue()); |
| 147 statement.BindInt(4, info.hidden() ? 1 : 0); | 138 statement.BindInt(4, info.hidden() ? 1 : 0); |
| 148 statement.BindInt64(5, url_id); | 139 statement.BindInt64(5, url_id); |
| 140 | |
| 149 return statement.Run(); | 141 return statement.Run(); |
| 150 } | 142 } |
| 151 | 143 |
| 152 URLID URLDatabase::AddURLInternal(const history::URLRow& info, | 144 URLID URLDatabase::AddURLInternal(const history::URLRow& info, |
| 153 bool is_temporary) { | 145 bool is_temporary) { |
| 154 // This function is used to insert into two different tables, so we have to | 146 // This function is used to insert into two different tables, so we have to |
| 155 // do some shuffling. Unfortinately, we can't use the macro | 147 // do some shuffling. Unfortinately, we can't use the macro |
| 156 // HISTORY_URL_ROW_FIELDS because that specifies the table name which is | 148 // HISTORY_URL_ROW_FIELDS because that specifies the table name which is |
| 157 // invalid in the insert syntax. | 149 // invalid in the insert syntax. |
| 158 #define ADDURL_COMMON_SUFFIX \ | 150 #define ADDURL_COMMON_SUFFIX \ |
| 159 " (url, title, visit_count, typed_count, "\ | 151 " (url, title, visit_count, typed_count, "\ |
| 160 "last_visit_time, hidden) "\ | 152 "last_visit_time, hidden) "\ |
| 161 "VALUES (?,?,?,?,?,?)" | 153 "VALUES (?,?,?,?,?,?)" |
| 162 const char* statement_name; | 154 const char* statement_name; |
| 163 const char* statement_sql; | 155 const char* statement_sql; |
| 164 if (is_temporary) { | 156 if (is_temporary) { |
| 165 statement_name = "AddURLTemporary"; | 157 statement_name = "AddURLTemporary"; |
| 166 statement_sql = "INSERT INTO temp_urls" ADDURL_COMMON_SUFFIX; | 158 statement_sql = "INSERT INTO temp_urls" ADDURL_COMMON_SUFFIX; |
| 167 } else { | 159 } else { |
| 168 statement_name = "AddURL"; | 160 statement_name = "AddURL"; |
| 169 statement_sql = "INSERT INTO urls" ADDURL_COMMON_SUFFIX; | 161 statement_sql = "INSERT INTO urls" ADDURL_COMMON_SUFFIX; |
| 170 } | 162 } |
| 171 #undef ADDURL_COMMON_SUFFIX | 163 #undef ADDURL_COMMON_SUFFIX |
| 172 | 164 |
| 173 sql::Statement statement(GetDB().GetCachedStatement( | 165 sql::Statement statement(GetDB().GetCachedStatement( |
| 174 sql::StatementID(statement_name), statement_sql)); | 166 sql::StatementID(statement_name), statement_sql)); |
| 175 if (!statement) { | |
| 176 NOTREACHED() << GetDB().GetErrorMessage(); | |
| 177 return 0; | |
| 178 } | |
| 179 | |
| 180 statement.BindString(0, GURLToDatabaseURL(info.url())); | 167 statement.BindString(0, GURLToDatabaseURL(info.url())); |
| 181 statement.BindString16(1, info.title()); | 168 statement.BindString16(1, info.title()); |
| 182 statement.BindInt(2, info.visit_count()); | 169 statement.BindInt(2, info.visit_count()); |
| 183 statement.BindInt(3, info.typed_count()); | 170 statement.BindInt(3, info.typed_count()); |
| 184 statement.BindInt64(4, info.last_visit().ToInternalValue()); | 171 statement.BindInt64(4, info.last_visit().ToInternalValue()); |
| 185 statement.BindInt(5, info.hidden() ? 1 : 0); | 172 statement.BindInt(5, info.hidden() ? 1 : 0); |
| 186 | 173 |
| 187 if (!statement.Run()) { | 174 if (!statement.Run()) { |
| 188 VLOG(0) << "Failed to add url " << info.url().possibly_invalid_spec() | 175 VLOG(0) << "Failed to add url " << info.url().possibly_invalid_spec() |
| 189 << " to table history.urls."; | 176 << " to table history.urls."; |
| 190 return 0; | 177 return 0; |
| 191 } | 178 } |
| 192 return GetDB().GetLastInsertRowId(); | 179 return GetDB().GetLastInsertRowId(); |
| 193 } | 180 } |
| 194 | 181 |
| 195 bool URLDatabase::DeleteURLRow(URLID id) { | 182 bool URLDatabase::DeleteURLRow(URLID id) { |
| 196 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 183 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 197 "DELETE FROM urls WHERE id = ?")); | 184 "DELETE FROM urls WHERE id = ?")); |
| 198 if (!statement) | 185 statement.BindInt64(0, id); |
| 199 return false; | |
| 200 | 186 |
| 201 statement.BindInt64(0, id); | |
| 202 if (!statement.Run()) | 187 if (!statement.Run()) |
| 203 return false; | 188 return false; |
| 204 | 189 |
| 205 // And delete any keyword visits. | 190 // And delete any keyword visits. |
| 206 if (!has_keyword_search_terms_) | 191 if (!has_keyword_search_terms_) |
| 207 return true; | 192 return true; |
| 208 | 193 |
| 209 sql::Statement del_keyword_visit(GetDB().GetCachedStatement(SQL_FROM_HERE, | 194 sql::Statement del_keyword_visit(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 210 "DELETE FROM keyword_search_terms WHERE url_id=?")); | 195 "DELETE FROM keyword_search_terms WHERE url_id=?")); |
| 211 if (!del_keyword_visit) | |
| 212 return false; | |
| 213 del_keyword_visit.BindInt64(0, id); | 196 del_keyword_visit.BindInt64(0, id); |
| 197 | |
| 214 return del_keyword_visit.Run(); | 198 return del_keyword_visit.Run(); |
| 215 } | 199 } |
| 216 | 200 |
| 217 bool URLDatabase::CreateTemporaryURLTable() { | 201 bool URLDatabase::CreateTemporaryURLTable() { |
| 218 return CreateURLTable(true); | 202 return CreateURLTable(true); |
| 219 } | 203 } |
| 220 | 204 |
| 221 bool URLDatabase::CommitTemporaryURLTable() { | 205 bool URLDatabase::CommitTemporaryURLTable() { |
| 222 // See the comments in the header file as well as | 206 // See the comments in the header file as well as |
| 223 // HistoryBackend::DeleteAllHistory() for more information on how this works | 207 // HistoryBackend::DeleteAllHistory() for more information on how this works |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 244 | 228 |
| 245 return true; | 229 return true; |
| 246 } | 230 } |
| 247 | 231 |
| 248 bool URLDatabase::InitURLEnumeratorForEverything(URLEnumerator* enumerator) { | 232 bool URLDatabase::InitURLEnumeratorForEverything(URLEnumerator* enumerator) { |
| 249 DCHECK(!enumerator->initialized_); | 233 DCHECK(!enumerator->initialized_); |
| 250 std::string sql("SELECT "); | 234 std::string sql("SELECT "); |
| 251 sql.append(kURLRowFields); | 235 sql.append(kURLRowFields); |
| 252 sql.append(" FROM urls"); | 236 sql.append(" FROM urls"); |
| 253 enumerator->statement_.Assign(GetDB().GetUniqueStatement(sql.c_str())); | 237 enumerator->statement_.Assign(GetDB().GetUniqueStatement(sql.c_str())); |
| 254 if (!enumerator->statement_) { | |
| 255 NOTREACHED() << GetDB().GetErrorMessage(); | |
| 256 return false; | |
| 257 } | |
|
Scott Hess - ex-Googler
2012/01/03 23:41:57
I'm not entirely convinced that removing these is
Greg Billock
2012/01/04 19:20:20
OK. Is the above build-up of a query manually kosh
Scott Hess - ex-Googler
2012/01/10 22:04:56
In general I hate dynamically-generated queries, p
| |
| 258 enumerator->initialized_ = true; | 238 enumerator->initialized_ = true; |
| 259 return true; | 239 return true; |
| 260 } | 240 } |
| 261 | 241 |
| 262 bool URLDatabase::InitURLEnumeratorForSignificant(URLEnumerator* enumerator) { | 242 bool URLDatabase::InitURLEnumeratorForSignificant(URLEnumerator* enumerator) { |
| 263 DCHECK(!enumerator->initialized_); | 243 DCHECK(!enumerator->initialized_); |
| 264 std::string sql("SELECT "); | 244 std::string sql("SELECT "); |
| 265 sql.append(kURLRowFields); | 245 sql.append(kURLRowFields); |
| 266 sql.append(" FROM urls WHERE last_visit_time >= ? OR visit_count >= ? OR " | 246 sql.append(" FROM urls WHERE last_visit_time >= ? OR visit_count >= ? OR " |
| 267 "typed_count >= ?"); | 247 "typed_count >= ?"); |
| 268 enumerator->statement_.Assign(GetDB().GetUniqueStatement(sql.c_str())); | 248 enumerator->statement_.Assign(GetDB().GetUniqueStatement(sql.c_str())); |
| 269 if (!enumerator->statement_) { | |
| 270 NOTREACHED() << GetDB().GetErrorMessage(); | |
| 271 return false; | |
| 272 } | |
| 273 enumerator->statement_.BindInt64( | 249 enumerator->statement_.BindInt64( |
| 274 0, AutocompleteAgeThreshold().ToInternalValue()); | 250 0, AutocompleteAgeThreshold().ToInternalValue()); |
| 275 enumerator->statement_.BindInt(1, kLowQualityMatchVisitLimit); | 251 enumerator->statement_.BindInt(1, kLowQualityMatchVisitLimit); |
| 276 enumerator->statement_.BindInt(2, kLowQualityMatchTypedLimit); | 252 enumerator->statement_.BindInt(2, kLowQualityMatchTypedLimit); |
| 277 enumerator->initialized_ = true; | 253 enumerator->initialized_ = true; |
| 278 return true; | 254 return true; |
| 279 } | 255 } |
| 280 | 256 |
| 281 bool URLDatabase::InitIconMappingEnumeratorForEverything( | 257 bool URLDatabase::InitIconMappingEnumeratorForEverything( |
| 282 IconMappingEnumerator* enumerator) { | 258 IconMappingEnumerator* enumerator) { |
| 283 DCHECK(!enumerator->initialized_); | 259 DCHECK(!enumerator->initialized_); |
| 284 enumerator->statement_.Assign(GetDB().GetUniqueStatement( | 260 enumerator->statement_.Assign(GetDB().GetUniqueStatement( |
| 285 "SELECT url, favicon_id FROM urls WHERE favicon_id <> 0")); | 261 "SELECT url, favicon_id FROM urls WHERE favicon_id <> 0")); |
| 286 if (!enumerator->statement_) { | |
| 287 NOTREACHED() << GetDB().GetErrorMessage(); | |
| 288 return false; | |
| 289 } | |
| 290 enumerator->initialized_ = true; | 262 enumerator->initialized_ = true; |
| 291 return true; | 263 return true; |
| 292 } | 264 } |
| 293 | 265 |
| 294 bool URLDatabase::AutocompleteForPrefix(const std::string& prefix, | 266 bool URLDatabase::AutocompleteForPrefix(const std::string& prefix, |
| 295 size_t max_results, | 267 size_t max_results, |
| 296 bool typed_only, | 268 bool typed_only, |
| 297 std::vector<history::URLRow>* results) { | 269 std::vector<history::URLRow>* results) { |
| 298 // NOTE: this query originally sorted by starred as the second parameter. But | 270 // NOTE: this query originally sorted by starred as the second parameter. But |
| 299 // as bookmarks is no longer part of the db we no longer include the order | 271 // as bookmarks is no longer part of the db we no longer include the order |
| 300 // by clause. | 272 // by clause. |
| 301 results->clear(); | 273 results->clear(); |
| 302 const char* sql; | 274 const char* sql; |
| 303 int line; | 275 int line; |
| 304 if (typed_only) { | 276 if (typed_only) { |
| 305 sql = "SELECT" HISTORY_URL_ROW_FIELDS "FROM urls " | 277 sql = "SELECT" HISTORY_URL_ROW_FIELDS "FROM urls " |
| 306 "WHERE url >= ? AND url < ? AND hidden = 0 AND typed_count > 0 " | 278 "WHERE url >= ? AND url < ? AND hidden = 0 AND typed_count > 0 " |
| 307 "ORDER BY typed_count DESC, visit_count DESC, last_visit_time DESC " | 279 "ORDER BY typed_count DESC, visit_count DESC, last_visit_time DESC " |
| 308 "LIMIT ?"; | 280 "LIMIT ?"; |
| 309 line = __LINE__; | 281 line = __LINE__; |
| 310 } else { | 282 } else { |
| 311 sql = "SELECT" HISTORY_URL_ROW_FIELDS "FROM urls " | 283 sql = "SELECT" HISTORY_URL_ROW_FIELDS "FROM urls " |
| 312 "WHERE url >= ? AND url < ? AND hidden = 0 " | 284 "WHERE url >= ? AND url < ? AND hidden = 0 " |
| 313 "ORDER BY typed_count DESC, visit_count DESC, last_visit_time DESC " | 285 "ORDER BY typed_count DESC, visit_count DESC, last_visit_time DESC " |
| 314 "LIMIT ?"; | 286 "LIMIT ?"; |
| 315 line = __LINE__; | 287 line = __LINE__; |
| 316 } | 288 } |
| 317 sql::Statement statement( | 289 sql::Statement statement( |
| 318 GetDB().GetCachedStatement(sql::StatementID(__FILE__, line), sql)); | 290 GetDB().GetCachedStatement(sql::StatementID(__FILE__, line), sql)); |
| 319 if (!statement) | |
| 320 return false; | |
| 321 | 291 |
| 322 // We will find all strings between "prefix" and this string, which is prefix | 292 // We will find all strings between "prefix" and this string, which is prefix |
| 323 // followed by the maximum character size. Use 8-bit strings for everything | 293 // followed by the maximum character size. Use 8-bit strings for everything |
| 324 // so we can be sure sqlite is comparing everything in 8-bit mode. Otherwise, | 294 // so we can be sure sqlite is comparing everything in 8-bit mode. Otherwise, |
| 325 // it will have to convert strings either to UTF-8 or UTF-16 for comparison. | 295 // it will have to convert strings either to UTF-8 or UTF-16 for comparison. |
| 326 std::string end_query(prefix); | 296 std::string end_query(prefix); |
| 327 end_query.push_back(std::numeric_limits<unsigned char>::max()); | 297 end_query.push_back(std::numeric_limits<unsigned char>::max()); |
| 328 | 298 |
| 329 statement.BindString(0, prefix); | 299 statement.BindString(0, prefix); |
| 330 statement.BindString(1, end_query); | 300 statement.BindString(1, end_query); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 368 // those wouldn't use the index, and would run into problems with "wildcard" | 338 // those wouldn't use the index, and would run into problems with "wildcard" |
| 369 // characters that appear in URLs (% for LIKE, or *, ? for GLOB). | 339 // characters that appear in URLs (% for LIKE, or *, ? for GLOB). |
| 370 std::string sql("SELECT "); | 340 std::string sql("SELECT "); |
| 371 sql.append(kURLRowFields); | 341 sql.append(kURLRowFields); |
| 372 sql.append(" FROM urls WHERE url "); | 342 sql.append(" FROM urls WHERE url "); |
| 373 sql.append(allow_base ? ">=" : ">"); | 343 sql.append(allow_base ? ">=" : ">"); |
| 374 sql.append(" ? AND url < :end AND url = substr(:end, 1, length(url)) " | 344 sql.append(" ? AND url < :end AND url = substr(:end, 1, length(url)) " |
| 375 "AND hidden = 0 AND visit_count >= ? AND typed_count >= ? " | 345 "AND hidden = 0 AND visit_count >= ? AND typed_count >= ? " |
| 376 "ORDER BY url LIMIT 1"); | 346 "ORDER BY url LIMIT 1"); |
| 377 sql::Statement statement(GetDB().GetUniqueStatement(sql.c_str())); | 347 sql::Statement statement(GetDB().GetUniqueStatement(sql.c_str())); |
| 378 if (!statement) { | |
| 379 NOTREACHED() << GetDB().GetErrorMessage(); | |
| 380 return false; | |
| 381 } | |
| 382 | |
| 383 statement.BindString(0, base); | 348 statement.BindString(0, base); |
| 384 statement.BindString(1, url); // :end | 349 statement.BindString(1, url); // :end |
| 385 statement.BindInt(2, min_visits); | 350 statement.BindInt(2, min_visits); |
| 386 statement.BindInt(3, min_typed); | 351 statement.BindInt(3, min_typed); |
| 387 | 352 |
| 388 if (!statement.Step()) | 353 if (!statement.Step()) |
| 389 return false; | 354 return false; |
| 390 | 355 |
| 391 DCHECK(info); | 356 DCHECK(info); |
| 392 FillURLRow(statement, info); | 357 FillURLRow(statement, info); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 413 "keyword_search_terms (keyword_id, lower_term)")) { | 378 "keyword_search_terms (keyword_id, lower_term)")) { |
| 414 return false; | 379 return false; |
| 415 } | 380 } |
| 416 | 381 |
| 417 // For deletion. | 382 // For deletion. |
| 418 if (!GetDB().Execute( | 383 if (!GetDB().Execute( |
| 419 "CREATE INDEX IF NOT EXISTS keyword_search_terms_index2 ON " | 384 "CREATE INDEX IF NOT EXISTS keyword_search_terms_index2 ON " |
| 420 "keyword_search_terms (url_id)")) { | 385 "keyword_search_terms (url_id)")) { |
| 421 return false; | 386 return false; |
| 422 } | 387 } |
| 388 | |
| 423 return true; | 389 return true; |
| 424 } | 390 } |
| 425 | 391 |
| 426 bool URLDatabase::DropKeywordSearchTermsTable() { | 392 bool URLDatabase::DropKeywordSearchTermsTable() { |
| 427 // This will implicitly delete the indices over the table. | 393 // This will implicitly delete the indices over the table. |
| 428 return GetDB().Execute("DROP TABLE keyword_search_terms"); | 394 return GetDB().Execute("DROP TABLE keyword_search_terms"); |
| 429 } | 395 } |
| 430 | 396 |
| 431 bool URLDatabase::SetKeywordSearchTermsForURL(URLID url_id, | 397 bool URLDatabase::SetKeywordSearchTermsForURL(URLID url_id, |
| 432 TemplateURLID keyword_id, | 398 TemplateURLID keyword_id, |
| 433 const string16& term) { | 399 const string16& term) { |
| 434 DCHECK(url_id && keyword_id && !term.empty()); | 400 DCHECK(url_id && keyword_id && !term.empty()); |
| 435 | 401 |
| 436 sql::Statement exist_statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 402 sql::Statement exist_statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 437 "SELECT term FROM keyword_search_terms " | 403 "SELECT term FROM keyword_search_terms " |
| 438 "WHERE keyword_id = ? AND url_id = ?")); | 404 "WHERE keyword_id = ? AND url_id = ?")); |
| 439 if (!exist_statement) | |
| 440 return false; | |
| 441 exist_statement.BindInt64(0, keyword_id); | 405 exist_statement.BindInt64(0, keyword_id); |
| 442 exist_statement.BindInt64(1, url_id); | 406 exist_statement.BindInt64(1, url_id); |
| 407 | |
| 443 if (exist_statement.Step()) | 408 if (exist_statement.Step()) |
| 444 return true; // Term already exists, no need to add it. | 409 return true; // Term already exists, no need to add it. |
| 445 | 410 |
| 446 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 411 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 447 "INSERT INTO keyword_search_terms (keyword_id, url_id, lower_term, term) " | 412 "INSERT INTO keyword_search_terms (keyword_id, url_id, lower_term, term) " |
| 448 "VALUES (?,?,?,?)")); | 413 "VALUES (?,?,?,?)")); |
| 449 if (!statement) | |
| 450 return false; | |
| 451 | |
| 452 statement.BindInt64(0, keyword_id); | 414 statement.BindInt64(0, keyword_id); |
| 453 statement.BindInt64(1, url_id); | 415 statement.BindInt64(1, url_id); |
| 454 statement.BindString16(2, base::i18n::ToLower(term)); | 416 statement.BindString16(2, base::i18n::ToLower(term)); |
| 455 statement.BindString16(3, term); | 417 statement.BindString16(3, term); |
| 456 return statement.Run(); | 418 return statement.Run(); |
| 457 } | 419 } |
| 458 | 420 |
| 459 bool URLDatabase::GetKeywordSearchTermRow(URLID url_id, | 421 bool URLDatabase::GetKeywordSearchTermRow(URLID url_id, |
| 460 KeywordSearchTermRow* row) { | 422 KeywordSearchTermRow* row) { |
| 461 DCHECK(url_id); | 423 DCHECK(url_id); |
| 462 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 424 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 463 "SELECT keyword_id, term FROM keyword_search_terms WHERE url_id=?")); | 425 "SELECT keyword_id, term FROM keyword_search_terms WHERE url_id=?")); |
| 464 if (!statement) | 426 statement.BindInt64(0, url_id); |
| 465 return false; | |
| 466 | 427 |
| 467 statement.BindInt64(0, url_id); | |
| 468 if (!statement.Step()) | 428 if (!statement.Step()) |
| 469 return false; | 429 return false; |
| 470 | 430 |
| 471 if (row) { | 431 if (row) { |
| 472 row->url_id = url_id; | 432 row->url_id = url_id; |
| 473 row->keyword_id = statement.ColumnInt64(0); | 433 row->keyword_id = statement.ColumnInt64(0); |
| 474 row->term = statement.ColumnString16(1); | 434 row->term = statement.ColumnString16(1); |
| 475 } | 435 } |
| 476 return true; | 436 return true; |
| 477 } | 437 } |
| 478 | 438 |
| 479 void URLDatabase::DeleteAllSearchTermsForKeyword( | 439 void URLDatabase::DeleteAllSearchTermsForKeyword( |
| 480 TemplateURLID keyword_id) { | 440 TemplateURLID keyword_id) { |
| 481 DCHECK(keyword_id); | 441 DCHECK(keyword_id); |
| 482 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 442 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 483 "DELETE FROM keyword_search_terms WHERE keyword_id=?")); | 443 "DELETE FROM keyword_search_terms WHERE keyword_id=?")); |
| 484 if (!statement) | 444 statement.BindInt64(0, keyword_id); |
| 485 return; | |
| 486 | 445 |
| 487 statement.BindInt64(0, keyword_id); | |
| 488 statement.Run(); | 446 statement.Run(); |
| 489 } | 447 } |
| 490 | 448 |
| 491 void URLDatabase::GetMostRecentKeywordSearchTerms( | 449 void URLDatabase::GetMostRecentKeywordSearchTerms( |
| 492 TemplateURLID keyword_id, | 450 TemplateURLID keyword_id, |
| 493 const string16& prefix, | 451 const string16& prefix, |
| 494 int max_count, | 452 int max_count, |
| 495 std::vector<KeywordSearchTermVisit>* matches) { | 453 std::vector<KeywordSearchTermVisit>* matches) { |
| 496 // NOTE: the keyword_id can be zero if on first run the user does a query | 454 // NOTE: the keyword_id can be zero if on first run the user does a query |
| 497 // before the TemplateURLService has finished loading. As the chances of this | 455 // before the TemplateURLService has finished loading. As the chances of this |
| 498 // occurring are small, we ignore it. | 456 // occurring are small, we ignore it. |
| 499 if (!keyword_id) | 457 if (!keyword_id) |
| 500 return; | 458 return; |
| 501 | 459 |
| 502 DCHECK(!prefix.empty()); | 460 DCHECK(!prefix.empty()); |
| 503 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 461 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 504 "SELECT DISTINCT kv.term, u.visit_count, u.last_visit_time " | 462 "SELECT DISTINCT kv.term, u.visit_count, u.last_visit_time " |
| 505 "FROM keyword_search_terms kv " | 463 "FROM keyword_search_terms kv " |
| 506 "JOIN urls u ON kv.url_id = u.id " | 464 "JOIN urls u ON kv.url_id = u.id " |
| 507 "WHERE kv.keyword_id = ? AND kv.lower_term >= ? AND kv.lower_term < ? " | 465 "WHERE kv.keyword_id = ? AND kv.lower_term >= ? AND kv.lower_term < ? " |
| 508 "ORDER BY u.last_visit_time DESC LIMIT ?")); | 466 "ORDER BY u.last_visit_time DESC LIMIT ?")); |
| 509 if (!statement) | |
| 510 return; | |
| 511 | 467 |
| 512 // NOTE: Keep this ToLower() call in sync with search_provider.cc. | 468 // NOTE: Keep this ToLower() call in sync with search_provider.cc. |
| 513 string16 lower_prefix = base::i18n::ToLower(prefix); | 469 string16 lower_prefix = base::i18n::ToLower(prefix); |
| 514 // This magic gives us a prefix search. | 470 // This magic gives us a prefix search. |
| 515 string16 next_prefix = lower_prefix; | 471 string16 next_prefix = lower_prefix; |
| 516 next_prefix[next_prefix.size() - 1] = | 472 next_prefix[next_prefix.size() - 1] = |
| 517 next_prefix[next_prefix.size() - 1] + 1; | 473 next_prefix[next_prefix.size() - 1] + 1; |
| 518 statement.BindInt64(0, keyword_id); | 474 statement.BindInt64(0, keyword_id); |
| 519 statement.BindString16(1, lower_prefix); | 475 statement.BindString16(1, lower_prefix); |
| 520 statement.BindString16(2, next_prefix); | 476 statement.BindString16(2, next_prefix); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 576 return GetDB().Execute(sql.c_str()); | 532 return GetDB().Execute(sql.c_str()); |
| 577 } | 533 } |
| 578 | 534 |
| 579 bool URLDatabase::CreateMainURLIndex() { | 535 bool URLDatabase::CreateMainURLIndex() { |
| 580 // Index over URLs so we can quickly look up based on URL. | 536 // Index over URLs so we can quickly look up based on URL. |
| 581 return GetDB().Execute( | 537 return GetDB().Execute( |
| 582 "CREATE INDEX IF NOT EXISTS urls_url_index ON urls (url)"); | 538 "CREATE INDEX IF NOT EXISTS urls_url_index ON urls (url)"); |
| 583 } | 539 } |
| 584 | 540 |
| 585 } // namespace history | 541 } // namespace history |
| OLD | NEW |