sqlite_utils.h revision ddb351dbec246cf1fab5ec20d2d5520909041de1
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