Chromium Code Reviews| 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/connection.h" | 5 #include "sql/connection.h" |
| 6 | 6 |
| 7 #include <string.h> | 7 #include <string.h> |
| 8 | 8 |
| 9 #include "base/file_path.h" | 9 #include "base/file_path.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 161 if (!dummy.Step()) | 161 if (!dummy.Step()) |
| 162 return; | 162 return; |
| 163 | 163 |
| 164 #if !defined(USE_SYSTEM_SQLITE) | 164 #if !defined(USE_SYSTEM_SQLITE) |
| 165 // This function is only defined in Chromium's version of sqlite. | 165 // This function is only defined in Chromium's version of sqlite. |
| 166 // Do not call it when using system sqlite. | 166 // Do not call it when using system sqlite. |
| 167 sqlite3_preload(db_); | 167 sqlite3_preload(db_); |
| 168 #endif | 168 #endif |
| 169 } | 169 } |
| 170 | 170 |
| 171 // Create an in-memory database with the existing database's page | |
| 172 // size, then backup that database over the existing database. | |
| 173 bool Connection::Raze() { | |
| 174 if (!db_) { | |
| 175 DLOG(FATAL) << "Cannot raze null db"; | |
| 176 return false; | |
| 177 } | |
| 178 | |
| 179 if (transaction_nesting_ > 0) { | |
| 180 DLOG(FATAL) << "Cannot raze within a transaction"; | |
| 181 return false; | |
| 182 } | |
| 183 | |
| 184 sql::Connection null_db; | |
| 185 if (!null_db.OpenInMemory()) { | |
| 186 DLOG(FATAL) << "Unable to open in-memory database."; | |
| 187 return false; | |
| 188 } | |
| 189 | |
| 190 // Get the page size from the current connection, then propagate it | |
| 191 // to the null database. | |
| 192 Statement s(GetUniqueStatement("PRAGMA page_size")); | |
| 193 if (!s.Step()) | |
| 194 return false; | |
| 195 const std::string sql = StringPrintf("PRAGMA page_size=%d", s.ColumnInt(0)); | |
| 196 if (!null_db.Execute(sql.c_str())) | |
| 197 return false; | |
| 198 | |
| 199 // The page size doesn't take effect until a database has pages, and | |
| 200 // at this point the null database has none. Changing the schema | |
| 201 // version will create the first page. This will not affect the | |
| 202 // schema version in the resulting database, as SQLite's backup | |
| 203 // implementation propagates the schema version from the original | |
| 204 // connection to the new version of the database, incremented by one | |
| 205 // so that other readers see the schema change and act accordingly. | |
| 206 if (!null_db.Execute("PRAGMA schema_version = 1")) | |
| 207 return false; | |
| 208 | |
| 209 sqlite3_backup* backup = sqlite3_backup_init(db_, "main", | |
| 210 null_db.db_, "main"); | |
| 211 if (!backup) { | |
| 212 DLOG(FATAL) << "Unable to start sqlite3_backup()."; | |
| 213 return false; | |
| 214 } | |
| 215 | |
| 216 // -1 backs up the entire database. | |
| 217 int rc = sqlite3_backup_step(backup, -1); | |
| 218 int pages = sqlite3_backup_pagecount(backup); | |
| 219 sqlite3_backup_finish(backup); | |
| 220 | |
| 221 // The destination database was locked. | |
| 222 if (rc == SQLITE_BUSY) { | |
| 223 return false; | |
| 224 } | |
| 225 | |
| 226 // The entire database should have been backed up. | |
| 227 if (rc != SQLITE_DONE) { | |
| 228 DLOG(FATAL) << "Unable to copy entire null database."; | |
| 229 return false; | |
| 230 } | |
| 231 | |
| 232 // Exactly one page should have been backed up. If this breaks, | |
| 233 // check this function to make sure assumptions aren't being broken. | |
| 234 DCHECK_EQ(pages, 1); | |
|
Greg Billock
2012/04/04 19:49:21
Likes it. That should get the attention of a versi
| |
| 235 | |
| 236 return true; | |
| 237 } | |
| 238 | |
| 239 bool Connection::RazeWithTimout(base::TimeDelta timeout) { | |
| 240 if (!db_) { | |
| 241 DLOG(FATAL) << "Cannot raze null db"; | |
| 242 return false; | |
| 243 } | |
| 244 | |
| 245 ScopedBusyTimeout busy_timeout(db_); | |
| 246 busy_timeout.SetTimeout(timeout); | |
| 247 return Raze(); | |
| 248 } | |
| 249 | |
| 171 bool Connection::BeginTransaction() { | 250 bool Connection::BeginTransaction() { |
| 172 if (needs_rollback_) { | 251 if (needs_rollback_) { |
| 173 DCHECK_GT(transaction_nesting_, 0); | 252 DCHECK_GT(transaction_nesting_, 0); |
| 174 | 253 |
| 175 // When we're going to rollback, fail on this begin and don't actually | 254 // When we're going to rollback, fail on this begin and don't actually |
| 176 // mark us as entering the nested transaction. | 255 // mark us as entering the nested transaction. |
| 177 return false; | 256 return false; |
| 178 } | 257 } |
| 179 | 258 |
| 180 bool success = true; | 259 bool success = true; |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 485 | 564 |
| 486 int Connection::OnSqliteError(int err, sql::Statement *stmt) { | 565 int Connection::OnSqliteError(int err, sql::Statement *stmt) { |
| 487 if (error_delegate_.get()) | 566 if (error_delegate_.get()) |
| 488 return error_delegate_->OnError(err, this, stmt); | 567 return error_delegate_->OnError(err, this, stmt); |
| 489 // The default handling is to assert on debug and to ignore on release. | 568 // The default handling is to assert on debug and to ignore on release. |
| 490 DLOG(FATAL) << GetErrorMessage(); | 569 DLOG(FATAL) << GetErrorMessage(); |
| 491 return err; | 570 return err; |
| 492 } | 571 } |
| 493 | 572 |
| 494 } // namespace sql | 573 } // namespace sql |
| OLD | NEW |