Commit 35b26745 authored by Victor Costan's avatar Victor Costan Committed by Commit Bot

DOMStorage: Remove support for V1 database schema.

The V2 schema was introduced in WebKit on 2011-07-15, in
https://bugs.webkit.org/show_bug.cgi?id=58762. Removing support for the
V1 schema allows us to remove the plumbing for a SQLite feature that no
other part of the codebase uses.

This CL does mean that a hypothetical user who hasn't upgraded Chrome
for 7 years and suddenly upgrades will have their DOM storage reset. We
generally support database schemas up to 2 years old, so this
hypothetical user will most likely start with a clean slate anyways.

Change-Id: I8e21c525a114ed1da856af5c393d62a0ad8cfb1c
Reviewed-on: https://chromium-review.googlesource.com/1146280Reviewed-by: default avatarDaniel Murphy <dmurph@chromium.org>
Commit-Queue: Daniel Murphy <dmurph@chromium.org>
Cr-Commit-Position: refs/heads/master@{#577266}
parent f2854bc2
......@@ -186,12 +186,8 @@ bool DOMStorageDatabase::LazyOpen(bool create_if_needed) {
// and whether it's usable (i.e. not corrupted).
SchemaVersion current_version = DetectSchemaVersion();
if (current_version == V2) {
if (current_version == V2)
return true;
} else if (current_version == V1) {
if (UpgradeVersion1To2())
return true;
}
}
// This is the exceptional case - to try and recover we'll attempt
......@@ -218,20 +214,7 @@ DOMStorageDatabase::SchemaVersion DOMStorageDatabase::DetectSchemaVersion() {
!db_->DoesColumnExist("ItemTable", "value"))
return INVALID;
// We must use a unique statement here as we aren't going to step it.
sql::Statement statement(
db_->GetUniqueStatement("SELECT key,value from ItemTable LIMIT 1"));
if (statement.DeclaredColumnType(0) != sql::COLUMN_TYPE_TEXT)
return INVALID;
switch (statement.DeclaredColumnType(1)) {
case sql::COLUMN_TYPE_BLOB:
return V2;
case sql::COLUMN_TYPE_TEXT:
return V1;
default:
return INVALID;
}
return V2;
}
bool DOMStorageDatabase::CreateTableV2() {
......@@ -263,32 +246,6 @@ bool DOMStorageDatabase::DeleteFileAndRecreate() {
return false;
}
bool DOMStorageDatabase::UpgradeVersion1To2() {
DCHECK(IsOpen());
DCHECK(DetectSchemaVersion() == V1);
sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE,
"SELECT * FROM ItemTable"));
DCHECK(statement.is_valid());
// Need to migrate from TEXT value column to BLOB.
// Store the current database content so we can re-insert
// the data into the new V2 table.
DOMStorageValuesMap values;
while (statement.Step()) {
base::string16 key = statement.ColumnString16(0);
base::NullableString16 value(statement.ColumnString16(1), false);
values[key] = value;
}
sql::Transaction migration(db_.get());
return migration.Begin() &&
db_->Execute("DROP TABLE ItemTable") &&
CreateTableV2() &&
CommitChanges(false, values) &&
migration.Commit();
}
void DOMStorageDatabase::Close() {
db_.reset(nullptr);
}
......
......@@ -80,8 +80,11 @@ class CONTENT_EXPORT DOMStorageDatabase {
enum SchemaVersion {
INVALID,
V1,
V2
// V1 is deprecated.
// 2011-07-15 - https://bugs.webkit.org/show_bug.cgi?id=58762
V2,
};
// Open the database at file_path_ if it exists already and creates it if
......@@ -105,12 +108,6 @@ class CONTENT_EXPORT DOMStorageDatabase {
// scratch.
bool DeleteFileAndRecreate();
// Version 1 -> 2 migrates the value column in the ItemTable from a TEXT
// to a BLOB. Exisitng data is preserved on success. Returns false if the
// upgrade failed. If true is returned, the database is guaranteed to be at
// version 2.
bool UpgradeVersion1To2();
void Close();
bool IsOpen() const { return db_.get() ? db_->is_open() : false; }
......
......@@ -18,15 +18,6 @@ using base::ASCIIToUTF16;
namespace content {
void CreateV1Table(sql::Connection* db) {
ASSERT_TRUE(db->is_open());
ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
ASSERT_TRUE(db->Execute(
"CREATE TABLE ItemTable ("
"key TEXT UNIQUE ON CONFLICT REPLACE, "
"value TEXT NOT NULL ON CONFLICT FAIL)"));
}
void CreateV2Table(sql::Connection* db) {
ASSERT_TRUE(db->is_open());
ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
......@@ -36,37 +27,15 @@ void CreateV2Table(sql::Connection* db) {
"value BLOB NOT NULL ON CONFLICT FAIL)"));
}
void CreateInvalidKeyColumnTable(sql::Connection* db) {
// Create a table with the key type as FLOAT - this is "invalid"
void CreateInvalidTable(sql::Connection* db) {
// Create a table with out a key column - this is "invalid"
// as far as the DOM Storage db is concerned.
ASSERT_TRUE(db->is_open());
ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
ASSERT_TRUE(db->Execute(
"CREATE TABLE IF NOT EXISTS ItemTable ("
"key FLOAT UNIQUE ON CONFLICT REPLACE, "
"value BLOB NOT NULL ON CONFLICT FAIL)"));
}
void CreateInvalidValueColumnTable(sql::Connection* db) {
// Create a table with the value type as FLOAT - this is "invalid"
// as far as the DOM Storage db is concerned.
ASSERT_TRUE(db->is_open());
ASSERT_TRUE(db->Execute("DROP TABLE IF EXISTS ItemTable"));
ASSERT_TRUE(db->Execute(
"CREATE TABLE IF NOT EXISTS ItemTable ("
"key TEXT UNIQUE ON CONFLICT REPLACE, "
"value FLOAT NOT NULL ON CONFLICT FAIL)"));
}
void InsertDataV1(sql::Connection* db,
const base::string16& key,
const base::string16& value) {
sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE,
"INSERT INTO ItemTable VALUES (?,?)"));
statement.BindString16(0, key);
statement.BindString16(1, value);
ASSERT_TRUE(statement.is_valid());
statement.Run();
}
void CheckValuesMatch(DOMStorageDatabase* db,
const DOMStorageValuesMap& expected) {
......@@ -201,39 +170,13 @@ TEST(DOMStorageDatabaseTest, TestDetectSchemaVersion) {
db.db_.reset(new sql::Connection());
ASSERT_TRUE(db.db_->OpenInMemory());
CreateInvalidValueColumnTable(db.db_.get());
CreateInvalidTable(db.db_.get());
EXPECT_EQ(DOMStorageDatabase::INVALID, db.DetectSchemaVersion());
CreateInvalidKeyColumnTable(db.db_.get());
EXPECT_EQ(DOMStorageDatabase::INVALID, db.DetectSchemaVersion());
CreateV1Table(db.db_.get());
EXPECT_EQ(DOMStorageDatabase::V1, db.DetectSchemaVersion());
CreateV2Table(db.db_.get());
EXPECT_EQ(DOMStorageDatabase::V2, db.DetectSchemaVersion());
}
TEST(DOMStorageDatabaseTest, TestLazyOpenUpgradesDatabase) {
// This test needs to operate with a file on disk so that we
// can create a table at version 1 and then close it again
// so that LazyOpen sees there is work to do (LazyOpen will return
// early if the database is already open).
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::FilePath file_name =
temp_dir.GetPath().AppendASCII("TestDOMStorageDatabase.db");
DOMStorageDatabase db(file_name);
db.db_.reset(new sql::Connection());
ASSERT_TRUE(db.db_->Open(file_name));
CreateV1Table(db.db_.get());
db.Close();
EXPECT_TRUE(db.LazyOpen(true));
EXPECT_EQ(DOMStorageDatabase::V2, db.DetectSchemaVersion());
}
TEST(DOMStorageDatabaseTest, SimpleWriteAndReadBack) {
DOMStorageDatabase db;
......@@ -266,25 +209,6 @@ TEST(DOMStorageDatabaseTest, WriteWithClear) {
CheckValuesMatch(&db, storage);
}
TEST(DOMStorageDatabaseTest, UpgradeFromV1ToV2WithData) {
const base::string16 kCannedKey = ASCIIToUTF16("foo");
const base::NullableString16 kCannedValue(ASCIIToUTF16("bar"), false);
DOMStorageValuesMap expected;
expected[kCannedKey] = kCannedValue;
DOMStorageDatabase db;
db.db_.reset(new sql::Connection());
ASSERT_TRUE(db.db_->OpenInMemory());
CreateV1Table(db.db_.get());
InsertDataV1(db.db_.get(), kCannedKey, kCannedValue.string());
ASSERT_TRUE(db.UpgradeVersion1To2());
EXPECT_EQ(DOMStorageDatabase::V2, db.DetectSchemaVersion());
CheckValuesMatch(&db, expected);
}
TEST(DOMStorageDatabaseTest, TestSimpleRemoveOneValue) {
DOMStorageDatabase db;
......
......@@ -216,22 +216,6 @@ ColType Statement::ColumnType(int col) const {
return static_cast<ColType>(sqlite3_column_type(ref_->stmt(), col));
}
ColType Statement::DeclaredColumnType(int col) const {
std::string column_type = base::ToLowerASCII(
sqlite3_column_decltype(ref_->stmt(), col));
if (column_type == "integer")
return COLUMN_TYPE_INTEGER;
else if (column_type == "float")
return COLUMN_TYPE_FLOAT;
else if (column_type == "text")
return COLUMN_TYPE_TEXT;
else if (column_type == "blob")
return COLUMN_TYPE_BLOB;
return COLUMN_TYPE_NULL;
}
bool Statement::ColumnBool(int col) const {
return !!ColumnInt(col);
}
......
......@@ -124,7 +124,6 @@ class SQL_EXPORT Statement {
// where that type is not the native type. For safety, call ColumnType only
// on a column before getting the value out in any way.
ColType ColumnType(int col) const;
ColType DeclaredColumnType(int col) const;
// These all take a 0-based argument index.
bool ColumnBool(int col) const;
......
......@@ -91,6 +91,9 @@ config("chromium_sqlite3_compile_options") {
# Chromium calls sqlite3_reset() correctly to reset prepared statements.
"SQLITE_OMIT_AUTORESET",
# Chrome does not use sqlite3_column_decltype().
"SQLITE_OMIT_DECLTYPE",
# Chromium does not use sqlite3_{get,free}_table().
"SQLITE_OMIT_GET_TABLE",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment