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

Side by Side Diff: components/offline_pages/offline_page_metadata_store_sql.cc

Issue 2336813002: [Offline pages] OPMStoreSQL: Upgrade to M55, Upgrade refactoring, conversion refactoring (Closed)
Patch Set: Addressing CR feedback Created 4 years, 3 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
« no previous file with comments | « components/offline_pages/offline_page_metadata_store_sql.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/offline_pages/offline_page_metadata_store_sql.h" 5 #include "components/offline_pages/offline_page_metadata_store_sql.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/files/file_path.h" 8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h" 9 #include "base/files/file_util.h"
10 #include "base/location.h" 10 #include "base/location.h"
(...skipping 15 matching lines...) Expand all
26 26
27 // This is a macro instead of a const so that 27 // This is a macro instead of a const so that
28 // it can be used inline in other SQL statements below. 28 // it can be used inline in other SQL statements below.
29 #define OFFLINE_PAGES_TABLE_NAME "offlinepages_v1" 29 #define OFFLINE_PAGES_TABLE_NAME "offlinepages_v1"
30 30
31 bool CreateOfflinePagesTable(sql::Connection* db) { 31 bool CreateOfflinePagesTable(sql::Connection* db) {
32 const char kSql[] = "CREATE TABLE IF NOT EXISTS " OFFLINE_PAGES_TABLE_NAME 32 const char kSql[] = "CREATE TABLE IF NOT EXISTS " OFFLINE_PAGES_TABLE_NAME
33 "(offline_id INTEGER PRIMARY KEY NOT NULL," 33 "(offline_id INTEGER PRIMARY KEY NOT NULL,"
34 " creation_time INTEGER NOT NULL," 34 " creation_time INTEGER NOT NULL,"
35 " file_size INTEGER NOT NULL," 35 " file_size INTEGER NOT NULL,"
36 " version INTEGER NOT NULL,"
37 " last_access_time INTEGER NOT NULL," 36 " last_access_time INTEGER NOT NULL,"
38 " access_count INTEGER NOT NULL," 37 " access_count INTEGER NOT NULL,"
39 // TODO(fgorski): Remove. Never used.
40 " status INTEGER NOT NULL DEFAULT 0,"
41 // A note on this field: It will be NULL for now and is
42 // reserved for later use. We will treat NULL as
43 // "Unknown" in any subsequent queries for user_initiated
44 // values.
45 " user_initiated INTEGER," // this is actually a boolean
46 " expiration_time INTEGER NOT NULL DEFAULT 0," 38 " expiration_time INTEGER NOT NULL DEFAULT 0,"
47 " client_namespace VARCHAR NOT NULL," 39 " client_namespace VARCHAR NOT NULL,"
48 " client_id VARCHAR NOT NULL," 40 " client_id VARCHAR NOT NULL,"
49 " online_url VARCHAR NOT NULL," 41 " online_url VARCHAR NOT NULL,"
50 // TODO(fgorski): Remove. Never used.
51 " offline_url VARCHAR NOT NULL DEFAULT '',"
52 " file_path VARCHAR NOT NULL," 42 " file_path VARCHAR NOT NULL,"
53 " title VARCHAR NOT NULL DEFAULT ''" 43 " title VARCHAR NOT NULL DEFAULT ''"
54 ")"; 44 ")";
55 return db->Execute(kSql); 45 return db->Execute(kSql);
56 } 46 }
57 47
58 bool RefreshColumnsFrom52To54(sql::Connection* db) { 48 bool UpgradeWithQuery(sql::Connection* db, const char* upgrade_sql) {
59 if (!db->Execute("ALTER TABLE " OFFLINE_PAGES_TABLE_NAME 49 if (!db->Execute("ALTER TABLE " OFFLINE_PAGES_TABLE_NAME
60 " RENAME TO temp_" OFFLINE_PAGES_TABLE_NAME)) { 50 " RENAME TO temp_" OFFLINE_PAGES_TABLE_NAME)) {
61 return false; 51 return false;
62 } 52 }
63 if (!CreateOfflinePagesTable(db)) 53 if (!CreateOfflinePagesTable(db))
64 return false; 54 return false;
65 if (!db->Execute( 55 if (!db->Execute(upgrade_sql))
66 "INSERT INTO " OFFLINE_PAGES_TABLE_NAME
67 " (offline_id, creation_time, file_size, version, last_access_time, "
68 "access_count, status, user_initiated, client_namespace, client_id, "
69 "online_url, offline_url, file_path) "
70 "SELECT offline_id, creation_time, file_size, version, "
71 "last_access_time, "
72 "access_count, status, user_initiated, client_namespace, client_id, "
73 "online_url, offline_url, file_path "
74 "FROM temp_" OFFLINE_PAGES_TABLE_NAME)) {
75 return false; 56 return false;
76 }
77 if (!db->Execute("DROP TABLE IF EXISTS temp_" OFFLINE_PAGES_TABLE_NAME)) 57 if (!db->Execute("DROP TABLE IF EXISTS temp_" OFFLINE_PAGES_TABLE_NAME))
78 return false; 58 return false;
79
80 return true; 59 return true;
81 } 60 }
82 61
83 bool RefreshColumnsFrom53To54(sql::Connection* db) { 62 bool UpgradeFrom52(sql::Connection* db) {
84 if (!db->Execute("ALTER TABLE " OFFLINE_PAGES_TABLE_NAME 63 const char kSql[] =
85 " RENAME TO temp_" OFFLINE_PAGES_TABLE_NAME)) { 64 "INSERT INTO " OFFLINE_PAGES_TABLE_NAME
86 return false; 65 " (offline_id, creation_time, file_size, last_access_time, "
87 } 66 "access_count, client_namespace, client_id, "
88 if (!CreateOfflinePagesTable(db)) 67 "online_url, file_path) "
89 return false; 68 "SELECT "
90 if (!db->Execute( 69 "offline_id, creation_time, file_size, last_access_time, "
91 "INSERT INTO " OFFLINE_PAGES_TABLE_NAME 70 "access_count, client_namespace, client_id, "
92 " (offline_id, creation_time, file_size, version, last_access_time, " 71 "online_url, file_path "
93 "access_count, status, user_initiated, client_namespace, client_id, " 72 "FROM temp_" OFFLINE_PAGES_TABLE_NAME;
94 "online_url, offline_url, file_path, expiration_time) " 73 return UpgradeWithQuery(db, kSql);
95 "SELECT offline_id, creation_time, file_size, version, " 74 }
96 "last_access_time, "
97 "access_count, status, user_initiated, client_namespace, client_id, "
98 "online_url, offline_url, file_path, expiration_time "
99 "FROM temp_" OFFLINE_PAGES_TABLE_NAME)) {
100 return false;
101 }
102 if (!db->Execute("DROP TABLE IF EXISTS temp_" OFFLINE_PAGES_TABLE_NAME))
103 return false;
104 75
105 return true; 76 bool UpgradeFrom53(sql::Connection* db) {
77 const char kSql[] =
78 "INSERT INTO " OFFLINE_PAGES_TABLE_NAME
79 " (offline_id, creation_time, file_size, last_access_time, "
80 "access_count, expiration_time, client_namespace, client_id, "
81 "online_url, file_path) "
82 "SELECT "
83 "offline_id, creation_time, file_size, last_access_time, "
84 "access_count, expiration_time, client_namespace, client_id, "
85 "online_url, file_path "
86 "FROM temp_" OFFLINE_PAGES_TABLE_NAME;
87 return UpgradeWithQuery(db, kSql);
88 }
89
90 bool UpgradeFrom54(sql::Connection* db) {
91 const char kSql[] =
92 "INSERT INTO " OFFLINE_PAGES_TABLE_NAME
93 " (offline_id, creation_time, file_size, last_access_time, "
94 "access_count, expiration_time, client_namespace, client_id, "
95 "online_url, file_path, title) "
96 "SELECT "
97 "offline_id, creation_time, file_size, last_access_time, "
98 "access_count, expiration_time, client_namespace, client_id, "
99 "online_url, file_path, title "
100 "FROM temp_" OFFLINE_PAGES_TABLE_NAME;
101 return UpgradeWithQuery(db, kSql);
106 } 102 }
107 103
108 bool CreateSchema(sql::Connection* db) { 104 bool CreateSchema(sql::Connection* db) {
109 // If you create a transaction but don't Commit() it is automatically 105 // If you create a transaction but don't Commit() it is automatically
110 // rolled back by its destructor when it falls out of scope. 106 // rolled back by its destructor when it falls out of scope.
111 sql::Transaction transaction(db); 107 sql::Transaction transaction(db);
112 if (!transaction.Begin()) 108 if (!transaction.Begin())
113 return false; 109 return false;
114 110
115 if (!db->DoesTableExist(OFFLINE_PAGES_TABLE_NAME)) { 111 if (!db->DoesTableExist(OFFLINE_PAGES_TABLE_NAME)) {
116 if (!CreateOfflinePagesTable(db)) 112 if (!CreateOfflinePagesTable(db))
117 return false; 113 return false;
118 } 114 }
119 115
116 // Upgrade section. Details are described in the header file.
120 if (!db->DoesColumnExist(OFFLINE_PAGES_TABLE_NAME, "expiration_time")) { 117 if (!db->DoesColumnExist(OFFLINE_PAGES_TABLE_NAME, "expiration_time")) {
121 if (!RefreshColumnsFrom52To54(db)) 118 if (!UpgradeFrom52(db))
122 return false; 119 return false;
123 } else if (!db->DoesColumnExist(OFFLINE_PAGES_TABLE_NAME, "title")) { 120 } else if (!db->DoesColumnExist(OFFLINE_PAGES_TABLE_NAME, "title")) {
124 if (!RefreshColumnsFrom53To54(db)) 121 if (!UpgradeFrom53(db))
122 return false;
123 } else if (db->DoesColumnExist(OFFLINE_PAGES_TABLE_NAME, "offline_url")) {
124 if (!UpgradeFrom54(db))
125 return false; 125 return false;
126 } 126 }
127 127
128 // TODO(bburns): Add indices here. 128 // TODO(bburns): Add indices here.
129 return transaction.Commit(); 129 return transaction.Commit();
130 } 130 }
131 131
132 bool DeleteByOfflineId(sql::Connection* db, int64_t offline_id) { 132 bool DeleteByOfflineId(sql::Connection* db, int64_t offline_id) {
133 static const char kSql[] = 133 static const char kSql[] =
134 "DELETE FROM " OFFLINE_PAGES_TABLE_NAME " WHERE offline_id=?"; 134 "DELETE FROM " OFFLINE_PAGES_TABLE_NAME " WHERE offline_id=?";
135 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); 135 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
136 statement.BindInt64(0, offline_id); 136 statement.BindInt64(0, offline_id);
137 return statement.Run(); 137 return statement.Run();
138 } 138 }
139 139
140 base::FilePath GetPathFromUTF8String(const std::string& path_string) {
141 #if defined(OS_POSIX)
142 return base::FilePath(path_string);
143 #elif defined(OS_WIN)
144 return base::FilePath(base::UTF8ToWide(path_string));
145 #else
146 #error Unknown OS
147 #endif
148 }
149
150 std::string GetUTF8StringFromPath(const base::FilePath& path) {
151 #if defined(OS_POSIX)
152 return path.value();
153 #elif defined(OS_WIN)
154 return base::WideToUTF8(path.value());
155 #else
156 #error Unknown OS
157 #endif
158 }
159
140 // Create an offline page item from a SQL result. Expects complete rows with 160 // Create an offline page item from a SQL result. Expects complete rows with
141 // all columns present. 161 // all columns present.
142 OfflinePageItem MakeOfflinePageItem(sql::Statement* statement) { 162 OfflinePageItem MakeOfflinePageItem(sql::Statement* statement) {
143 int64_t id = statement->ColumnInt64(0); 163 int64_t id = statement->ColumnInt64(0);
144 base::Time creation_time = 164 base::Time creation_time =
145 base::Time::FromInternalValue(statement->ColumnInt64(1)); 165 base::Time::FromInternalValue(statement->ColumnInt64(1));
146 int64_t file_size = statement->ColumnInt64(2); 166 int64_t file_size = statement->ColumnInt64(2);
147 ClientId client_id(statement->ColumnString(9), 167 base::Time last_access_time =
148 statement->ColumnString(10)); 168 base::Time::FromInternalValue(statement->ColumnInt64(3));
149 GURL url(statement->ColumnString(11)); 169 int access_count = statement->ColumnInt(4);
150 #if defined(OS_POSIX) 170 base::Time expiration_time =
151 base::FilePath path(statement->ColumnString(13)); 171 base::Time::FromInternalValue(statement->ColumnInt64(5));
152 #elif defined(OS_WIN) 172 ClientId client_id(statement->ColumnString(6), statement->ColumnString(7));
153 base::FilePath path(base::UTF8ToWide(statement->ColumnString(13))); 173 GURL url(statement->ColumnString(8));
154 #else 174 base::FilePath path(GetPathFromUTF8String(statement->ColumnString(9)));
155 #error Unknown OS 175 base::string16 title = statement->ColumnString16(10);
156 #endif
157 176
158 OfflinePageItem item(url, id, client_id, path, file_size, creation_time); 177 OfflinePageItem item(url, id, client_id, path, file_size, creation_time);
159 item.version = statement->ColumnInt(3); 178 item.last_access_time = last_access_time;
160 item.last_access_time = base::Time::FromInternalValue( 179 item.access_count = access_count;
161 statement->ColumnInt64(4)); 180 item.expiration_time = expiration_time;
162 item.access_count = statement->ColumnInt(5); 181 item.title = title;
163 item.expiration_time =
164 base::Time::FromInternalValue(statement->ColumnInt64(8));
165 item.title = statement->ColumnString16(14);
166 return item; 182 return item;
167 } 183 }
168 184
169 bool InsertOrReplace(sql::Connection* db, const OfflinePageItem& item) { 185 bool InsertOrReplace(sql::Connection* db, const OfflinePageItem& item) {
170 const char kSql[] = 186 const char kSql[] =
171 "INSERT OR REPLACE INTO " OFFLINE_PAGES_TABLE_NAME 187 "INSERT OR REPLACE INTO " OFFLINE_PAGES_TABLE_NAME
172 " (offline_id, online_url, client_namespace, client_id, file_path, " 188 " (offline_id, online_url, client_namespace, client_id, file_path, "
173 "file_size, creation_time, last_access_time, version, access_count, " 189 "file_size, creation_time, last_access_time, access_count, "
174 "expiration_time, title)" 190 "expiration_time, title)"
175 " VALUES " 191 " VALUES "
176 " (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; 192 " (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
177 193
178 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); 194 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
179 statement.BindInt64(0, item.offline_id); 195 statement.BindInt64(0, item.offline_id);
180 statement.BindString(1, item.url.spec()); 196 statement.BindString(1, item.url.spec());
181 statement.BindString(2, item.client_id.name_space); 197 statement.BindString(2, item.client_id.name_space);
182 statement.BindString(3, item.client_id.id); 198 statement.BindString(3, item.client_id.id);
183 #if defined(OS_POSIX) 199 statement.BindString(4, GetUTF8StringFromPath(item.file_path));
184 std::string path_string = item.file_path.value();
185 #elif defined(OS_WIN)
186 std::string path_string = base::WideToUTF8(item.file_path.value());
187 #else
188 #error Unknown OS
189 #endif
190 statement.BindString(4, path_string);
191 statement.BindInt64(5, item.file_size); 200 statement.BindInt64(5, item.file_size);
192 statement.BindInt64(6, item.creation_time.ToInternalValue()); 201 statement.BindInt64(6, item.creation_time.ToInternalValue());
193 statement.BindInt64(7, item.last_access_time.ToInternalValue()); 202 statement.BindInt64(7, item.last_access_time.ToInternalValue());
194 statement.BindInt(8, item.version); 203 statement.BindInt(8, item.access_count);
195 statement.BindInt(9, item.access_count); 204 statement.BindInt64(9, item.expiration_time.ToInternalValue());
196 statement.BindInt64(10, item.expiration_time.ToInternalValue()); 205 statement.BindString16(10, item.title);
197 statement.BindString16(11, item.title);
198 return statement.Run(); 206 return statement.Run();
199 } 207 }
200 208
201 bool InitDatabase(sql::Connection* db, base::FilePath path) { 209 bool InitDatabase(sql::Connection* db, base::FilePath path) {
202 db->set_page_size(4096); 210 db->set_page_size(4096);
203 db->set_cache_size(500); 211 db->set_cache_size(500);
204 db->set_histogram_tag("OfflinePageMetadata"); 212 db->set_histogram_tag("OfflinePageMetadata");
205 db->set_exclusive_locking(); 213 db->set_exclusive_locking();
206 214
207 base::File::Error err; 215 base::File::Error err;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 if (statement.Succeeded()) { 268 if (statement.Succeeded()) {
261 NotifyLoadResult(runner, callback, OfflinePageMetadataStore::LOAD_SUCCEEDED, 269 NotifyLoadResult(runner, callback, OfflinePageMetadataStore::LOAD_SUCCEEDED,
262 result); 270 result);
263 } else { 271 } else {
264 result.clear(); 272 result.clear();
265 NotifyLoadResult(runner, callback, 273 NotifyLoadResult(runner, callback,
266 OfflinePageMetadataStore::STORE_LOAD_FAILED, result); 274 OfflinePageMetadataStore::STORE_LOAD_FAILED, result);
267 } 275 }
268 } 276 }
269 277
270 void AddOrUpdateOfflinePageSync( 278 void AddOrUpdateOfflinePageSync(
dewittj 2016/09/13 21:43:51 nit: I'd avoid moving these functions just because
fgorski 2016/09/13 22:08:59 Move had to happen to clean up the interface and b
271 const OfflinePageItem& offline_page, 279 const OfflinePageItem& offline_page,
272 sql::Connection* db, 280 sql::Connection* db,
273 scoped_refptr<base::SingleThreadTaskRunner> runner, 281 scoped_refptr<base::SingleThreadTaskRunner> runner,
274 const OfflinePageMetadataStore::UpdateCallback& callback) { 282 const OfflinePageMetadataStore::UpdateCallback& callback) {
275 // TODO(bburns): add UMA metrics here (and for levelDB). 283 // TODO(bburns): add UMA metrics here (and for levelDB).
dewittj 2016/09/13 21:43:51 But if you do move the functions, it might be wise
fgorski 2016/09/13 22:08:59 I'll get to that later.
276 bool ok = InsertOrReplace(db, offline_page); 284 bool ok = InsertOrReplace(db, offline_page);
277 runner->PostTask(FROM_HERE, base::Bind(callback, ok)); 285 runner->PostTask(FROM_HERE, base::Bind(callback, ok));
278 } 286 }
279 287
280 void RemoveOfflinePagesSync( 288 void RemoveOfflinePagesSync(
281 const std::vector<int64_t>& offline_ids, 289 const std::vector<int64_t>& offline_ids,
282 sql::Connection* db, 290 sql::Connection* db,
283 scoped_refptr<base::SingleThreadTaskRunner> runner, 291 scoped_refptr<base::SingleThreadTaskRunner> runner,
284 const OfflinePageMetadataStore::UpdateCallback& callback) { 292 const OfflinePageMetadataStore::UpdateCallback& callback) {
285 // TODO(bburns): add UMA metrics here (and for levelDB). 293 // TODO(bburns): add UMA metrics here (and for levelDB).
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 DCHECK(db_.get()); 433 DCHECK(db_.get());
426 if (!db_.get()) { 434 if (!db_.get()) {
427 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, 435 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
428 base::Bind(callback)); 436 base::Bind(callback));
429 return false; 437 return false;
430 } 438 }
431 return true; 439 return true;
432 } 440 }
433 441
434 } // namespace offline_pages 442 } // namespace offline_pages
OLDNEW
« no previous file with comments | « components/offline_pages/offline_page_metadata_store_sql.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698