Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(197)

Side by Side Diff: webkit/dom_storage/dom_storage_database.cc

Issue 9159020: Create a class to represent a DOM Storage Database. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: DomStorageDatabase for backing local storage to disk. Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "webkit/dom_storage/dom_storage_database.h"
6
7 #include <string>
8
9 #include "base/logging.h"
10 #include "base/utf_string_conversions.h"
11 #include "sql/diagnostic_error_delegate.h"
12 #include "sql/statement.h"
13 #include "sql/transaction.h"
14
15 namespace {
16
17 class HistogramUniquifier {
18 public:
19 static const char* name() { return "Sqlite.DomStorageDatabase.Error"; }
20 };
21
22 sql::ErrorDelegate* GetErrorHandlerForDomStorageDatabase() {
23 return new sql::DiagnosticErrorDelegate<HistogramUniquifier>();
24 }
25
26 } // anon namespace
27
28 namespace dom_storage {
29
30 DomStorageDatabase::DomStorageDatabase(const FilePath& file_path)
31 : file_path_(file_path),
32 db_(NULL) {
33 DCHECK(!file_path_.empty());
34 }
35
36 DomStorageDatabase::~DomStorageDatabase() {
37 if (IsOpen())
38 Close();
michaeln 2012/01/31 22:45:32 Since sql::Connection dtor will close automaticall
benm (inactive) 2012/02/01 15:42:09 Close is private and useful in the unit tests. I c
39 }
40
41 bool DomStorageDatabase::LazyOpen() {
michaeln 2012/01/31 22:45:32 can you reorder the methods in the .cc file to mat
benm (inactive) 2012/02/01 15:42:09 Done.
42 if (IsOpen())
43 return true;
44
45 db_.reset(new sql::Connection());
46 bool is_open = db_->Open(file_path_);
47 db_->set_error_delegate(GetErrorHandlerForDomStorageDatabase());
michaeln 2012/01/31 22:45:32 If the db->Open() method can invoke the error dele
benm (inactive) 2012/02/01 15:42:09 The docs in sql::Connection actually say that it s
48
49 if (!is_open) {
50 LOG(WARNING) << "Unable to open Database at " << file_path_.value();
51 return false;
52 }
53
54 // sql::Connection uses UTF-8 encoding, but WebCore style databases use
55 // UTF-16, so ensure we match.
56 ignore_result(db_->Execute("PRAGMA encoding=\"UTF-16\""));
57
58 // Ensure we're at the correct version.
59 if (db_->DoesTableExist("ItemTable")) {
60 if (UpgradeVersion1To2IfNeeded())
61 return true;
62 else {
63 // Upgrade failed, drop table and start fresh.
64 if (db_->Execute("DROP TABLE ItemTable"))
65 return CreateTable();
66 else
67 return false;
68 }
69 } else
70 return CreateTable();
michaeln 2012/01/31 22:45:32 style nit: since the if { block } has brackets, th
benm (inactive) 2012/02/01 15:42:09 gah, webkit style on the brain :)
71 }
72
73 void DomStorageDatabase::Close() {
74 if (!LazyOpen())
michaeln 2012/01/31 22:45:32 at this point, there's no reason to open if not al
benm (inactive) 2012/02/01 15:42:09 Good spot, think I was a little too generous with
75 return;
76
77 db_->Close();
78 db_.reset(NULL);
79 }
80
81 bool DomStorageDatabase::CreateTable() {
82 // Current version is 2.
83 return CreateTableV2();
84 }
85
86 bool DomStorageDatabase::CreateTableV2() {
87 if (!LazyOpen())
88 return false;
89
90 return db_->Execute(
91 "CREATE TABLE IF NOT EXISTS ItemTable ("
92 "key TEXT UNIQUE ON CONFLICT REPLACE, "
93 "value BLOB NOT NULL ON CONFLICT FAIL)");
94 }
95
96 void DomStorageDatabase::ReadAllValues(
97 DomStorageDatabase::ValuesMap* result) {
98 if (!LazyOpen())
99 return;
100
101 sql::Statement stmt(db_->GetCachedStatement(SQL_FROM_HERE,
102 "SELECT * from ItemTable"));
103 DCHECK(stmt.is_valid());
104 if (!stmt)
105 return;
106
107 while (stmt.Step()) {
108 string16 key = stmt.ColumnString16(0);
109 string16 value;
110 stmt.ColumnBlobAsString16(1, &value);
111 (*result)[key] = value;
112 }
113 }
114
115 bool DomStorageDatabase::WriteValues(const ValuesMap& values) {
116 if (!LazyOpen())
117 return false;
118
119 ValuesMap::const_iterator it = values.begin();
120 sql::Transaction transaction(db_.get());
121 if (!transaction.Begin())
122 return false;
123
124 for(; it != values.end(); ++it) {
125 sql::Statement stmt(db_->GetCachedStatement(SQL_FROM_HERE,
126 "INSERT INTO ItemTable VALUES (?,?)"));
127 string16 key = it->first;
128 string16 value = it->second;
129 stmt.BindString16(0, key);
130 stmt.BindBlob(1, value.data(), value.length() * sizeof(char16));
131 DCHECK(stmt.is_valid());
132 stmt.Run();
133 }
134 transaction.Commit();
135 return true;
michaeln 2012/01/31 22:45:32 return transaction.Commit();
benm (inactive) 2012/02/01 15:42:09 Done.
136 }
137
138 bool DomStorageDatabase::RemoveValues(const ValuesSet& keys) {
139 if (!LazyOpen())
140 return false;
141
142 ValuesSet::const_iterator it = keys.begin();
143
144 sql::Transaction transaction(db_.get());
145 if (!transaction.Begin())
146 return false;
147
148 for ( ; it != keys.end(); ++it) {
149 sql::Statement stmt(db_->GetCachedStatement(SQL_FROM_HERE,
150 "DELETE FROM ItemTable WHERE key=?"));
151 stmt.BindString16(0, *it);
152 DCHECK(stmt.is_valid());
153 stmt.Run();
154 }
155 transaction.Commit();
156 return true;
157 }
158
159 bool DomStorageDatabase::UpgradeVersion1To2IfNeeded() {
160 sql::Statement stmt(db_->GetCachedStatement(SQL_FROM_HERE,
161 "SELECT * FROM ItemTable"));
162 DCHECK(stmt.is_valid());
163 if (!stmt)
164 return false;
165
166 // Quick check to see if we need to upgrade or not. The single
167 // effect of V1 -> V2 is to change the value column from type
168 // TEXT to type BLOB.
169 sql::ColType valueColumnType = stmt.DeclaredColumnType(1);
170 if (valueColumnType == sql::COLUMN_TYPE_BLOB)
171 return true;
172
173 if (valueColumnType != sql::COLUMN_TYPE_TEXT) {
174 // Something is messed up. This is not a V1 database.
175 return false;
176 }
177
178 // Need to migrate from TEXT value column to BLOB.
179 ValuesMap values;
180 while (stmt.Step()) {
181 string16 key = stmt.ColumnString16(0);
182 string16 value = stmt.ColumnString16(1);
183 values[key] = value;
184 }
185
186 {
michaeln 2012/01/31 22:45:32 why the extra scope
benm (inactive) 2012/02/01 15:42:09 hmm, I think I used to have some extra stuff after
187 sql::Transaction migration(db_.get());
188 if (migration.Begin()) {
189 if (db_->Execute("DROP TABLE ItemTable")) {
190 CreateTableV2();
191 if (WriteValues(values)) {
192 migration.Commit();
michaeln 2012/01/31 22:45:32 return migration.Commit()?
benm (inactive) 2012/02/01 15:42:09 Done.
193 return true;
194 }
195 }
196 }
197 }
198 return false;
199 }
200
201 } // namespace dom_storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698