diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-02 05:01:42 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-02 05:01:42 +0000 |
commit | 765b445022c7f2a24bc862b45d48ece4ca9a77e1 (patch) | |
tree | 9f351b1203bbfd02fae7018a1f11e2f15b6eeacb /app/sql | |
parent | eb6f2c542d7405788d668a762282b66655836e1d (diff) | |
download | chromium_src-765b445022c7f2a24bc862b45d48ece4ca9a77e1.zip chromium_src-765b445022c7f2a24bc862b45d48ece4ca9a77e1.tar.gz chromium_src-765b445022c7f2a24bc862b45d48ece4ca9a77e1.tar.bz2 |
Convert history to use new sql wrappers. Enhance wrappers in several ways to
support the needs of history.
BUG=none
TEST=covered by unit tests
Review URL: http://codereview.chromium.org/246053
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27832 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'app/sql')
-rw-r--r-- | app/sql/connection.cc | 58 | ||||
-rw-r--r-- | app/sql/connection.h | 37 | ||||
-rw-r--r-- | app/sql/connection_unittest.cc | 2 | ||||
-rw-r--r-- | app/sql/statement.cc | 19 | ||||
-rw-r--r-- | app/sql/statement.h | 20 | ||||
-rw-r--r-- | app/sql/statement_unittest.cc | 4 | ||||
-rw-r--r-- | app/sql/transaction_unittest.cc | 2 |
7 files changed, 102 insertions, 40 deletions
diff --git a/app/sql/connection.cc b/app/sql/connection.cc index 886f781..ac1c545 100644 --- a/app/sql/connection.cc +++ b/app/sql/connection.cc @@ -59,36 +59,16 @@ Connection::~Connection() { Close(); } -bool Connection::Init(const FilePath& path) { +bool Connection::Open(const FilePath& path) { #if defined(OS_WIN) - // We want the default encoding to always be UTF-8, so we use the - // 8-bit version of open(). - int err = sqlite3_open(WideToUTF8(path.value()).c_str(), &db_); + return OpenInternal(WideToUTF8(path.value())); #elif defined(OS_POSIX) - int err = sqlite3_open(path.value().c_str(), &db_); + return OpenInternal(path.value()); #endif +} - if (err != SQLITE_OK) { - db_ = NULL; - return false; - } - - if (page_size_ != 0) { - if (!Execute(StringPrintf("PRAGMA page_size=%d", page_size_).c_str())) - NOTREACHED() << "Could not set page size"; - } - - if (cache_size_ != 0) { - if (!Execute(StringPrintf("PRAGMA cache_size=%d", cache_size_).c_str())) - NOTREACHED() << "Could not set page size"; - } - - if (exclusive_locking_) { - if (!Execute("PRAGMA locking_mode=EXCLUSIVE")) - NOTREACHED() << "Could not set locking mode."; - } - - return true; +bool Connection::OpenInMemory() { + return OpenInternal(":memory:"); } void Connection::Close() { @@ -283,6 +263,32 @@ const char* Connection::GetErrorMessage() const { return sqlite3_errmsg(db_); } +bool Connection::OpenInternal(const std::string& file_name) { + int err = sqlite3_open(file_name.c_str(), &db_); + if (err != SQLITE_OK) { + OnSqliteError(err, NULL); + db_ = NULL; + return false; + } + + if (page_size_ != 0) { + if (!Execute(StringPrintf("PRAGMA page_size=%d", page_size_).c_str())) + NOTREACHED() << "Could not set page size"; + } + + if (cache_size_ != 0) { + if (!Execute(StringPrintf("PRAGMA cache_size=%d", cache_size_).c_str())) + NOTREACHED() << "Could not set page size"; + } + + if (exclusive_locking_) { + if (!Execute("PRAGMA locking_mode=EXCLUSIVE")) + NOTREACHED() << "Could not set locking mode."; + } + + return true; +} + void Connection::DoRollback() { Statement rollback(GetCachedStatement(SQL_FROM_HERE, "ROLLBACK")); if (rollback) diff --git a/app/sql/connection.h b/app/sql/connection.h index 904d614..e87baa8 100644 --- a/app/sql/connection.h +++ b/app/sql/connection.h @@ -79,8 +79,12 @@ class ErrorDelegate : public base::RefCounted<ErrorDelegate> { virtual ~ErrorDelegate() {} // |error| is an sqlite result code as seen in sqlite\preprocessed\sqlite3.h // |connection| is db connection where the error happened and |stmt| is - // our best guess at the statement that triggered the error. Do not store + // our best guess at the statement that triggered the error. Do not store // these pointers. + // + // |stmt| MAY BE NULL if there is no statement causing the problem (i.e. on + // initialization). + // // If the error condition has been fixed an the original statement succesfuly // re-tried then returning SQLITE_OK is appropiate; otherwise is recomended // that you return the original |error| or the appropiae error code. @@ -92,14 +96,14 @@ class Connection { class StatementRef; // Forward declaration, see real one below. public: - // The database is opened by calling Init(). Any uncommitted transactions - // will be rolled back when this object is deleted. + // The database is opened by calling Open[InMemory](). Any uncommitted + // transactions will be rolled back when this object is deleted. Connection(); ~Connection(); // Pre-init configuration ---------------------------------------------------- - // Sets the page size that will be used when creating a new adtabase. This + // Sets the page size that will be used when creating a new database. This // must be called before Init(), and will only have an effect on new // databases. // @@ -110,7 +114,7 @@ class Connection { // Sets the number of pages that will be cached in memory by sqlite. The // total cache size in bytes will be page_size * cache_size. This must be - // called before Init() to have an effect. + // called before Open() to have an effect. void set_cache_size(int cache_size) { cache_size_ = cache_size; } // Call to put the database in exclusive locking mode. There is no "back to @@ -122,11 +126,11 @@ class Connection { // transaction, which means there may be less time spent initializing the // next transaction because it doesn't have to re-aquire locks. // - // This must be called before Init() to have an effect. + // This must be called before Open() to have an effect. void set_exclusive_locking() { exclusive_locking_ = true; } // Sets the object that will handle errors. Recomended that it should be set - // before calling Init(). If not set, the default is to ignore errors on + // before calling Open(). If not set, the default is to ignore errors on // release and assert on debug builds. void set_error_delegate(ErrorDelegate* delegate) { error_delegate_ = delegate; @@ -135,8 +139,16 @@ class Connection { // Initialization ------------------------------------------------------------ // Initializes the SQL connection for the given file, returning true if the - // file could be opened. - bool Init(const FilePath& path); + // file could be opened. You can call this or InitInMemory to initialize. + bool Open(const FilePath& path); + + // Initializes the SQL connection for a temporary in-memory database. There + // will be no associated file on disk, and the initial database will be + // empty. You must call this or Init to open the database. + bool OpenInMemory(); + + // Returns trie if the database has been successfully opened. + bool is_open() const { return !!db_; } // Closes the database. This is automatically performed on destruction for // you, but this allows you to close the database early. You must not call @@ -225,7 +237,7 @@ class Connection { // Info querying ------------------------------------------------------------- // Returns true if the given table exists. - bool DoesTableExist( const char* table_name) const; + bool DoesTableExist(const char* table_name) const; // Returns true if a column with the given name exists in the given table. bool DoesColumnExist(const char* table_name, const char* column_name) const; @@ -253,6 +265,11 @@ class Connection { // (they should go through Statement). friend class Statement; + // Internal initialize function used by both Init and InitInMemory. The file + // name is always 8 bits since we want to use the 8-bit version of + // sqlite3_open. The string can also be sqlite's special ":memory:" string. + bool OpenInternal(const std::string& file_name); + // A StatementRef is a refcounted wrapper around a sqlite statement pointer. // Refcounting allows us to give these statements out to sql::Statement // objects while also optionally maintaining a cache of compiled statements diff --git a/app/sql/connection_unittest.cc b/app/sql/connection_unittest.cc index 70c9ffc..a36fca7 100644 --- a/app/sql/connection_unittest.cc +++ b/app/sql/connection_unittest.cc @@ -18,7 +18,7 @@ class SQLConnectionTest : public testing::Test { ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &path_)); path_ = path_.AppendASCII("SQLConnectionTest.db"); file_util::Delete(path_, false); - ASSERT_TRUE(db_.Init(path_)); + ASSERT_TRUE(db_.Open(path_)); } void TearDown() { diff --git a/app/sql/statement.cc b/app/sql/statement.cc index 3cadb6e..7abc225 100644 --- a/app/sql/statement.cc +++ b/app/sql/statement.cc @@ -70,6 +70,10 @@ bool Statement::BindNull(int col) { return false; } +bool Statement::BindBool(int col, bool val) { + return BindInt(col, val ? 1 : 0); +} + bool Statement::BindInt(int col, int val) { if (is_valid()) { int err = CheckError(sqlite3_bind_int(ref_->stmt(), col + 1, val)); @@ -129,6 +133,21 @@ int Statement::ColumnCount() const { return sqlite3_column_count(ref_->stmt()); } +ColType Statement::ColumnType(int col) const { + // Verify that our enum matches sqlite's values. + COMPILE_ASSERT(COLUMN_TYPE_INTEGER == SQLITE_INTEGER, integer_no_match); + COMPILE_ASSERT(COLUMN_TYPE_FLOAT == SQLITE_FLOAT, float_no_match); + COMPILE_ASSERT(COLUMN_TYPE_TEXT == SQLITE_TEXT, integer_no_match); + COMPILE_ASSERT(COLUMN_TYPE_BLOB == SQLITE_BLOB, blob_no_match); + COMPILE_ASSERT(COLUMN_TYPE_NULL == SQLITE_NULL, null_no_match); + + return static_cast<ColType>(sqlite3_column_type(ref_->stmt(), col)); +} + +bool Statement::ColumnBool(int col) const { + return !!ColumnInt(col); +} + int Statement::ColumnInt(int col) const { if (!is_valid()) { NOTREACHED(); diff --git a/app/sql/statement.h b/app/sql/statement.h index 6211d34..8ee6ef5 100644 --- a/app/sql/statement.h +++ b/app/sql/statement.h @@ -14,6 +14,16 @@ namespace sql { +// Possible return values from ColumnType in a statement. These should match +// the values in sqlite3.h. +enum ColType { + COLUMN_TYPE_INTEGER = 1, + COLUMN_TYPE_FLOAT = 2, + COLUMN_TYPE_TEXT = 3, + COLUMN_TYPE_BLOB = 4, + COLUMN_TYPE_NULL = 5, +}; + // Normal usage: // sql::Statement s = connection_.GetUniqueStatement(...); // if (!s) // You should check for errors before using the statement. @@ -88,6 +98,7 @@ class Statement { // The main thing you may want to check is when binding large blobs or // strings there may be out of memory. bool BindNull(int col); + bool BindBool(int col, bool val); bool BindInt(int col, int val); bool BindInt64(int col, int64 val); bool BindDouble(int col, double val); @@ -100,7 +111,16 @@ class Statement { // Returns the number of output columns in the result. int ColumnCount() const; + // Returns the type associated with the given column. + // + // Watch out: the type may be undefined if you've done something to cause a + // "type conversion." This means requesting the value of a column of a type + // where that type is not the native type. For safety, call ColumnType only + // on a column before getting the value out in any way. + ColType ColumnType(int col) const; + // These all take a 0-based argument index. + bool ColumnBool(int col) const; int ColumnInt(int col) const; int64 ColumnInt64(int col) const; double ColumnDouble(int col) const; diff --git a/app/sql/statement_unittest.cc b/app/sql/statement_unittest.cc index 5f04880..90f421c 100644 --- a/app/sql/statement_unittest.cc +++ b/app/sql/statement_unittest.cc @@ -19,7 +19,7 @@ class StatementErrorHandler : public sql::ErrorDelegate { virtual int OnError(int error, sql::Connection* connection, sql::Statement* stmt) { error_ = error; - const char* sql_txt = stmt->GetSQLStatement(); + const char* sql_txt = stmt ? stmt->GetSQLStatement() : NULL; sql_text_ = sql_txt ? sql_txt : "no statement available"; return error; } @@ -46,7 +46,7 @@ class SQLStatementTest : public testing::Test { ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &path_)); path_ = path_.AppendASCII("SQLStatementTest.db"); file_util::Delete(path_, false); - ASSERT_TRUE(db_.Init(path_)); + ASSERT_TRUE(db_.Open(path_)); // The |error_handler_| will be called if any sqlite statement operation // returns an error code. db_.set_error_delegate(error_handler_); diff --git a/app/sql/transaction_unittest.cc b/app/sql/transaction_unittest.cc index 0da79e3..55b77b9 100644 --- a/app/sql/transaction_unittest.cc +++ b/app/sql/transaction_unittest.cc @@ -19,7 +19,7 @@ class SQLTransactionTest : public testing::Test { ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &path_)); path_ = path_.AppendASCII("SQLStatementTest.db"); file_util::Delete(path_, false); - ASSERT_TRUE(db_.Init(path_)); + ASSERT_TRUE(db_.Open(path_)); ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); } |