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/files/file_path.h" | 9 #include "base/files/file_path.h" |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 168 #elif defined(OS_POSIX) | 168 #elif defined(OS_POSIX) |
| 169 return OpenInternal(path.value()); | 169 return OpenInternal(path.value()); |
| 170 #endif | 170 #endif |
| 171 } | 171 } |
| 172 | 172 |
| 173 bool Connection::OpenInMemory() { | 173 bool Connection::OpenInMemory() { |
| 174 in_memory_ = true; | 174 in_memory_ = true; |
| 175 return OpenInternal(":memory:"); | 175 return OpenInternal(":memory:"); |
| 176 } | 176 } |
| 177 | 177 |
| 178 bool Connection::OpenTemporary() { | |
| 179 return OpenInternal(""); | |
| 180 } | |
| 181 | |
| 178 void Connection::CloseInternal(bool forced) { | 182 void Connection::CloseInternal(bool forced) { |
| 179 // TODO(shess): Calling "PRAGMA journal_mode = DELETE" at this point | 183 // TODO(shess): Calling "PRAGMA journal_mode = DELETE" at this point |
| 180 // will delete the -journal file. For ChromiumOS or other more | 184 // will delete the -journal file. For ChromiumOS or other more |
| 181 // embedded systems, this is probably not appropriate, whereas on | 185 // embedded systems, this is probably not appropriate, whereas on |
| 182 // desktop it might make some sense. | 186 // desktop it might make some sense. |
| 183 | 187 |
| 184 // sqlite3_close() needs all prepared statements to be finalized. | 188 // sqlite3_close() needs all prepared statements to be finalized. |
| 185 | 189 |
| 186 // Release cached statements. | 190 // Release cached statements. |
| 187 statement_cache_.clear(); | 191 statement_cache_.clear(); |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 354 return Raze(); | 358 return Raze(); |
| 355 } | 359 } |
| 356 | 360 |
| 357 bool Connection::RazeAndClose() { | 361 bool Connection::RazeAndClose() { |
| 358 if (!db_) { | 362 if (!db_) { |
| 359 DLOG_IF(FATAL, !poisoned_) << "Cannot raze null db"; | 363 DLOG_IF(FATAL, !poisoned_) << "Cannot raze null db"; |
| 360 return false; | 364 return false; |
| 361 } | 365 } |
| 362 | 366 |
| 363 // Raze() cannot run in a transaction. | 367 // Raze() cannot run in a transaction. |
| 364 while (transaction_nesting_) { | 368 RollbackAllTransactions(); |
| 365 RollbackTransaction(); | |
| 366 } | |
| 367 | 369 |
| 368 bool result = Raze(); | 370 bool result = Raze(); |
| 369 | 371 |
| 370 CloseInternal(true); | 372 CloseInternal(true); |
| 371 | 373 |
| 372 // Mark the database so that future API calls fail appropriately, | 374 // Mark the database so that future API calls fail appropriately, |
| 373 // but don't DCHECK (because after calling this function they are | 375 // but don't DCHECK (because after calling this function they are |
| 374 // expected to fail). | 376 // expected to fail). |
| 375 poisoned_ = true; | 377 poisoned_ = true; |
| 376 | 378 |
| 377 return result; | 379 return result; |
| 378 } | 380 } |
| 379 | 381 |
| 382 void Connection::CloseAndPoison() { | |
| 383 if (!db_) { | |
| 384 DLOG_IF(FATAL, !poisoned_) << "Cannot poison null db"; | |
|
erikwright (departed)
2013/07/05 19:02:30
is this different from DCHECK(poisoned) << "..";?
Scott Hess - ex-Googler
2013/07/08 21:41:51
Once Upon A Time, in a refactor we had a big knock
| |
| 385 return; | |
| 386 } | |
| 387 | |
| 388 RollbackAllTransactions(); | |
| 389 CloseInternal(true); | |
| 390 | |
| 391 // Mark the database so that future API calls fail appropriately, | |
| 392 // but don't DCHECK (because after calling this function they are | |
| 393 // expected to fail). | |
| 394 poisoned_ = true; | |
| 395 } | |
| 396 | |
| 380 // TODO(shess): To the extent possible, figure out the optimal | 397 // TODO(shess): To the extent possible, figure out the optimal |
| 381 // ordering for these deletes which will prevent other connections | 398 // ordering for these deletes which will prevent other connections |
| 382 // from seeing odd behavior. For instance, it may be necessary to | 399 // from seeing odd behavior. For instance, it may be necessary to |
| 383 // manually lock the main database file in a SQLite-compatible fashion | 400 // manually lock the main database file in a SQLite-compatible fashion |
| 384 // (to prevent other processes from opening it), then delete the | 401 // (to prevent other processes from opening it), then delete the |
| 385 // journal files, then delete the main database file. Another option | 402 // journal files, then delete the main database file. Another option |
| 386 // might be to lock the main database file and poison the header with | 403 // might be to lock the main database file and poison the header with |
| 387 // junk to prevent other processes from opening it successfully (like | 404 // junk to prevent other processes from opening it successfully (like |
| 388 // Gears "SQLite poison 3" trick). | 405 // Gears "SQLite poison 3" trick). |
| 389 // | 406 // |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 455 | 472 |
| 456 if (needs_rollback_) { | 473 if (needs_rollback_) { |
| 457 DoRollback(); | 474 DoRollback(); |
| 458 return false; | 475 return false; |
| 459 } | 476 } |
| 460 | 477 |
| 461 Statement commit(GetCachedStatement(SQL_FROM_HERE, "COMMIT")); | 478 Statement commit(GetCachedStatement(SQL_FROM_HERE, "COMMIT")); |
| 462 return commit.Run(); | 479 return commit.Run(); |
| 463 } | 480 } |
| 464 | 481 |
| 482 void Connection::RollbackAllTransactions() { | |
| 483 if (transaction_nesting_ > 0) { | |
| 484 transaction_nesting_ = 0; | |
| 485 DoRollback(); | |
| 486 } | |
| 487 } | |
| 488 | |
| 465 int Connection::ExecuteAndReturnErrorCode(const char* sql) { | 489 int Connection::ExecuteAndReturnErrorCode(const char* sql) { |
| 466 AssertIOAllowed(); | 490 AssertIOAllowed(); |
| 467 if (!db_) { | 491 if (!db_) { |
| 468 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db"; | 492 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db"; |
| 469 return SQLITE_ERROR; | 493 return SQLITE_ERROR; |
| 470 } | 494 } |
| 471 return sqlite3_exec(db_, sql, NULL, NULL, NULL); | 495 return sqlite3_exec(db_, sql, NULL, NULL, NULL); |
| 472 } | 496 } |
| 473 | 497 |
| 474 bool Connection::Execute(const char* sql) { | 498 bool Connection::Execute(const char* sql) { |
| (...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 840 } | 864 } |
| 841 | 865 |
| 842 // Best effort to put things back as they were before. | 866 // Best effort to put things back as they were before. |
| 843 const char kNoWritableSchema[] = "PRAGMA writable_schema = OFF"; | 867 const char kNoWritableSchema[] = "PRAGMA writable_schema = OFF"; |
| 844 ignore_result(Execute(kNoWritableSchema)); | 868 ignore_result(Execute(kNoWritableSchema)); |
| 845 | 869 |
| 846 return ret; | 870 return ret; |
| 847 } | 871 } |
| 848 | 872 |
| 849 } // namespace sql | 873 } // namespace sql |
| OLD | NEW |