| Index: webkit/appcache/appcache_database.cc
|
| ===================================================================
|
| --- webkit/appcache/appcache_database.cc (revision 113546)
|
| +++ webkit/appcache/appcache_database.cc (working copy)
|
| @@ -19,20 +19,29 @@
|
| // Schema -------------------------------------------------------------------
|
| namespace {
|
|
|
| -const int kCurrentVersion = 3;
|
| -const int kCompatibleVersion = 3;
|
| +const int kCurrentVersion = 4;
|
| +const int kCompatibleVersion = 4;
|
|
|
| const char kGroupsTable[] = "Groups";
|
| const char kCachesTable[] = "Caches";
|
| const char kEntriesTable[] = "Entries";
|
| -const char kFallbackNameSpacesTable[] = "FallbackNameSpaces";
|
| +const char kNamespacesTable[] = "Namespaces";
|
| const char kOnlineWhiteListsTable[] = "OnlineWhiteLists";
|
| const char kDeletableResponseIdsTable[] = "DeletableResponseIds";
|
|
|
| -const struct {
|
| +struct TableInfo {
|
| const char* table_name;
|
| const char* columns;
|
| -} kTables[] = {
|
| +};
|
| +
|
| +struct IndexInfo {
|
| + const char* index_name;
|
| + const char* table_name;
|
| + const char* columns;
|
| + bool unique;
|
| +};
|
| +
|
| +const TableInfo kTables[] = {
|
| { kGroupsTable,
|
| "(group_id INTEGER PRIMARY KEY,"
|
| " origin TEXT,"
|
| @@ -54,11 +63,12 @@
|
| " response_id INTEGER,"
|
| " response_size INTEGER)" },
|
|
|
| - { kFallbackNameSpacesTable,
|
| + { kNamespacesTable,
|
| "(cache_id INTEGER,"
|
| " origin TEXT," // intentionally not normalized
|
| + " type INTEGER,"
|
| " namespace_url TEXT,"
|
| - " fallback_entry_url TEXT)" },
|
| + " target_url TEXT)" },
|
|
|
| { kOnlineWhiteListsTable,
|
| "(cache_id INTEGER,"
|
| @@ -68,12 +78,7 @@
|
| "(response_id INTEGER NOT NULL)" },
|
| };
|
|
|
| -const struct {
|
| - const char* index_name;
|
| - const char* table_name;
|
| - const char* columns;
|
| - bool unique;
|
| -} kIndexes[] = {
|
| +const IndexInfo kIndexes[] = {
|
| { "GroupsOriginIndex",
|
| kGroupsTable,
|
| "(origin)",
|
| @@ -104,18 +109,18 @@
|
| "(response_id)",
|
| true },
|
|
|
| - { "FallbackNameSpacesCacheIndex",
|
| - kFallbackNameSpacesTable,
|
| + { "NamespacesCacheIndex",
|
| + kNamespacesTable,
|
| "(cache_id)",
|
| false },
|
|
|
| - { "FallbackNameSpacesOriginIndex",
|
| - kFallbackNameSpacesTable,
|
| + { "NamespacesOriginIndex",
|
| + kNamespacesTable,
|
| "(origin)",
|
| false },
|
|
|
| - { "FallbackNameSpacesCacheAndUrlIndex",
|
| - kFallbackNameSpacesTable,
|
| + { "NamespacesCacheAndUrlIndex",
|
| + kNamespacesTable,
|
| "(cache_id, namespace_url)",
|
| true },
|
|
|
| @@ -142,6 +147,26 @@
|
| return new sql::DiagnosticErrorDelegate<HistogramUniquifier>();
|
| }
|
|
|
| +bool CreateTable(sql::Connection* db, const TableInfo& info) {
|
| + std::string sql("CREATE TABLE ");
|
| + sql += info.table_name;
|
| + sql += info.columns;
|
| + return db->Execute(sql.c_str());
|
| +}
|
| +
|
| +bool CreateIndex(sql::Connection* db, const IndexInfo& info) {
|
| + std::string sql;
|
| + if (info.unique)
|
| + sql += "CREATE UNIQUE INDEX ";
|
| + else
|
| + sql += "CREATE INDEX ";
|
| + sql += info.index_name;
|
| + sql += " ON ";
|
| + sql += info.table_name;
|
| + sql += info.columns;
|
| + return db->Execute(sql.c_str());
|
| +}
|
| +
|
| } // anon namespace
|
|
|
| // AppCacheDatabase ----------------------------------------------------------
|
| @@ -154,13 +179,14 @@
|
| AppCacheDatabase::GroupRecord::~GroupRecord() {
|
| }
|
|
|
| -AppCacheDatabase::FallbackNameSpaceRecord::FallbackNameSpaceRecord()
|
| - : cache_id(0) {
|
| +AppCacheDatabase::NamespaceRecord::NamespaceRecord()
|
| + : cache_id(0), type(FALLBACK_NAMESPACE) {
|
| }
|
|
|
| -AppCacheDatabase::FallbackNameSpaceRecord::~FallbackNameSpaceRecord() {
|
| +AppCacheDatabase::NamespaceRecord::~NamespaceRecord() {
|
| }
|
|
|
| +
|
| AppCacheDatabase::AppCacheDatabase(const FilePath& path)
|
| : db_file_path_(path), is_disabled_(false), is_recreating_(false) {
|
| }
|
| @@ -655,61 +681,59 @@
|
| return statement.Run() && db_->GetLastChangeCount();
|
| }
|
|
|
| -bool AppCacheDatabase::FindFallbackNameSpacesForOrigin(
|
| - const GURL& origin, std::vector<FallbackNameSpaceRecord>* records) {
|
| - DCHECK(records && records->empty());
|
| +bool AppCacheDatabase::FindNamespacesForOrigin(
|
| + const GURL& origin,
|
| + std::vector<NamespaceRecord>* intercepts,
|
| + std::vector<NamespaceRecord>* fallbacks) {
|
| + DCHECK(intercepts && intercepts->empty());
|
| + DCHECK(fallbacks && fallbacks->empty());
|
| if (!LazyOpen(false))
|
| return false;
|
|
|
| const char* kSql =
|
| - "SELECT cache_id, origin, namespace_url, fallback_entry_url"
|
| - " FROM FallbackNameSpaces WHERE origin = ?";
|
| + "SELECT cache_id, origin, type, namespace_url, target_url"
|
| + " FROM Namespaces WHERE origin = ?";
|
|
|
| sql::Statement statement;
|
| if (!PrepareCachedStatement(SQL_FROM_HERE, kSql, &statement))
|
| return false;
|
|
|
| statement.BindString(0, origin.spec());
|
| - while (statement.Step()) {
|
| - records->push_back(FallbackNameSpaceRecord());
|
| - ReadFallbackNameSpaceRecord(statement, &records->back());
|
| - DCHECK(records->back().origin == origin);
|
| - }
|
| + ReadNamespaceRecords(&statement, intercepts, fallbacks);
|
| return statement.Succeeded();
|
| }
|
|
|
| -bool AppCacheDatabase::FindFallbackNameSpacesForCache(
|
| - int64 cache_id, std::vector<FallbackNameSpaceRecord>* records) {
|
| - DCHECK(records && records->empty());
|
| +bool AppCacheDatabase::FindNamespacesForCache(
|
| + int64 cache_id,
|
| + std::vector<NamespaceRecord>* intercepts,
|
| + std::vector<NamespaceRecord>* fallbacks) {
|
| + DCHECK(intercepts && intercepts->empty());
|
| + DCHECK(fallbacks && fallbacks->empty());
|
| if (!LazyOpen(false))
|
| return false;
|
|
|
| const char* kSql =
|
| - "SELECT cache_id, origin, namespace_url, fallback_entry_url"
|
| - " FROM FallbackNameSpaces WHERE cache_id = ?";
|
| + "SELECT cache_id, origin, type, namespace_url, target_url"
|
| + " FROM Namespaces WHERE cache_id = ?";
|
|
|
| sql::Statement statement;
|
| if (!PrepareCachedStatement(SQL_FROM_HERE, kSql, &statement))
|
| return false;
|
|
|
| statement.BindInt64(0, cache_id);
|
| - while (statement.Step()) {
|
| - records->push_back(FallbackNameSpaceRecord());
|
| - ReadFallbackNameSpaceRecord(statement, &records->back());
|
| - DCHECK(records->back().cache_id == cache_id);
|
| - }
|
| + ReadNamespaceRecords(&statement, intercepts, fallbacks);
|
| return statement.Succeeded();
|
| }
|
|
|
| -bool AppCacheDatabase::InsertFallbackNameSpace(
|
| - const FallbackNameSpaceRecord* record) {
|
| +bool AppCacheDatabase::InsertNamespace(
|
| + const NamespaceRecord* record) {
|
| if (!LazyOpen(true))
|
| return false;
|
|
|
| const char* kSql =
|
| - "INSERT INTO FallbackNameSpaces"
|
| - " (cache_id, origin, namespace_url, fallback_entry_url)"
|
| - " VALUES (?, ?, ?, ?)";
|
| + "INSERT INTO Namespaces"
|
| + " (cache_id, origin, type, namespace_url, target_url)"
|
| + " VALUES (?, ?, ?, ?, ?)";
|
|
|
| sql::Statement statement;
|
| if (!PrepareCachedStatement(SQL_FROM_HERE, kSql, &statement))
|
| @@ -717,33 +741,34 @@
|
|
|
| statement.BindInt64(0, record->cache_id);
|
| statement.BindString(1, record->origin.spec());
|
| - statement.BindString(2, record->namespace_url.spec());
|
| - statement.BindString(3, record->fallback_entry_url.spec());
|
| + statement.BindInt(2, record->type);
|
| + statement.BindString(3, record->namespace_url.spec());
|
| + statement.BindString(4, record->target_url.spec());
|
| return statement.Run();
|
| }
|
|
|
| -bool AppCacheDatabase::InsertFallbackNameSpaceRecords(
|
| - const std::vector<FallbackNameSpaceRecord>& records) {
|
| +bool AppCacheDatabase::InsertNamespaceRecords(
|
| + const std::vector<NamespaceRecord>& records) {
|
| if (records.empty())
|
| return true;
|
| sql::Transaction transaction(db_.get());
|
| if (!transaction.Begin())
|
| return false;
|
| - std::vector<FallbackNameSpaceRecord>::const_iterator iter = records.begin();
|
| + std::vector<NamespaceRecord>::const_iterator iter = records.begin();
|
| while (iter != records.end()) {
|
| - if (!InsertFallbackNameSpace(&(*iter)))
|
| + if (!InsertNamespace(&(*iter)))
|
| return false;
|
| ++iter;
|
| }
|
| return transaction.Commit();
|
| }
|
|
|
| -bool AppCacheDatabase::DeleteFallbackNameSpacesForCache(int64 cache_id) {
|
| +bool AppCacheDatabase::DeleteNamespacesForCache(int64 cache_id) {
|
| if (!LazyOpen(false))
|
| return false;
|
|
|
| const char* kSql =
|
| - "DELETE FROM FallbackNameSpaces WHERE cache_id = ?";
|
| + "DELETE FROM Namespaces WHERE cache_id = ?";
|
|
|
| sql::Statement statement;
|
| if (!PrepareCachedStatement(SQL_FROM_HERE, kSql, &statement))
|
| @@ -974,14 +999,28 @@
|
| record->response_size = statement.ColumnInt64(4);
|
| }
|
|
|
| -void AppCacheDatabase::ReadFallbackNameSpaceRecord(
|
| - const sql::Statement& statement, FallbackNameSpaceRecord* record) {
|
| - record->cache_id = statement.ColumnInt64(0);
|
| - record->origin = GURL(statement.ColumnString(1));
|
| - record->namespace_url = GURL(statement.ColumnString(2));
|
| - record->fallback_entry_url = GURL(statement.ColumnString(3));
|
| +void AppCacheDatabase::ReadNamespaceRecords(
|
| + sql::Statement* statement,
|
| + NamespaceRecordVector* intercepts,
|
| + NamespaceRecordVector* fallbacks) {
|
| + while (statement->Step()) {
|
| + NamespaceType type = static_cast<NamespaceType>(statement->ColumnInt(2));
|
| + NamespaceRecordVector* records =
|
| + (type == FALLBACK_NAMESPACE) ? fallbacks : intercepts;
|
| + records->push_back(NamespaceRecord());
|
| + ReadNamespaceRecord(statement, &records->back());
|
| + }
|
| }
|
|
|
| +void AppCacheDatabase::ReadNamespaceRecord(
|
| + const sql::Statement* statement, NamespaceRecord* record) {
|
| + record->cache_id = statement->ColumnInt64(0);
|
| + record->origin = GURL(statement->ColumnString(1));
|
| + record->type = static_cast<NamespaceType>(statement->ColumnInt(2));
|
| + record->namespace_url = GURL(statement->ColumnString(3));
|
| + record->target_url = GURL(statement->ColumnString(4));
|
| +}
|
| +
|
| void AppCacheDatabase::ReadOnlineWhiteListRecord(
|
| const sql::Statement& statement, OnlineWhiteListRecord* record) {
|
| record->cache_id = statement.ColumnInt64(0);
|
| @@ -1060,6 +1099,9 @@
|
| for (int i = 0; i < kTableCount; ++i) {
|
| DCHECK(db_->DoesTableExist(kTables[i].table_name));
|
| }
|
| + for (int i = 0; i < kIndexCount; ++i) {
|
| + DCHECK(db_->DoesIndexExist(kIndexes[i].index_name));
|
| + }
|
| #endif
|
|
|
| return true;
|
| @@ -1074,24 +1116,12 @@
|
| return false;
|
|
|
| for (int i = 0; i < kTableCount; ++i) {
|
| - std::string sql("CREATE TABLE ");
|
| - sql += kTables[i].table_name;
|
| - sql += kTables[i].columns;
|
| - if (!db_->Execute(sql.c_str()))
|
| + if (!CreateTable(db_.get(), kTables[i]))
|
| return false;
|
| }
|
|
|
| for (int i = 0; i < kIndexCount; ++i) {
|
| - std::string sql;
|
| - if (kIndexes[i].unique)
|
| - sql += "CREATE UNIQUE INDEX ";
|
| - else
|
| - sql += "CREATE INDEX ";
|
| - sql += kIndexes[i].index_name;
|
| - sql += " ON ";
|
| - sql += kIndexes[i].table_name;
|
| - sql += kIndexes[i].columns;
|
| - if (!db_->Execute(sql.c_str()))
|
| + if (!CreateIndex(db_.get(), kIndexes[i]))
|
| return false;
|
| }
|
|
|
| @@ -1099,8 +1129,46 @@
|
| }
|
|
|
| bool AppCacheDatabase::UpgradeSchema() {
|
| - // Upgrade logic goes here
|
| + if (meta_table_->GetVersionNumber() == 3) {
|
| + DCHECK_EQ(strcmp(kNamespacesTable, kTables[3].table_name), 0);
|
| + DCHECK_EQ(strcmp(kNamespacesTable, kIndexes[6].table_name), 0);
|
| + DCHECK_EQ(strcmp(kNamespacesTable, kIndexes[7].table_name), 0);
|
| + DCHECK_EQ(strcmp(kNamespacesTable, kIndexes[8].table_name), 0);
|
|
|
| + // Migrate from the old "FallbackNameSpaces" to the new "Namespaces" table.
|
| + sql::Transaction transaction(db_.get());
|
| + if (!transaction.Begin() ||
|
| + !CreateTable(db_.get(), kTables[3])) {
|
| + return false;
|
| + }
|
| +
|
| + // Move data from the old table to the new table, setting the
|
| + // 'type' for all current records to the value for FALLBACK_NAMESPACE.
|
| + DCHECK_EQ(0, static_cast<int>(FALLBACK_NAMESPACE));
|
| + if (!db_->Execute(
|
| + "INSERT INTO Namespaces"
|
| + " SELECT cache_id, origin, 0, namespace_url, fallback_entry_url"
|
| + " FROM FallbackNameSpaces")) {
|
| + return false;
|
| + }
|
| +
|
| + // Drop the old table, indexes on that table are also removed by this.
|
| + if (!db_->Execute("DROP TABLE FallbackNameSpaces"))
|
| + return false;
|
| +
|
| + // Create new indexes.
|
| + if (!CreateIndex(db_.get(), kIndexes[6]) ||
|
| + !CreateIndex(db_.get(), kIndexes[7]) ||
|
| + !CreateIndex(db_.get(), kIndexes[8])) {
|
| + return false;
|
| + }
|
| +
|
| + // Finally bump the version numbers and commit it.
|
| + meta_table_->SetVersionNumber(4);
|
| + meta_table_->SetCompatibleVersionNumber(4);
|
| + return transaction.Commit();
|
| + }
|
| +
|
| // If there is no upgrade path for the version on disk to the current
|
| // version, nuke everything and start over.
|
| return DeleteExistingAndCreateNewDatabase();
|
|
|