1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef CHROME_COMMON_SQLITE_UTILS_H_ 6#define CHROME_COMMON_SQLITE_UTILS_H_ 7#pragma once 8 9#include <string> 10#include <vector> 11 12#include "base/basictypes.h" 13#include "base/memory/scoped_ptr.h" 14#include "base/string16.h" 15#include "base/utf_string_conversions.h" 16#include "third_party/sqlite/sqlite3.h" 17 18// forward declarations of classes defined here 19class FilePath; 20class SQLTransaction; 21class SQLNestedTransaction; 22class SQLNestedTransactionSite; 23class scoped_sqlite3_stmt_ptr; 24class SQLStatement; 25 26//------------------------------------------------------------------------------ 27// Interface to be implemented by objects that can handle exceptional sqlite 28// conditions. This way client code can focus on handling normal condtions. 29//------------------------------------------------------------------------------ 30class SQLErrorHandler { 31 public: 32 virtual ~SQLErrorHandler() {} 33 // Handle a sqlite error. |error| is the return code an of sqlite operation 34 // which is considered an error. This handler is free to try repair, notify 35 // someone or even break into the debugger depending on the situation. 36 virtual int HandleError(int error, sqlite3* db) = 0; 37 // Returns the last value of |error| passed to HandleError. 38 virtual int GetLastError() const = 0; 39}; 40 41//------------------------------------------------------------------------------ 42// The factory interface is used to create the different error handling 43// strategies for debug, release and for diagnostic mode. 44//------------------------------------------------------------------------------ 45class SQLErrorHandlerFactory { 46 public: 47 virtual ~SQLErrorHandlerFactory() {} 48 virtual SQLErrorHandler* Make() = 0; 49}; 50 51//------------------------------------------------------------------------------ 52// A wrapper for sqlite transactions that rollsback when the wrapper 53// goes out of scope if the caller has not already called Commit or Rollback. 54// Note: the constructor does NOT Begin a transaction. 55//------------------------------------------------------------------------------ 56class SQLTransaction { 57 public: 58 explicit SQLTransaction(sqlite3* db); 59 virtual ~SQLTransaction(); 60 61 int Begin() { 62 // By default, we BEGIN IMMEDIATE to establish file locks at the 63 // onset of a transaction. This avoids SQLITE_BUSY errors, without 64 // waiting for the busy timeout period, which can occur when BEGIN 65 // DEFERRED is used. 66 return BeginImmediate(); 67 } 68 69 int BeginExclusive() { 70 return BeginCommand("BEGIN EXCLUSIVE"); 71 } 72 73 int BeginImmediate() { 74 return BeginCommand("BEGIN IMMEDIATE"); 75 } 76 77 int BeginDeferred() { 78 return BeginCommand("BEGIN DEFERRED"); 79 } 80 81 int Commit() { 82 return EndCommand("COMMIT"); 83 } 84 85 int Rollback() { 86 return EndCommand("ROLLBACK"); 87 } 88 89 bool HasBegun() { 90 return began_; 91 } 92 93 protected: 94 virtual int BeginCommand(const char* command); 95 virtual int EndCommand(const char* command); 96 97 sqlite3* db_; 98 bool began_; 99 DISALLOW_COPY_AND_ASSIGN(SQLTransaction); 100}; 101 102 103//------------------------------------------------------------------------------ 104// A class for use with SQLNestedTransaction. 105//------------------------------------------------------------------------------ 106class SQLNestedTransactionSite { 107 protected: 108 SQLNestedTransactionSite() : db_(NULL), top_transaction_(NULL) {} 109 virtual ~SQLNestedTransactionSite(); 110 111 // The following virtual methods provide notification of true transaction 112 // boundaries as they are crossed by a top nested transaction. 113 // Intended to be overriden (See WebCacheDB) 114 // SQLNestedTransaction calls these after the underlying database 115 // operation has been performed. 116 117 virtual void OnBegin() {} 118 virtual void OnCommit() {} 119 virtual void OnRollback() {} 120 121 // Returns the sqlite3 database connection associated with this site 122 // Used by SQLNestedTransaction 123 sqlite3* GetSqlite3DB() { return db_; } 124 125 // Returns the current top nested transaction associated with this site 126 // Used by SQLNestedTransaction 127 SQLNestedTransaction* GetTopTransaction() { 128 return top_transaction_; 129 } 130 131 // Sets or clears the top nested transaction associated with this site 132 // Used by SQLNestedTransaction 133 void SetTopTransaction(SQLNestedTransaction* top); 134 135 sqlite3* db_; 136 SQLNestedTransaction* top_transaction_; 137 friend class SQLNestedTransaction; 138}; 139 140//------------------------------------------------------------------------------ 141// SQLite does not support nested transactions. This class provides a gross 142// approximation of nested transactions. 143// 144// Really there is only one transaction, the top transaction. 145// 146// A nested transaction commits with respect to the top transaction. 147// That is, even though the nested transaction commits, the permanence of its 148// effects depends on the top transaction committing. If the top 149// transaction rollsback, the results of the nested transaction are backed out. 150// If any nested transaction aborts, the top transaction ultimately rollsback 151// as well. 152// 153// Note: If a nested transaction is open for a particular db connection, an 154// attempt to open a non-nested transaction (class SQLTransaction) will fail. 155// And vice versa. 156// 157// TODO(michaeln): demonstrate usage here 158// TODO(michaeln): safegaurds to prevent mis-use 159//------------------------------------------------------------------------------ 160class SQLNestedTransaction : public SQLTransaction { 161 public: 162 explicit SQLNestedTransaction(SQLNestedTransactionSite* site); 163 virtual ~SQLNestedTransaction(); 164 165 protected: 166 virtual int BeginCommand(const char* command); 167 virtual int EndCommand(const char* command); 168 169 private: 170 bool needs_rollback_; 171 SQLNestedTransactionSite* site_; 172 DISALLOW_COPY_AND_ASSIGN(SQLNestedTransaction); 173}; 174 175//------------------------------------------------------------------------------ 176// A scoped sqlite statement that finalizes when it goes out of scope. 177//------------------------------------------------------------------------------ 178class scoped_sqlite3_stmt_ptr { 179 public: 180 ~scoped_sqlite3_stmt_ptr() { 181 finalize(); 182 } 183 184 scoped_sqlite3_stmt_ptr() : stmt_(NULL) { 185 } 186 187 explicit scoped_sqlite3_stmt_ptr(sqlite3_stmt* stmt) 188 : stmt_(stmt) { 189 } 190 191 sqlite3_stmt* get() const { 192 return stmt_; 193 } 194 195 void set(sqlite3_stmt* stmt) { 196 finalize(); 197 stmt_ = stmt; 198 } 199 200 sqlite3_stmt* release() { 201 sqlite3_stmt* tmp = stmt_; 202 stmt_ = NULL; 203 return tmp; 204 } 205 206 // It is not safe to call sqlite3_finalize twice on the same stmt. 207 // Sqlite3's sqlite3_finalize() function should not be called directly 208 // without calling the release method. If sqlite3_finalize() must be 209 // called directly, the following usage is advised: 210 // scoped_sqlite3_stmt_ptr stmt; 211 // ... do something with stmt ... 212 // sqlite3_finalize(stmt.release()); 213 int finalize() { 214 int err = sqlite3_finalize(stmt_); 215 stmt_ = NULL; 216 return err; 217 } 218 219 protected: 220 sqlite3_stmt* stmt_; 221 222 private: 223 DISALLOW_COPY_AND_ASSIGN(scoped_sqlite3_stmt_ptr); 224}; 225 226//------------------------------------------------------------------------------ 227// A scoped sqlite statement with convenient C++ wrappers for sqlite3 APIs. 228//------------------------------------------------------------------------------ 229class SQLStatement : public scoped_sqlite3_stmt_ptr { 230 public: 231 SQLStatement() {} 232 233 int prepare(sqlite3* db, const char* sql) { 234 return prepare(db, sql, -1); 235 } 236 237 int prepare(sqlite3* db, const char* sql, int sql_len); 238 239 int step(); 240 int reset(); 241 sqlite_int64 last_insert_rowid(); 242 int changes(); 243 sqlite3* db_handle(); 244 245 // 246 // Parameter binding helpers (NOTE: index is 0-based) 247 // 248 249 int bind_parameter_count(); 250 251 typedef void (*Function)(void*); 252 253 int bind_blob(int index, std::vector<unsigned char>* blob); 254 int bind_blob(int index, const void* value, int value_len); 255 int bind_blob(int index, const void* value, int value_len, Function dtor); 256 int bind_double(int index, double value); 257 int bind_bool(int index, bool value); 258 int bind_int(int index, int value); 259 int bind_int64(int index, sqlite_int64 value); 260 int bind_null(int index); 261 262 int bind_string(int index, const std::string& value) { 263 // don't use c_str so it doesn't have to fix up the null terminator 264 // (sqlite just uses the length) 265 return bind_text(index, value.data(), 266 static_cast<int>(value.length()), SQLITE_TRANSIENT); 267 } 268 269 int bind_string16(int index, const string16& value) { 270 // don't use c_str so it doesn't have to fix up the null terminator 271 // (sqlite just uses the length) 272 std::string value_utf8(UTF16ToUTF8(value)); 273 return bind_text(index, value_utf8.data(), 274 static_cast<int>(value_utf8.length()), SQLITE_TRANSIENT); 275 } 276 277 int bind_wstring(int index, const std::wstring& value) { 278 // don't use c_str so it doesn't have to fix up the null terminator 279 // (sqlite just uses the length) 280 std::string value_utf8(WideToUTF8(value)); 281 return bind_text(index, value_utf8.data(), 282 static_cast<int>(value_utf8.length()), SQLITE_TRANSIENT); 283 } 284 285 int bind_text(int index, const char* value) { 286 return bind_text(index, value, -1, SQLITE_TRANSIENT); 287 } 288 289 // value_len is number of characters or may be negative 290 // a for null-terminated value string 291 int bind_text(int index, const char* value, int value_len) { 292 return bind_text(index, value, value_len, SQLITE_TRANSIENT); 293 } 294 295 // value_len is number of characters or may be negative 296 // a for null-terminated value string 297 int bind_text(int index, const char* value, int value_len, 298 Function dtor); 299 300 int bind_text16(int index, const char16* value) { 301 return bind_text16(index, value, -1, SQLITE_TRANSIENT); 302 } 303 304 // value_len is number of characters or may be negative 305 // a for null-terminated value string 306 int bind_text16(int index, const char16* value, int value_len) { 307 return bind_text16(index, value, value_len, SQLITE_TRANSIENT); 308 } 309 310 // value_len is number of characters or may be negative 311 // a for null-terminated value string 312 int bind_text16(int index, const char16* value, int value_len, 313 Function dtor); 314 315 int bind_value(int index, const sqlite3_value* value); 316 317 // 318 // Column helpers (NOTE: index is 0-based) 319 // 320 321 int column_count(); 322 int column_type(int index); 323 const void* column_blob(int index); 324 bool column_blob_as_vector(int index, std::vector<unsigned char>* blob); 325 bool column_blob_as_string(int index, std::string* blob); 326 int column_bytes(int index); 327 int column_bytes16(int index); 328 double column_double(int index); 329 bool column_bool(int index); 330 int column_int(int index); 331 sqlite_int64 column_int64(int index); 332 const char* column_text(int index); 333 bool column_string(int index, std::string* str); 334 std::string column_string(int index); 335 const char16* column_text16(int index); 336 bool column_string16(int index, string16* str); 337 string16 column_string16(int index); 338 bool column_wstring(int index, std::wstring* str); 339 std::wstring column_wstring(int index); 340 341 private: 342 DISALLOW_COPY_AND_ASSIGN(SQLStatement); 343}; 344 345namespace sqlite_utils { 346 347//------------------------------------------------------------------------------ 348// A scoped sqlite database that closes when it goes out of scope. 349//------------------------------------------------------------------------------ 350class DBClose { 351 public: 352 inline void operator()(sqlite3* x) const { 353 sqlite3_close(x); 354 } 355}; 356 357typedef scoped_ptr_malloc<sqlite3, DBClose> scoped_sqlite_db_ptr; 358 359// Opens the DB in the file pointed to by |filepath|. This method forces the 360// database to be in UTF-8 mode on all platforms. See 361// http://www.sqlite.org/capi3ref.html#sqlite3_open for an explanation of the 362// return value. 363int OpenSqliteDb(const FilePath& filepath, sqlite3** database); 364 365// Returns true if there is a table with the given name in the database. 366// For the version where a database name is specified, it may be NULL or the 367// empty string if no database name is necessary. 368bool DoesSqliteTableExist(sqlite3* db, 369 const char* db_name, 370 const char* table_name); 371inline bool DoesSqliteTableExist(sqlite3* db, const char* table_name) { 372 return DoesSqliteTableExist(db, NULL, table_name); 373} 374 375// Test whether a table has a column matching the provided name and type. 376// Returns true if the column exist and false otherwise. There are two 377// versions, one that takes a database name, the other that doesn't. The 378// database name can be NULL or empty if no name is desired. 379// 380// Column type is optional, it can be NULL or empty. If specified, we the 381// function will check that the column is of the correct type (case-sensetive). 382bool DoesSqliteColumnExist(sqlite3* db, 383 const char* datbase_name, 384 const char* table_name, 385 const char* column_name, 386 const char* column_type); 387inline bool DoesSqliteColumnExist(sqlite3* db, 388 const char* table_name, 389 const char* column_name, 390 const char* column_type) { 391 return DoesSqliteColumnExist(db, NULL, table_name, column_name, column_type); 392} 393 394// Test whether a table has one or more rows. Returns true if the table 395// has one or more rows and false if the table is empty or doesn't exist. 396bool DoesSqliteTableHaveRow(sqlite3* db, const char* table_name); 397 398} // namespace sqlite_utils 399 400#endif // CHROME_COMMON_SQLITE_UTILS_H_ 401