| 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 |