Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(284)

Side by Side Diff: sql/connection.cc

Issue 19281002: [sql] Scoped recovery framework. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 87
88 // If successful, exactly one page should have been backed up. If 88 // If successful, exactly one page should have been backed up. If
89 // this breaks, check this function to make sure assumptions aren't 89 // this breaks, check this function to make sure assumptions aren't
90 // being broken. 90 // being broken.
91 if (rc == SQLITE_DONE) 91 if (rc == SQLITE_DONE)
92 DCHECK_EQ(pages, 1); 92 DCHECK_EQ(pages, 1);
93 93
94 return rc; 94 return rc;
95 } 95 }
96 96
97 // Be very strict on attachment point. SQLite can handle a much wider
98 // character set with appropriate quoting, but Chromium code should
99 // just use clean names to start with.
100 bool ValidAttachmentPoint(const char* attachment_point) {
101 for (size_t i = 0; attachment_point[i]; ++i) {
102 if (!((attachment_point[i] >= '0' && attachment_point[i] <= '9') ||
103 (attachment_point[i] >= 'a' && attachment_point[i] <= 'z') ||
104 (attachment_point[i] >= 'A' && attachment_point[i] <= 'Z') ||
105 attachment_point[i] == '_')) {
106 return false;
107 }
108 }
109 return true;
110 }
111
97 } // namespace 112 } // namespace
98 113
99 namespace sql { 114 namespace sql {
100 115
101 // static 116 // static
102 Connection::ErrorIgnorerCallback* Connection::current_ignorer_cb_ = NULL; 117 Connection::ErrorIgnorerCallback* Connection::current_ignorer_cb_ = NULL;
103 118
104 // static 119 // static
105 bool Connection::ShouldIgnore(int error) { 120 bool Connection::ShouldIgnore(int error) {
106 if (!current_ignorer_cb_) 121 if (!current_ignorer_cb_)
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 #elif defined(OS_POSIX) 213 #elif defined(OS_POSIX)
199 return OpenInternal(path.value()); 214 return OpenInternal(path.value());
200 #endif 215 #endif
201 } 216 }
202 217
203 bool Connection::OpenInMemory() { 218 bool Connection::OpenInMemory() {
204 in_memory_ = true; 219 in_memory_ = true;
205 return OpenInternal(":memory:"); 220 return OpenInternal(":memory:");
206 } 221 }
207 222
223 bool Connection::OpenTemporary() {
224 return OpenInternal("");
225 }
226
208 void Connection::CloseInternal(bool forced) { 227 void Connection::CloseInternal(bool forced) {
209 // TODO(shess): Calling "PRAGMA journal_mode = DELETE" at this point 228 // TODO(shess): Calling "PRAGMA journal_mode = DELETE" at this point
210 // will delete the -journal file. For ChromiumOS or other more 229 // will delete the -journal file. For ChromiumOS or other more
211 // embedded systems, this is probably not appropriate, whereas on 230 // embedded systems, this is probably not appropriate, whereas on
212 // desktop it might make some sense. 231 // desktop it might make some sense.
213 232
214 // sqlite3_close() needs all prepared statements to be finalized. 233 // sqlite3_close() needs all prepared statements to be finalized.
215 234
216 // Release cached statements. 235 // Release cached statements.
217 statement_cache_.clear(); 236 statement_cache_.clear();
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 return Raze(); 424 return Raze();
406 } 425 }
407 426
408 bool Connection::RazeAndClose() { 427 bool Connection::RazeAndClose() {
409 if (!db_) { 428 if (!db_) {
410 DLOG_IF(FATAL, !poisoned_) << "Cannot raze null db"; 429 DLOG_IF(FATAL, !poisoned_) << "Cannot raze null db";
411 return false; 430 return false;
412 } 431 }
413 432
414 // Raze() cannot run in a transaction. 433 // Raze() cannot run in a transaction.
415 while (transaction_nesting_) { 434 RollbackAllTransactions();
416 RollbackTransaction();
417 }
418 435
419 bool result = Raze(); 436 bool result = Raze();
420 437
421 CloseInternal(true); 438 CloseInternal(true);
422 439
423 // Mark the database so that future API calls fail appropriately, 440 // Mark the database so that future API calls fail appropriately,
424 // but don't DCHECK (because after calling this function they are 441 // but don't DCHECK (because after calling this function they are
425 // expected to fail). 442 // expected to fail).
426 poisoned_ = true; 443 poisoned_ = true;
427 444
428 return result; 445 return result;
429 } 446 }
430 447
448 void Connection::Poison() {
449 if (!db_) {
450 DLOG_IF(FATAL, !poisoned_) << "Cannot poison null db";
451 return;
452 }
453
454 RollbackAllTransactions();
455 CloseInternal(true);
456
457 // Mark the database so that future API calls fail appropriately,
458 // but don't DCHECK (because after calling this function they are
459 // expected to fail).
460 poisoned_ = true;
461 }
462
431 // TODO(shess): To the extent possible, figure out the optimal 463 // TODO(shess): To the extent possible, figure out the optimal
432 // ordering for these deletes which will prevent other connections 464 // ordering for these deletes which will prevent other connections
433 // from seeing odd behavior. For instance, it may be necessary to 465 // from seeing odd behavior. For instance, it may be necessary to
434 // manually lock the main database file in a SQLite-compatible fashion 466 // manually lock the main database file in a SQLite-compatible fashion
435 // (to prevent other processes from opening it), then delete the 467 // (to prevent other processes from opening it), then delete the
436 // journal files, then delete the main database file. Another option 468 // journal files, then delete the main database file. Another option
437 // might be to lock the main database file and poison the header with 469 // might be to lock the main database file and poison the header with
438 // junk to prevent other processes from opening it successfully (like 470 // junk to prevent other processes from opening it successfully (like
439 // Gears "SQLite poison 3" trick). 471 // Gears "SQLite poison 3" trick).
440 // 472 //
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 538
507 if (needs_rollback_) { 539 if (needs_rollback_) {
508 DoRollback(); 540 DoRollback();
509 return false; 541 return false;
510 } 542 }
511 543
512 Statement commit(GetCachedStatement(SQL_FROM_HERE, "COMMIT")); 544 Statement commit(GetCachedStatement(SQL_FROM_HERE, "COMMIT"));
513 return commit.Run(); 545 return commit.Run();
514 } 546 }
515 547
548 void Connection::RollbackAllTransactions() {
549 if (transaction_nesting_ > 0) {
550 transaction_nesting_ = 0;
551 DoRollback();
552 }
553 }
554
555 bool Connection::AttachDatabase(const base::FilePath& other_db_path,
556 const char* attachment_point) {
557 DCHECK(ValidAttachmentPoint(attachment_point));
558
559 Statement s(GetUniqueStatement("ATTACH DATABASE ? AS ?"));
560 #if OS_WIN
561 s.BindString16(0, other_db_path.value());
562 #else
563 s.BindString(0, other_db_path.value());
564 #endif
565 s.BindString(1, attachment_point);
566 return s.Run();
567 }
568
569 bool Connection::DetachDatabase(const char* attachment_point) {
570 DCHECK(ValidAttachmentPoint(attachment_point));
571
572 Statement s(GetUniqueStatement("DETACH DATABASE ?"));
573 s.BindString(0, attachment_point);
574 return s.Run();
575 }
576
516 int Connection::ExecuteAndReturnErrorCode(const char* sql) { 577 int Connection::ExecuteAndReturnErrorCode(const char* sql) {
517 AssertIOAllowed(); 578 AssertIOAllowed();
518 if (!db_) { 579 if (!db_) {
519 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db"; 580 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db";
520 return SQLITE_ERROR; 581 return SQLITE_ERROR;
521 } 582 }
522 return sqlite3_exec(db_, sql, NULL, NULL, NULL); 583 return sqlite3_exec(db_, sql, NULL, NULL, NULL);
523 } 584 }
524 585
525 bool Connection::Execute(const char* sql) { 586 bool Connection::Execute(const char* sql) {
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
902 } 963 }
903 964
904 // Best effort to put things back as they were before. 965 // Best effort to put things back as they were before.
905 const char kNoWritableSchema[] = "PRAGMA writable_schema = OFF"; 966 const char kNoWritableSchema[] = "PRAGMA writable_schema = OFF";
906 ignore_result(Execute(kNoWritableSchema)); 967 ignore_result(Execute(kNoWritableSchema));
907 968
908 return ret; 969 return ret;
909 } 970 }
910 971
911 } // namespace sql 972 } // namespace sql
OLDNEW
« sql/connection.h ('K') | « sql/connection.h ('k') | sql/connection_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698