Index: webkit/dom_storage/local_storage_database.cc |
diff --git a/webkit/dom_storage/local_storage_database.cc b/webkit/dom_storage/local_storage_database.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..95717c164d32d968a0cf9dd49c9e1019d3f15a43 |
--- /dev/null |
+++ b/webkit/dom_storage/local_storage_database.cc |
@@ -0,0 +1,154 @@ |
+// Copyright (c) 2012 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 "webkit/dom_storage/local_storage_database.h" |
+ |
+#include <string> |
+ |
+#include "base/logging.h" |
+#include "base/utf_string_conversions.h" |
+#include "sql/statement.h" |
+#include "sql/transaction.h" |
+ |
+namespace dom_storage { |
+ |
+LocalStorageDatabase::LocalStorageDatabase(const FilePath& file_path) |
+ : file_path_(file_path), |
+ db_(NULL) { |
+} |
+ |
+LocalStorageDatabase::~LocalStorageDatabase() { |
+ if (IsOpen()) |
+ Close(); |
+} |
+ |
+bool LocalStorageDatabase::Open() { |
+ if (IsOpen()) |
+ return true; |
+ |
+ db_.reset(new sql::Connection()); |
+ bool is_open = db_->Open(file_path_); |
michaeln
2012/01/24 00:18:16
WebCore uses sqlite3_open16 where as the sql::Conn
benm (inactive)
2012/01/24 10:47:01
Good spot!
|
+ |
+ if (!is_open) |
+ LOG(WARNING) << "Unable to open Database at " << file_path_.value(); |
+ |
+ meta_table_.Init(db_.get(), 1, 1); |
michaeln
2012/01/24 00:18:16
... similarly, since this isn't in the current sch
benm (inactive)
2012/01/24 10:47:01
Fair enough, but this won't stop us using a WebCor
|
+ |
+ return is_open; |
+} |
+ |
+bool LocalStorageDatabase::Init() { |
+ if (!IsOpen()) |
+ return false; |
+ |
+ if (db_->DoesTableExist("ItemTable")) { |
+ bool success = UpgradeVersion1To2IfNeeded(); |
+ if (success) |
+ meta_table_.SetVersionNumber(2); |
+ return success; |
+ } else |
+ return CreateTable(); |
+} |
+ |
+void LocalStorageDatabase::Close() { |
+ if (!IsOpen()) |
+ return; |
+ |
+ DCHECK(db_.get()); |
+ |
+ meta_table_.Reset(); |
+ |
+ db_->Close(); |
+ db_.reset(NULL); |
+} |
+ |
+bool LocalStorageDatabase::CreateTable() { |
+ if (!IsOpen()) |
+ return false; |
+ |
+ bool success = db_->Execute( |
+ "CREATE TABLE IF NOT EXISTS ItemTable (" |
+ "key TEXT UNIQUE ON CONFLICT REPLACE, " |
+ "value BLOB NOT NULL ON CONFLICT FAIL)"); |
+ if (success) |
+ meta_table_.SetVersionNumber(2); |
+ return success; |
+} |
+ |
+std::map<string16, string16> LocalStorageDatabase::ReadAllValues() const { |
+ std::map<string16, string16> values; |
+ if (!IsOpen()) |
+ return values; |
+ |
+ sql::Statement stmt(db_->GetCachedStatement(SQL_FROM_HERE, |
+ "SELECT * from ItemTable")); |
+ DCHECK(stmt.is_valid()); |
+ if (stmt) { |
+ while (stmt.Step()) { |
+ string16 key = stmt.ColumnString16(0); |
+ |
+ std::string result; |
+ stmt.ColumnBlobAsString(1, &result); |
+ string16 value = UTF8ToUTF16(result); |
+ values[key] = value; |
+ } |
+ } |
+ |
+ return values; |
+} |
+ |
+bool LocalStorageDatabase::WriteAllValues( |
+ const std::map<string16, string16>& values) { |
+ if (!IsOpen()) |
+ return false; |
+ |
+ std::map<string16, string16>::const_iterator it = values.begin(); |
+ for(; it != values.end(); ++it) { |
+ sql::Statement stmt(db_->GetCachedStatement(SQL_FROM_HERE, |
+ "INSERT INTO ItemTable VALUES (?,?)")); |
+ string16 key = it->first; |
+ string16 value = it->second; |
+ stmt.BindString16(0, key); |
+ stmt.BindBlob(1, UTF16ToUTF8(value).c_str(), value.size()); |
+ DCHECK(stmt.is_valid()); |
+ stmt.Run(); |
+ } |
+ return true; |
+} |
+ |
+bool LocalStorageDatabase::UpgradeVersion1To2IfNeeded() { |
michaeln
2012/01/24 00:18:16
Code to utilize the new schema has been in used fo
benm (inactive)
2012/01/24 10:47:01
I wondered about that too, but the upgrade process
|
+ sql::Statement stmt(db_->GetCachedStatement(SQL_FROM_HERE, |
+ "SELECT value FROM ItemTable")); |
+ DCHECK(stmt.is_valid()); |
+ if (!stmt) |
+ return false; |
+ |
+ // Quick check to see if we need to upgrade or not. |
+ if (stmt.DeclaredColumnType(0) == sql::COLUMN_TYPE_BLOB) |
+ return true; |
+ |
+ // Need to migrate from TEXT value column to BLOB. |
+ std::map<string16, string16> values; |
+ while (stmt.Step()) { |
+ string16 key = stmt.ColumnString16(0); |
+ string16 value = stmt.ColumnString16(1); |
+ values[key] = value; |
+ } |
+ |
+ { |
+ sql::Transaction migration(db_.get()); |
+ if (migration.Begin()) { |
+ if (db_->Execute("DROP TABLE ItemTable")) { |
+ CreateTable(); |
+ if (WriteAllValues(values)) { |
+ migration.Commit(); |
+ return true; |
+ } |
+ } |
+ } |
+ } |
+ return false; |
+} |
+ |
+} // namespace dom_storage |