OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "sql/meta_table.h" | 5 #include "sql/meta_table.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
10 #include "sql/connection.h" | 10 #include "sql/connection.h" |
11 #include "sql/statement.h" | 11 #include "sql/statement.h" |
12 #include "sql/transaction.h" | 12 #include "sql/transaction.h" |
13 | 13 |
14 namespace { | 14 namespace { |
15 | 15 |
16 // Key used in our meta table for version numbers. | 16 // Keys understood directly by sql:MetaTable. |
17 const char kVersionKey[] = "version"; | 17 const char kVersionKey[] = "version"; |
18 const char kCompatibleVersionKey[] = "last_compatible_version"; | 18 const char kCompatibleVersionKey[] = "last_compatible_version"; |
| 19 const char kMmapStatusKey[] = "mmap_status"; |
19 | 20 |
20 // Used to track success/failure of deprecation checks. | 21 // Used to track success/failure of deprecation checks. |
21 enum DeprecationEventType { | 22 enum DeprecationEventType { |
22 // Database has info, but no meta table. This is probably bad. | 23 // Database has info, but no meta table. This is probably bad. |
23 DEPRECATION_DATABASE_NOT_EMPTY = 0, | 24 DEPRECATION_DATABASE_NOT_EMPTY = 0, |
24 | 25 |
25 // No meta, unable to query sqlite_master. This is probably bad. | 26 // No meta, unable to query sqlite_master. This is probably bad. |
26 DEPRECATION_DATABASE_UNKNOWN, | 27 DEPRECATION_DATABASE_UNKNOWN, |
27 | 28 |
28 // Failure querying meta table, corruption or similar problem likely. | 29 // Failure querying meta table, corruption or similar problem likely. |
(...skipping 23 matching lines...) Expand all Loading... |
52 | 53 |
53 namespace sql { | 54 namespace sql { |
54 | 55 |
55 MetaTable::MetaTable() : db_(NULL) { | 56 MetaTable::MetaTable() : db_(NULL) { |
56 } | 57 } |
57 | 58 |
58 MetaTable::~MetaTable() { | 59 MetaTable::~MetaTable() { |
59 } | 60 } |
60 | 61 |
61 // static | 62 // static |
| 63 int64_t MetaTable::kMmapFailure = -2; |
| 64 int64_t MetaTable::kMmapSuccess = -1; |
| 65 |
| 66 // static |
62 bool MetaTable::DoesTableExist(sql::Connection* db) { | 67 bool MetaTable::DoesTableExist(sql::Connection* db) { |
63 DCHECK(db); | 68 DCHECK(db); |
64 return db->DoesTableExist("meta"); | 69 return db->DoesTableExist("meta"); |
65 } | 70 } |
66 | 71 |
67 // static | 72 // static |
| 73 bool MetaTable::GetMmapStatus(Connection* db, int64_t* status) { |
| 74 const char* kMmapStatusSql = "SELECT value FROM meta WHERE key = ?"; |
| 75 Statement s(db->GetUniqueStatement(kMmapStatusSql)); |
| 76 if (!s.is_valid()) |
| 77 return false; |
| 78 |
| 79 // It is fine for the status to be missing entirely, but any error prevents |
| 80 // memory-mapping. |
| 81 s.BindString(0, kMmapStatusKey); |
| 82 *status = s.Step() ? s.ColumnInt64(0) : 0; |
| 83 return s.Succeeded(); |
| 84 } |
| 85 |
| 86 // static |
| 87 bool MetaTable::SetMmapStatus(Connection* db, int64_t status) { |
| 88 DCHECK(status == kMmapFailure || status == kMmapSuccess || status >= 0); |
| 89 |
| 90 const char* kMmapUpdateStatusSql = "REPLACE INTO meta VALUES (?, ?)"; |
| 91 Statement s(db->GetUniqueStatement(kMmapUpdateStatusSql)); |
| 92 s.BindString(0, kMmapStatusKey); |
| 93 s.BindInt64(1, status); |
| 94 return s.Run(); |
| 95 } |
| 96 |
| 97 // static |
68 void MetaTable::RazeIfDeprecated(Connection* db, int deprecated_version) { | 98 void MetaTable::RazeIfDeprecated(Connection* db, int deprecated_version) { |
69 DCHECK_GT(deprecated_version, 0); | 99 DCHECK_GT(deprecated_version, 0); |
70 DCHECK_EQ(0, db->transaction_nesting()); | 100 DCHECK_EQ(0, db->transaction_nesting()); |
71 | 101 |
72 if (!DoesTableExist(db)) { | 102 if (!DoesTableExist(db)) { |
73 sql::Statement s(db->GetUniqueStatement( | 103 sql::Statement s(db->GetUniqueStatement( |
74 "SELECT COUNT(*) FROM sqlite_master")); | 104 "SELECT COUNT(*) FROM sqlite_master")); |
75 if (s.Step()) { | 105 if (s.Step()) { |
76 if (s.ColumnInt(0) != 0) { | 106 if (s.ColumnInt(0) != 0) { |
77 RecordDeprecationEvent(DEPRECATION_DATABASE_NOT_EMPTY); | 107 RecordDeprecationEvent(DEPRECATION_DATABASE_NOT_EMPTY); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 // Make sure the table is created an populated atomically. | 154 // Make sure the table is created an populated atomically. |
125 sql::Transaction transaction(db_); | 155 sql::Transaction transaction(db_); |
126 if (!transaction.Begin()) | 156 if (!transaction.Begin()) |
127 return false; | 157 return false; |
128 | 158 |
129 if (!DoesTableExist(db)) { | 159 if (!DoesTableExist(db)) { |
130 if (!db_->Execute("CREATE TABLE meta" | 160 if (!db_->Execute("CREATE TABLE meta" |
131 "(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR)")) | 161 "(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR)")) |
132 return false; | 162 return false; |
133 | 163 |
| 164 // Newly-created databases start out with mmap'ed I/O, but have no place to |
| 165 // store the setting. Set here so that later opens don't need to validate. |
| 166 SetMmapStatus(db_, kMmapSuccess); |
| 167 |
134 // Note: there is no index over the meta table. We currently only have a | 168 // Note: there is no index over the meta table. We currently only have a |
135 // couple of keys, so it doesn't matter. If we start storing more stuff in | 169 // couple of keys, so it doesn't matter. If we start storing more stuff in |
136 // there, we should create an index. | 170 // there, we should create an index. |
137 SetVersionNumber(version); | 171 SetVersionNumber(version); |
138 SetCompatibleVersionNumber(compatible_version); | 172 SetCompatibleVersionNumber(compatible_version); |
139 } else { | 173 } else { |
140 db_->AddTaggedHistogram("Sqlite.Version", GetVersionNumber()); | 174 db_->AddTaggedHistogram("Sqlite.Version", GetVersionNumber()); |
141 } | 175 } |
142 return transaction.Commit(); | 176 return transaction.Commit(); |
143 } | 177 } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 | 264 |
231 bool MetaTable::PrepareGetStatement(Statement* statement, const char* key) { | 265 bool MetaTable::PrepareGetStatement(Statement* statement, const char* key) { |
232 DCHECK(db_ && statement); | 266 DCHECK(db_ && statement); |
233 statement->Assign(db_->GetCachedStatement(SQL_FROM_HERE, | 267 statement->Assign(db_->GetCachedStatement(SQL_FROM_HERE, |
234 "SELECT value FROM meta WHERE key=?")); | 268 "SELECT value FROM meta WHERE key=?")); |
235 statement->BindCString(0, key); | 269 statement->BindCString(0, key); |
236 return statement->Step(); | 270 return statement->Step(); |
237 } | 271 } |
238 | 272 |
239 } // namespace sql | 273 } // namespace sql |
OLD | NEW |