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

Side by Side Diff: sql/connection.cc

Issue 16664005: [sql] Framework for allowing tests to handle errors. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Erik's comments, plus lazy instance for global. Created 7 years, 6 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 } 61 }
62 62
63 private: 63 private:
64 sqlite3* db_; 64 sqlite3* db_;
65 }; 65 };
66 66
67 } // namespace 67 } // namespace
68 68
69 namespace sql { 69 namespace sql {
70 70
71 // static
72 base::LazyInstance<Connection::ErrorIgnorerCallback>
73 Connection::current_ignorer_cb_ = LAZY_INSTANCE_INITIALIZER;
74
75 // static
76 bool Connection::ShouldIgnore(int error) {
77 if (current_ignorer_cb_.Get().is_null())
78 return false;
79 return current_ignorer_cb_.Get().Run(error);
80 }
81
82 // static
83 void Connection::SetErrorIgnorer(const Connection::ErrorIgnorerCallback& cb) {
84 CHECK(current_ignorer_cb_.Get().is_null());
85 *current_ignorer_cb_.Pointer() = cb;
86 }
87
88 // static
89 void Connection::ResetErrorIgnorer() {
90 current_ignorer_cb_.Get().Reset();
91 }
92
71 bool StatementID::operator<(const StatementID& other) const { 93 bool StatementID::operator<(const StatementID& other) const {
72 if (number_ != other.number_) 94 if (number_ != other.number_)
73 return number_ < other.number_; 95 return number_ < other.number_;
74 return strcmp(str_, other.str_) < 0; 96 return strcmp(str_, other.str_) < 0;
75 } 97 }
76 98
77 ErrorDelegate::~ErrorDelegate() { 99 ErrorDelegate::~ErrorDelegate() {
78 } 100 }
79 101
80 Connection::StatementRef::StatementRef(Connection* connection, 102 Connection::StatementRef::StatementRef(Connection* connection,
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db"; 454 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db";
433 return false; 455 return false;
434 } 456 }
435 457
436 int error = ExecuteAndReturnErrorCode(sql); 458 int error = ExecuteAndReturnErrorCode(sql);
437 if (error != SQLITE_OK) 459 if (error != SQLITE_OK)
438 error = OnSqliteError(error, NULL); 460 error = OnSqliteError(error, NULL);
439 461
440 // This needs to be a FATAL log because the error case of arriving here is 462 // 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 463 // that there's a malformed SQL statement. This can arise in development if
442 // a change alters the schema but not all queries adjust. 464 // a change alters the schema but not all queries adjust. This can happen
465 // in production if the schema is corrupted.
443 if (error == SQLITE_ERROR) 466 if (error == SQLITE_ERROR)
444 DLOG(FATAL) << "SQL Error in " << sql << ", " << GetErrorMessage(); 467 DLOG(FATAL) << "SQL Error in " << sql << ", " << GetErrorMessage();
445 return error == SQLITE_OK; 468 return error == SQLITE_OK;
446 } 469 }
447 470
448 bool Connection::ExecuteWithTimeout(const char* sql, base::TimeDelta timeout) { 471 bool Connection::ExecuteWithTimeout(const char* sql, base::TimeDelta timeout) {
449 if (!db_) { 472 if (!db_) {
450 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db"; 473 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db";
451 return false; 474 return false;
452 } 475 }
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 DCHECK_EQ(err, SQLITE_OK) << "Could not enable extended result codes"; 680 DCHECK_EQ(err, SQLITE_OK) << "Could not enable extended result codes";
658 681
659 // If indicated, lock up the database before doing anything else, so 682 // If indicated, lock up the database before doing anything else, so
660 // that the following code doesn't have to deal with locking. 683 // that the following code doesn't have to deal with locking.
661 // TODO(shess): This code is brittle. Find the cases where code 684 // TODO(shess): This code is brittle. Find the cases where code
662 // doesn't request |exclusive_locking_| and audit that it does the 685 // doesn't request |exclusive_locking_| and audit that it does the
663 // right thing with SQLITE_BUSY, and that it doesn't make 686 // right thing with SQLITE_BUSY, and that it doesn't make
664 // assumptions about who might change things in the database. 687 // assumptions about who might change things in the database.
665 // http://crbug.com/56559 688 // http://crbug.com/56559
666 if (exclusive_locking_) { 689 if (exclusive_locking_) {
667 // TODO(shess): This should probably be a full CHECK(). Code 690 // TODO(shess): This should probably be a failure. Code which
668 // which requests exclusive locking but doesn't get it is almost 691 // requests exclusive locking but doesn't get it is almost certain
669 // certain to be ill-tested. 692 // to be ill-tested.
670 if (!Execute("PRAGMA locking_mode=EXCLUSIVE")) 693 ignore_result(Execute("PRAGMA locking_mode=EXCLUSIVE"));
671 DLOG(FATAL) << "Could not set locking mode: " << GetErrorMessage();
672 } 694 }
673 695
674 // http://www.sqlite.org/pragma.html#pragma_journal_mode 696 // http://www.sqlite.org/pragma.html#pragma_journal_mode
675 // DELETE (default) - delete -journal file to commit. 697 // DELETE (default) - delete -journal file to commit.
676 // TRUNCATE - truncate -journal file to commit. 698 // TRUNCATE - truncate -journal file to commit.
677 // PERSIST - zero out header of -journal file to commit. 699 // PERSIST - zero out header of -journal file to commit.
678 // journal_size_limit provides size to trim to in PERSIST. 700 // journal_size_limit provides size to trim to in PERSIST.
679 // TODO(shess): Figure out if PERSIST and journal_size_limit really 701 // TODO(shess): Figure out if PERSIST and journal_size_limit really
680 // matter. In theory, it keeps pages pre-allocated, so if 702 // matter. In theory, it keeps pages pre-allocated, so if
681 // transactions usually fit, it should be faster. 703 // transactions usually fit, it should be faster.
682 ignore_result(Execute("PRAGMA journal_mode = PERSIST")); 704 ignore_result(Execute("PRAGMA journal_mode = PERSIST"));
683 ignore_result(Execute("PRAGMA journal_size_limit = 16384")); 705 ignore_result(Execute("PRAGMA journal_size_limit = 16384"));
684 706
685 const base::TimeDelta kBusyTimeout = 707 const base::TimeDelta kBusyTimeout =
686 base::TimeDelta::FromSeconds(kBusyTimeoutSeconds); 708 base::TimeDelta::FromSeconds(kBusyTimeoutSeconds);
687 709
688 if (page_size_ != 0) { 710 if (page_size_ != 0) {
689 // Enforce SQLite restrictions on |page_size_|. 711 // Enforce SQLite restrictions on |page_size_|.
690 DCHECK(!(page_size_ & (page_size_ - 1))) 712 DCHECK(!(page_size_ & (page_size_ - 1)))
691 << " page_size_ " << page_size_ << " is not a power of two."; 713 << " page_size_ " << page_size_ << " is not a power of two.";
692 const int kSqliteMaxPageSize = 32768; // from sqliteLimit.h 714 const int kSqliteMaxPageSize = 32768; // from sqliteLimit.h
693 DCHECK_LE(page_size_, kSqliteMaxPageSize); 715 DCHECK_LE(page_size_, kSqliteMaxPageSize);
694 const std::string sql = 716 const std::string sql =
695 base::StringPrintf("PRAGMA page_size=%d", page_size_); 717 base::StringPrintf("PRAGMA page_size=%d", page_size_);
696 if (!ExecuteWithTimeout(sql.c_str(), kBusyTimeout)) 718 ignore_result(ExecuteWithTimeout(sql.c_str(), kBusyTimeout));
697 DLOG(FATAL) << "Could not set page size: " << GetErrorMessage();
698 } 719 }
699 720
700 if (cache_size_ != 0) { 721 if (cache_size_ != 0) {
701 const std::string sql = 722 const std::string sql =
702 base::StringPrintf("PRAGMA cache_size=%d", cache_size_); 723 base::StringPrintf("PRAGMA cache_size=%d", cache_size_);
703 if (!ExecuteWithTimeout(sql.c_str(), kBusyTimeout)) 724 ignore_result(ExecuteWithTimeout(sql.c_str(), kBusyTimeout));
704 DLOG(FATAL) << "Could not set cache size: " << GetErrorMessage();
705 } 725 }
706 726
707 if (!ExecuteWithTimeout("PRAGMA secure_delete=ON", kBusyTimeout)) { 727 if (!ExecuteWithTimeout("PRAGMA secure_delete=ON", kBusyTimeout)) {
708 DLOG(FATAL) << "Could not enable secure_delete: " << GetErrorMessage();
709 Close(); 728 Close();
710 return false; 729 return false;
711 } 730 }
712 731
713 return true; 732 return true;
714 } 733 }
715 734
716 void Connection::DoRollback() { 735 void Connection::DoRollback() {
717 Statement rollback(GetCachedStatement(SQL_FROM_HERE, "ROLLBACK")); 736 Statement rollback(GetCachedStatement(SQL_FROM_HERE, "ROLLBACK"));
718 rollback.Run(); 737 rollback.Run();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
763 error_callback_.Run(err, stmt); 782 error_callback_.Run(err, stmt);
764 return err; 783 return err;
765 } 784 }
766 785
767 // TODO(shess): Remove |error_delegate_| once everything is 786 // TODO(shess): Remove |error_delegate_| once everything is
768 // converted to |error_callback_|. 787 // converted to |error_callback_|.
769 if (error_delegate_.get()) 788 if (error_delegate_.get())
770 return error_delegate_->OnError(err, this, stmt); 789 return error_delegate_->OnError(err, this, stmt);
771 790
772 // The default handling is to assert on debug and to ignore on release. 791 // The default handling is to assert on debug and to ignore on release.
773 DLOG(FATAL) << GetErrorMessage(); 792 if (!ShouldIgnore(err))
793 DLOG(FATAL) << GetErrorMessage();
774 return err; 794 return err;
775 } 795 }
776 796
777 // TODO(shess): Allow specifying integrity_check versus quick_check. 797 // TODO(shess): Allow specifying integrity_check versus quick_check.
778 // TODO(shess): Allow specifying maximum results (default 100 lines). 798 // TODO(shess): Allow specifying maximum results (default 100 lines).
779 bool Connection::IntegrityCheck(std::vector<std::string>* messages) { 799 bool Connection::IntegrityCheck(std::vector<std::string>* messages) {
780 messages->clear(); 800 messages->clear();
781 801
782 // This has the side effect of setting SQLITE_RecoveryMode, which 802 // This has the side effect of setting SQLITE_RecoveryMode, which
783 // allows SQLite to process through certain cases of corruption. 803 // allows SQLite to process through certain cases of corruption.
(...skipping 19 matching lines...) Expand all
803 } 823 }
804 824
805 // Best effort to put things back as they were before. 825 // Best effort to put things back as they were before.
806 const char kNoWritableSchema[] = "PRAGMA writable_schema = OFF"; 826 const char kNoWritableSchema[] = "PRAGMA writable_schema = OFF";
807 ignore_result(Execute(kNoWritableSchema)); 827 ignore_result(Execute(kNoWritableSchema));
808 828
809 return ret; 829 return ret;
810 } 830 }
811 831
812 } // namespace sql 832 } // namespace sql
OLDNEW
« no previous file with comments | « sql/connection.h ('k') | sql/connection_unittest.cc » ('j') | sql/sql.gyp » ('J')

Powered by Google App Engine
This is Rietveld 408576698