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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 57 sqlite3_exec(db_, "PRAGMA writable_schema=1", NULL, NULL, NULL); | 57 sqlite3_exec(db_, "PRAGMA writable_schema=1", NULL, NULL, NULL); |
| 58 } | 58 } |
| 59 ~ScopedWritableSchema() { | 59 ~ScopedWritableSchema() { |
| 60 sqlite3_exec(db_, "PRAGMA writable_schema=0", NULL, NULL, NULL); | 60 sqlite3_exec(db_, "PRAGMA writable_schema=0", NULL, NULL, NULL); |
| 61 } | 61 } |
| 62 | 62 |
| 63 private: | 63 private: |
| 64 sqlite3* db_; | 64 sqlite3* db_; |
| 65 }; | 65 }; |
| 66 | 66 |
| 67 // Helper to wrap the sqlite3_backup_*() step of Raze(). Return | |
| 68 // SQLite error code from running the backup step. | |
| 69 int BackupDatabase(sqlite3* src, sqlite3* dst, const char* db_name) { | |
| 70 sqlite3_backup* backup = sqlite3_backup_init(dst, db_name, src, db_name); | |
| 71 if (!backup) { | |
| 72 // Since this call only sets things up, this indicates a gross | |
| 73 // error in SQLite. | |
| 74 DLOG(FATAL) << "Unable to start sqlite3_backup()."; | |
| 75 return SQLITE_ABORT; | |
| 76 } | |
| 77 | |
| 78 // -1 backs up the entire database. | |
| 79 int rc = sqlite3_backup_step(backup, -1); | |
| 80 int pages = sqlite3_backup_pagecount(backup); | |
| 81 sqlite3_backup_finish(backup); | |
| 82 | |
| 83 // Exactly one page should have been backed up. If this breaks, | |
| 84 // check this function to make sure assumptions aren't being broken. | |
| 85 if (rc == SQLITE_DONE) | |
| 86 DCHECK_EQ(pages, 1); | |
| 87 | |
| 88 return rc; | |
| 89 } | |
| 90 | |
| 91 // Hooks for ScopedErrorIgnorer. | |
| 92 sql::ScopedErrorIgnorer* g_current_ignorer = NULL; | |
| 93 bool ShouldIgnoreError(int error) { | |
| 94 if (g_current_ignorer) | |
| 95 return g_current_ignorer->ShouldIgnoreError(error); | |
| 96 return false; | |
| 97 } | |
| 98 | |
| 67 } // namespace | 99 } // namespace |
| 68 | 100 |
| 69 namespace sql { | 101 namespace sql { |
| 70 | 102 |
| 71 bool StatementID::operator<(const StatementID& other) const { | 103 bool StatementID::operator<(const StatementID& other) const { |
| 72 if (number_ != other.number_) | 104 if (number_ != other.number_) |
| 73 return number_ < other.number_; | 105 return number_ < other.number_; |
| 74 return strcmp(str_, other.str_) < 0; | 106 return strcmp(str_, other.str_) < 0; |
| 75 } | 107 } |
| 76 | 108 |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 288 // page, and if it does not match the total retrieved from a | 320 // page, and if it does not match the total retrieved from a |
| 289 // filesystem call, treats the database as corrupt. This situation | 321 // filesystem call, treats the database as corrupt. This situation |
| 290 // breaks almost all SQLite calls. "PRAGMA writable_schema" can be | 322 // breaks almost all SQLite calls. "PRAGMA writable_schema" can be |
| 291 // used to hint to SQLite to soldier on in that case, specifically | 323 // used to hint to SQLite to soldier on in that case, specifically |
| 292 // for purposes of recovery. [See SQLITE_CORRUPT_BKPT case in | 324 // for purposes of recovery. [See SQLITE_CORRUPT_BKPT case in |
| 293 // sqlite3.c lockBtree().] | 325 // sqlite3.c lockBtree().] |
| 294 // TODO(shess): With this, "PRAGMA auto_vacuum" and "PRAGMA | 326 // TODO(shess): With this, "PRAGMA auto_vacuum" and "PRAGMA |
| 295 // page_size" can be used to query such a database. | 327 // page_size" can be used to query such a database. |
| 296 ScopedWritableSchema writable_schema(db_); | 328 ScopedWritableSchema writable_schema(db_); |
| 297 | 329 |
| 298 sqlite3_backup* backup = sqlite3_backup_init(db_, "main", | 330 const char* kMain = "main"; |
| 299 null_db.db_, "main"); | 331 int rc = BackupDatabase(null_db.db_, db_, kMain); |
| 300 if (!backup) { | |
| 301 DLOG(FATAL) << "Unable to start sqlite3_backup()."; | |
| 302 return false; | |
| 303 } | |
| 304 | |
| 305 // -1 backs up the entire database. | |
| 306 int rc = sqlite3_backup_step(backup, -1); | |
| 307 int pages = sqlite3_backup_pagecount(backup); | |
| 308 sqlite3_backup_finish(backup); | |
| 309 | 332 |
| 310 // The destination database was locked. | 333 // The destination database was locked. |
| 311 if (rc == SQLITE_BUSY) { | 334 if (rc == SQLITE_BUSY) { |
| 312 return false; | 335 return false; |
| 313 } | 336 } |
| 314 | 337 |
| 338 // SQLITE_NOTADB can happen if page 1 exists but is not formatted | |
|
erikwright (departed)
2013/06/11 18:54:19
Can/should this block be a separate CL?
Scott Hess - ex-Googler
2013/06/12 22:42:46
It's in here so that the example tests can pass.
| |
| 339 // correctly. SQLITE_IOERR_SHORT_READ can happen if the database | |
| 340 // isn't even big enough for one page. Either way, reach in and | |
| 341 // truncate it before trying again. | |
| 342 // TODO(shess): Maybe it would be worthwhile to just truncate from | |
| 343 // the get-go? | |
| 344 if (rc == SQLITE_NOTADB || rc == SQLITE_IOERR_SHORT_READ) { | |
| 345 sqlite3_file* file = NULL; | |
| 346 rc = sqlite3_file_control(db_, "main", SQLITE_FCNTL_FILE_POINTER, &file); | |
| 347 if (rc != SQLITE_OK) { | |
| 348 DLOG(FATAL) << "Failure getting file handle."; | |
| 349 return false; | |
| 350 } else if (!file) { | |
| 351 DLOG(FATAL) << "File handle is empty."; | |
| 352 return false; | |
| 353 } | |
| 354 | |
| 355 rc = file->pMethods->xTruncate(file, 0); | |
| 356 if (rc != SQLITE_OK) { | |
| 357 DLOG(FATAL) << "Failed to truncate file."; | |
| 358 return false; | |
| 359 } | |
| 360 | |
| 361 rc = BackupDatabase(null_db.db_, db_, kMain); | |
| 362 | |
| 363 if (rc != SQLITE_DONE) { | |
| 364 DLOG(FATAL) << "Failed retrying Raze()."; | |
| 365 } | |
| 366 } | |
| 367 | |
| 315 // The entire database should have been backed up. | 368 // The entire database should have been backed up. |
| 316 if (rc != SQLITE_DONE) { | 369 if (rc != SQLITE_DONE) { |
| 370 // TODO(shess): Figure out which other cases can happen. | |
| 317 DLOG(FATAL) << "Unable to copy entire null database."; | 371 DLOG(FATAL) << "Unable to copy entire null database."; |
| 318 return false; | 372 return false; |
| 319 } | 373 } |
| 320 | 374 |
| 321 // Exactly one page should have been backed up. If this breaks, | |
| 322 // check this function to make sure assumptions aren't being broken. | |
| 323 DCHECK_EQ(pages, 1); | |
| 324 | |
| 325 return true; | 375 return true; |
| 326 } | 376 } |
| 327 | 377 |
| 328 bool Connection::RazeWithTimout(base::TimeDelta timeout) { | 378 bool Connection::RazeWithTimout(base::TimeDelta timeout) { |
| 329 if (!db_) { | 379 if (!db_) { |
| 330 DLOG_IF(FATAL, !poisoned_) << "Cannot raze null db"; | 380 DLOG_IF(FATAL, !poisoned_) << "Cannot raze null db"; |
| 331 return false; | 381 return false; |
| 332 } | 382 } |
| 333 | 383 |
| 334 ScopedBusyTimeout busy_timeout(db_); | 384 ScopedBusyTimeout busy_timeout(db_); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 432 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db"; | 482 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db"; |
| 433 return false; | 483 return false; |
| 434 } | 484 } |
| 435 | 485 |
| 436 int error = ExecuteAndReturnErrorCode(sql); | 486 int error = ExecuteAndReturnErrorCode(sql); |
| 437 if (error != SQLITE_OK) | 487 if (error != SQLITE_OK) |
| 438 error = OnSqliteError(error, NULL); | 488 error = OnSqliteError(error, NULL); |
| 439 | 489 |
| 440 // This needs to be a FATAL log because the error case of arriving here is | 490 // This needs to be a FATAL log because the error case of arriving here is |
| 441 // that there's a malformed SQL statement. This can arise in development if | 491 // that there's a malformed SQL statement. This can arise in development if |
| 442 // a change alters the schema but not all queries adjust. | 492 // a change alters the schema but not all queries adjust. This can happen |
| 493 // in production if the schema is corrupted. | |
| 443 if (error == SQLITE_ERROR) | 494 if (error == SQLITE_ERROR) |
| 444 DLOG(FATAL) << "SQL Error in " << sql << ", " << GetErrorMessage(); | 495 DLOG(FATAL) << "SQL Error in " << sql << ", " << GetErrorMessage(); |
| 445 return error == SQLITE_OK; | 496 return error == SQLITE_OK; |
| 446 } | 497 } |
| 447 | 498 |
| 448 bool Connection::ExecuteWithTimeout(const char* sql, base::TimeDelta timeout) { | 499 bool Connection::ExecuteWithTimeout(const char* sql, base::TimeDelta timeout) { |
| 449 if (!db_) { | 500 if (!db_) { |
| 450 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db"; | 501 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db"; |
| 451 return false; | 502 return false; |
| 452 } | 503 } |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 650 DCHECK_EQ(err, SQLITE_OK) << "Could not enable extended result codes"; | 701 DCHECK_EQ(err, SQLITE_OK) << "Could not enable extended result codes"; |
| 651 | 702 |
| 652 // If indicated, lock up the database before doing anything else, so | 703 // If indicated, lock up the database before doing anything else, so |
| 653 // that the following code doesn't have to deal with locking. | 704 // that the following code doesn't have to deal with locking. |
| 654 // TODO(shess): This code is brittle. Find the cases where code | 705 // TODO(shess): This code is brittle. Find the cases where code |
| 655 // doesn't request |exclusive_locking_| and audit that it does the | 706 // doesn't request |exclusive_locking_| and audit that it does the |
| 656 // right thing with SQLITE_BUSY, and that it doesn't make | 707 // right thing with SQLITE_BUSY, and that it doesn't make |
| 657 // assumptions about who might change things in the database. | 708 // assumptions about who might change things in the database. |
| 658 // http://crbug.com/56559 | 709 // http://crbug.com/56559 |
| 659 if (exclusive_locking_) { | 710 if (exclusive_locking_) { |
| 660 // TODO(shess): This should probably be a full CHECK(). Code | 711 // TODO(shess): This should probably be a failure. Code which |
| 661 // which requests exclusive locking but doesn't get it is almost | 712 // requests exclusive locking but doesn't get it is almost certain |
| 662 // certain to be ill-tested. | 713 // to be ill-tested. |
| 663 if (!Execute("PRAGMA locking_mode=EXCLUSIVE")) | 714 ignore_result(Execute("PRAGMA locking_mode=EXCLUSIVE")); |
| 664 DLOG(FATAL) << "Could not set locking mode: " << GetErrorMessage(); | |
| 665 } | 715 } |
| 666 | 716 |
| 667 // http://www.sqlite.org/pragma.html#pragma_journal_mode | 717 // http://www.sqlite.org/pragma.html#pragma_journal_mode |
| 668 // DELETE (default) - delete -journal file to commit. | 718 // DELETE (default) - delete -journal file to commit. |
| 669 // TRUNCATE - truncate -journal file to commit. | 719 // TRUNCATE - truncate -journal file to commit. |
| 670 // PERSIST - zero out header of -journal file to commit. | 720 // PERSIST - zero out header of -journal file to commit. |
| 671 // journal_size_limit provides size to trim to in PERSIST. | 721 // journal_size_limit provides size to trim to in PERSIST. |
| 672 // TODO(shess): Figure out if PERSIST and journal_size_limit really | 722 // TODO(shess): Figure out if PERSIST and journal_size_limit really |
| 673 // matter. In theory, it keeps pages pre-allocated, so if | 723 // matter. In theory, it keeps pages pre-allocated, so if |
| 674 // transactions usually fit, it should be faster. | 724 // transactions usually fit, it should be faster. |
| 675 ignore_result(Execute("PRAGMA journal_mode = PERSIST")); | 725 ignore_result(Execute("PRAGMA journal_mode = PERSIST")); |
| 676 ignore_result(Execute("PRAGMA journal_size_limit = 16384")); | 726 ignore_result(Execute("PRAGMA journal_size_limit = 16384")); |
| 677 | 727 |
| 678 const base::TimeDelta kBusyTimeout = | 728 const base::TimeDelta kBusyTimeout = |
| 679 base::TimeDelta::FromSeconds(kBusyTimeoutSeconds); | 729 base::TimeDelta::FromSeconds(kBusyTimeoutSeconds); |
| 680 | 730 |
| 681 if (page_size_ != 0) { | 731 if (page_size_ != 0) { |
| 682 // Enforce SQLite restrictions on |page_size_|. | 732 // Enforce SQLite restrictions on |page_size_|. |
| 683 DCHECK(!(page_size_ & (page_size_ - 1))) | 733 DCHECK(!(page_size_ & (page_size_ - 1))) |
| 684 << " page_size_ " << page_size_ << " is not a power of two."; | 734 << " page_size_ " << page_size_ << " is not a power of two."; |
| 685 const int kSqliteMaxPageSize = 32768; // from sqliteLimit.h | 735 const int kSqliteMaxPageSize = 32768; // from sqliteLimit.h |
| 686 DCHECK_LE(page_size_, kSqliteMaxPageSize); | 736 DCHECK_LE(page_size_, kSqliteMaxPageSize); |
| 687 const std::string sql = | 737 const std::string sql = |
| 688 base::StringPrintf("PRAGMA page_size=%d", page_size_); | 738 base::StringPrintf("PRAGMA page_size=%d", page_size_); |
| 689 if (!ExecuteWithTimeout(sql.c_str(), kBusyTimeout)) | 739 ignore_result(ExecuteWithTimeout(sql.c_str(), kBusyTimeout)); |
| 690 DLOG(FATAL) << "Could not set page size: " << GetErrorMessage(); | |
| 691 } | 740 } |
| 692 | 741 |
| 693 if (cache_size_ != 0) { | 742 if (cache_size_ != 0) { |
| 694 const std::string sql = | 743 const std::string sql = |
| 695 base::StringPrintf("PRAGMA cache_size=%d", cache_size_); | 744 base::StringPrintf("PRAGMA cache_size=%d", cache_size_); |
| 696 if (!ExecuteWithTimeout(sql.c_str(), kBusyTimeout)) | 745 ignore_result(ExecuteWithTimeout(sql.c_str(), kBusyTimeout)); |
| 697 DLOG(FATAL) << "Could not set cache size: " << GetErrorMessage(); | |
| 698 } | 746 } |
| 699 | 747 |
| 700 if (!ExecuteWithTimeout("PRAGMA secure_delete=ON", kBusyTimeout)) { | 748 if (!ExecuteWithTimeout("PRAGMA secure_delete=ON", kBusyTimeout)) { |
| 701 DLOG(FATAL) << "Could not enable secure_delete: " << GetErrorMessage(); | |
| 702 Close(); | 749 Close(); |
| 703 return false; | 750 return false; |
| 704 } | 751 } |
| 705 | 752 |
| 706 return true; | 753 return true; |
| 707 } | 754 } |
| 708 | 755 |
| 709 void Connection::DoRollback() { | 756 void Connection::DoRollback() { |
| 710 Statement rollback(GetCachedStatement(SQL_FROM_HERE, "ROLLBACK")); | 757 Statement rollback(GetCachedStatement(SQL_FROM_HERE, "ROLLBACK")); |
| 711 rollback.Run(); | 758 rollback.Run(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 756 error_callback_.Run(err, stmt); | 803 error_callback_.Run(err, stmt); |
| 757 return err; | 804 return err; |
| 758 } | 805 } |
| 759 | 806 |
| 760 // TODO(shess): Remove |error_delegate_| once everything is | 807 // TODO(shess): Remove |error_delegate_| once everything is |
| 761 // converted to |error_callback_|. | 808 // converted to |error_callback_|. |
| 762 if (error_delegate_.get()) | 809 if (error_delegate_.get()) |
| 763 return error_delegate_->OnError(err, this, stmt); | 810 return error_delegate_->OnError(err, this, stmt); |
| 764 | 811 |
| 765 // The default handling is to assert on debug and to ignore on release. | 812 // The default handling is to assert on debug and to ignore on release. |
| 766 DLOG(FATAL) << GetErrorMessage(); | 813 if (!ShouldIgnoreError(err)) |
| 814 DLOG(FATAL) << GetErrorMessage(); | |
| 767 return err; | 815 return err; |
| 768 } | 816 } |
| 769 | 817 |
| 770 // TODO(shess): Allow specifying integrity_check versus quick_check. | 818 // TODO(shess): Allow specifying integrity_check versus quick_check. |
| 771 // TODO(shess): Allow specifying maximum results (default 100 lines). | 819 // TODO(shess): Allow specifying maximum results (default 100 lines). |
| 772 bool Connection::IntegrityCheck(std::vector<std::string>* messages) { | 820 bool Connection::IntegrityCheck(std::vector<std::string>* messages) { |
| 773 const char kSql[] = "PRAGMA integrity_check"; | 821 const char kSql[] = "PRAGMA integrity_check"; |
| 774 sql::Statement stmt(GetUniqueStatement(kSql)); | 822 sql::Statement stmt(GetUniqueStatement(kSql)); |
| 775 | 823 |
| 776 messages->clear(); | 824 messages->clear(); |
| 777 | 825 |
| 778 // The pragma appears to return all results (up to 100 by default) | 826 // The pragma appears to return all results (up to 100 by default) |
| 779 // as a single string. This doesn't appear to be an API contract, | 827 // as a single string. This doesn't appear to be an API contract, |
| 780 // it could return separate lines, so loop _and_ split. | 828 // it could return separate lines, so loop _and_ split. |
| 781 while (stmt.Step()) { | 829 while (stmt.Step()) { |
| 782 std::string result(stmt.ColumnString(0)); | 830 std::string result(stmt.ColumnString(0)); |
| 783 base::SplitString(result, '\n', messages); | 831 base::SplitString(result, '\n', messages); |
| 784 } | 832 } |
| 785 return stmt.Succeeded(); | 833 return stmt.Succeeded(); |
| 786 } | 834 } |
| 787 | 835 |
| 836 ScopedErrorIgnorer::ScopedErrorIgnorer() | |
| 837 : checked_(false), | |
| 838 next_(g_current_ignorer) { | |
| 839 g_current_ignorer = this; | |
| 840 } | |
| 841 | |
| 842 ScopedErrorIgnorer::~ScopedErrorIgnorer() { | |
| 843 CHECK(checked_); | |
|
erikwright (departed)
2013/06/11 18:54:19
This should probably be ADD_FAILURE instead of CHE
Scott Hess - ex-Googler
2013/06/12 22:42:46
Basically I hate all this :-).
OK, so would it ma
| |
| 844 DCHECK_EQ(g_current_ignorer, this); | |
| 845 g_current_ignorer = next_; | |
| 846 } | |
| 847 | |
| 848 void ScopedErrorIgnorer::IgnoreError(int err) { | |
| 849 DCHECK_EQ(0u, ignore_errors_.count(err)); | |
| 850 ignore_errors_.insert(err); | |
| 851 } | |
| 852 | |
| 853 bool ScopedErrorIgnorer::CheckIgnoredErrors() { | |
| 854 checked_ = true; | |
| 855 return errors_ignored_ == ignore_errors_; | |
| 856 } | |
| 857 | |
| 858 // static | |
| 859 bool ScopedErrorIgnorer::ShouldIgnoreError(int err) { | |
| 860 // Do not ignore if no scoped ignorer. | |
| 861 if (!g_current_ignorer) | |
| 862 return false; | |
| 863 | |
| 864 // Check extended code. | |
| 865 if (g_current_ignorer->ignore_errors_.count(err) > 0) { | |
| 866 // Record that the error was seen and ignore it. | |
| 867 g_current_ignorer->errors_ignored_.insert(err); | |
| 868 return true; | |
| 869 } | |
| 870 | |
| 871 // Trim extended codes. | |
| 872 err &= 0xff; | |
| 873 | |
| 874 // Check extended code. | |
|
erikwright (departed)
2013/06/11 18:54:19
It seems like either line 874 or 864 is wrong?
Scott Hess - ex-Googler
2013/06/12 22:42:46
Doh, this one is checking the non-extended code.
| |
| 875 if (g_current_ignorer->ignore_errors_.count(err) > 0) { | |
| 876 // Record that the error was seen and ignore it. | |
| 877 g_current_ignorer->errors_ignored_.insert(err); | |
| 878 return true; | |
| 879 } | |
| 880 | |
| 881 // Unexpected error, do not ignore. | |
| 882 return false; | |
| 883 } | |
| 884 | |
| 788 } // namespace sql | 885 } // namespace sql |
| OLD | NEW |