blob: 43ae9ebc36e31095dbbe55d39268d3ec3be1b952 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/precache/core/precache_url_table.h"
#include <string>
#include "base/logging.h"
#include "sql/connection.h"
#include "sql/statement.h"
using sql::Statement;
namespace {
// Returns the spec of the given URL.
std::string GetKey(const GURL& url) {
return url.spec();
}
} // namespace
namespace precache {
bool PrecacheURLInfo::operator==(const PrecacheURLInfo& other) const {
return was_precached == other.was_precached &&
is_precached == other.is_precached && was_used == other.was_used &&
is_download_reported == other.is_download_reported;
}
PrecacheURLTable::PrecacheURLTable() : db_(NULL) {}
PrecacheURLTable::~PrecacheURLTable() {}
bool PrecacheURLTable::Init(sql::Connection* db) {
DCHECK(!db_); // Init must only be called once.
DCHECK(db); // The database connection must be non-NULL.
db_ = db;
return CreateTableIfNonExistent();
}
void PrecacheURLTable::AddURL(const GURL& url,
int64_t referrer_host_id,
bool is_precached,
const base::Time& precache_time,
bool is_download_reported) {
Statement statement(db_->GetCachedStatement(
SQL_FROM_HERE,
"INSERT OR REPLACE INTO precache_urls "
"(url, referrer_host_id, was_used, is_precached, time, "
" is_download_reported)"
"VALUES(?, ?, 0, ?, ?, ?)"));
statement.BindString(0, GetKey(url));
statement.BindInt64(1, referrer_host_id);
statement.BindInt64(2, is_precached ? 1 : 0);
statement.BindInt64(3, precache_time.ToInternalValue());
statement.BindInt64(4, is_download_reported);
statement.Run();
}
PrecacheURLInfo PrecacheURLTable::GetURLInfo(const GURL& url) {
Statement statement(db_->GetCachedStatement(
SQL_FROM_HERE,
"SELECT is_precached, was_used, is_download_reported "
"FROM precache_urls WHERE url=?"));
statement.BindString(0, GetKey(url));
if (statement.Step()) {
return {/*present=*/true, /*is_precached=*/statement.ColumnBool(0),
/*was_used==*/statement.ColumnBool(1),
/*is_download_reported=*/statement.ColumnBool(2)};
} else {
return {/*present=*/false, /*is_precached=*/false, /*was_used=*/false,
/*is_download_reported=*/false};
}
}
void PrecacheURLTable::SetPrecachedURLAsUsed(const GURL& url) {
Statement statement(
db_->GetCachedStatement(SQL_FROM_HERE,
"UPDATE precache_urls SET was_used=1, "
"is_precached=0 "
"WHERE url=? and was_used=0 and is_precached=1"));
statement.BindString(0, GetKey(url));
statement.Run();
}
void PrecacheURLTable::SetURLAsNotPrecached(const GURL& url) {
Statement statement(
db_->GetCachedStatement(SQL_FROM_HERE,
"UPDATE precache_urls SET is_precached=0 "
"WHERE url=? and is_precached=1"));
statement.BindString(0, GetKey(url));
statement.Run();
}
void PrecacheURLTable::GetURLListForReferrerHost(
int64_t referrer_host_id,
std::vector<GURL>* used_urls,
std::vector<GURL>* downloaded_urls) {
Statement statement(
db_->GetCachedStatement(SQL_FROM_HERE,
"SELECT url, was_used, is_download_reported "
"from precache_urls where referrer_host_id=?"));
statement.BindInt64(0, referrer_host_id);
while (statement.Step()) {
GURL url(statement.ColumnString(0));
if (statement.ColumnInt(1))
used_urls->push_back(url);
if (!statement.ColumnInt(2))
downloaded_urls->push_back(url);
}
}
void PrecacheURLTable::SetDownloadReported(int64_t referrer_host_id) {
Statement statement(
db_->GetCachedStatement(SQL_FROM_HERE,
"UPDATE precache_urls SET is_download_reported=1 "
"WHERE referrer_host_id=?"));
statement.BindInt64(0, referrer_host_id);
statement.Run();
}
void PrecacheURLTable::ClearAllForReferrerHost(int64_t referrer_host_id) {
// Delete the URLs that are not precached.
Statement delete_statement(
db_->GetCachedStatement(SQL_FROM_HERE,
"DELETE FROM precache_urls WHERE "
"referrer_host_id=? AND is_precached=0"));
delete_statement.BindInt64(0, referrer_host_id);
delete_statement.Run();
// Clear was_used for precached URLs.
Statement update_statement(db_->GetCachedStatement(
SQL_FROM_HERE,
"UPDATE precache_urls SET was_used=0 WHERE referrer_host_id=?"));
update_statement.BindInt64(0, referrer_host_id);
update_statement.Run();
}
void PrecacheURLTable::DeleteAllPrecachedBefore(const base::Time& delete_end) {
Statement statement(db_->GetCachedStatement(
SQL_FROM_HERE, "DELETE FROM precache_urls WHERE time < ?"));
statement.BindInt64(0, delete_end.ToInternalValue());
statement.Run();
}
void PrecacheURLTable::DeleteAll() {
Statement statement(
db_->GetCachedStatement(SQL_FROM_HERE, "DELETE FROM precache_urls"));
statement.Run();
}
void PrecacheURLTable::GetAllDataForTesting(std::map<GURL, base::Time>* map) {
map->clear();
Statement statement(db_->GetCachedStatement(
SQL_FROM_HERE,
"SELECT url, time FROM precache_urls where is_precached=1"));
while (statement.Step()) {
GURL url = GURL(statement.ColumnString(0));
(*map)[url] = base::Time::FromInternalValue(statement.ColumnInt64(1));
}
}
bool PrecacheURLTable::CreateTableIfNonExistent() {
// TODO(jamartin): The PRIMARY KEY should be (url, referrer_host_id).
if (!db_->DoesTableExist("precache_urls")) {
return db_->Execute(
"CREATE TABLE precache_urls "
"(url TEXT PRIMARY KEY, referrer_host_id INTEGER, was_used INTEGER, "
"is_precached INTEGER, "
"time INTEGER, is_download_reported INTEGER)");
} else {
// Migrate the table by creating the missing columns.
if (!db_->DoesColumnExist("precache_urls", "was_used") &&
!db_->Execute("ALTER TABLE precache_urls "
"ADD COLUMN was_used INTEGER")) {
return false;
}
if (!db_->DoesColumnExist("precache_urls", "is_precached") &&
!db_->Execute("ALTER TABLE precache_urls ADD COLUMN is_precached "
"INTEGER default 1")) {
return false;
}
if (!db_->DoesColumnExist("precache_urls", "referrer_host_id") &&
!db_->Execute(
"ALTER TABLE precache_urls ADD COLUMN referrer_host_id INTEGER")) {
return false;
}
if (!db_->DoesColumnExist("precache_urls", "is_download_reported") &&
!db_->Execute("ALTER TABLE precache_urls "
"ADD COLUMN is_download_reported INTEGER")) {
return false;
}
}
return true;
}
} // namespace precache