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 |