blob: 003f7b2cddd9465149c4d77ceb538e8b163284b3 [file] [log] [blame]
[email protected]e7afe2452010-08-22 16:19:131// Copyright (c) 2010 The Chromium Authors. All rights reserved.
[email protected]e5ffd0e42009-09-11 21:30:562// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "app/sql/connection.h"
6
7#include <string.h>
8
9#include "app/sql/statement.h"
10#include "base/file_path.h"
11#include "base/logging.h"
12#include "base/string_util.h"
[email protected]d55194ca2010-03-11 18:25:4513#include "base/utf_string_conversions.h"
[email protected]e33cba42010-08-18 23:37:0314#include "third_party/sqlite/sqlite3.h"
[email protected]e5ffd0e42009-09-11 21:30:5615
[email protected]5b96f3772010-09-28 16:30:5716namespace {
17
18// Spin for up to a second waiting for the lock to clear when setting
19// up the database.
20// TODO(shess): Better story on this. http://crbug.com/56559
21const base::TimeDelta kBusyTimeout = base::TimeDelta::FromSeconds(1);
22
23class ScopedBusyTimeout {
24 public:
25 explicit ScopedBusyTimeout(sqlite3* db)
26 : db_(db) {
27 }
28 ~ScopedBusyTimeout() {
29 sqlite3_busy_timeout(db_, 0);
30 }
31
32 int SetTimeout(base::TimeDelta timeout) {
33 DCHECK_LT(timeout.InMilliseconds(), INT_MAX);
34 return sqlite3_busy_timeout(db_,
35 static_cast<int>(timeout.InMilliseconds()));
36 }
37
38 private:
39 sqlite3* db_;
40};
41
42} // namespace
43
[email protected]e5ffd0e42009-09-11 21:30:5644namespace sql {
45
46bool StatementID::operator<(const StatementID& other) const {
47 if (number_ != other.number_)
48 return number_ < other.number_;
49 return strcmp(str_, other.str_) < 0;
50}
51
[email protected]d4799a32010-09-28 22:54:5852ErrorDelegate::ErrorDelegate() {
53}
54
55ErrorDelegate::~ErrorDelegate() {
56}
57
[email protected]e5ffd0e42009-09-11 21:30:5658Connection::StatementRef::StatementRef()
59 : connection_(NULL),
60 stmt_(NULL) {
61}
62
63Connection::StatementRef::StatementRef(Connection* connection,
64 sqlite3_stmt* stmt)
65 : connection_(connection),
66 stmt_(stmt) {
67 connection_->StatementRefCreated(this);
68}
69
70Connection::StatementRef::~StatementRef() {
71 if (connection_)
72 connection_->StatementRefDeleted(this);
73 Close();
74}
75
76void Connection::StatementRef::Close() {
77 if (stmt_) {
78 sqlite3_finalize(stmt_);
79 stmt_ = NULL;
80 }
81 connection_ = NULL; // The connection may be getting deleted.
82}
83
84Connection::Connection()
85 : db_(NULL),
86 page_size_(0),
87 cache_size_(0),
88 exclusive_locking_(false),
89 transaction_nesting_(0),
90 needs_rollback_(false) {
91}
92
93Connection::~Connection() {
94 Close();
95}
96
[email protected]765b44502009-10-02 05:01:4297bool Connection::Open(const FilePath& path) {
[email protected]e5ffd0e42009-09-11 21:30:5698#if defined(OS_WIN)
[email protected]765b44502009-10-02 05:01:4299 return OpenInternal(WideToUTF8(path.value()));
[email protected]e5ffd0e42009-09-11 21:30:56100#elif defined(OS_POSIX)
[email protected]765b44502009-10-02 05:01:42101 return OpenInternal(path.value());
[email protected]e5ffd0e42009-09-11 21:30:56102#endif
[email protected]765b44502009-10-02 05:01:42103}
[email protected]e5ffd0e42009-09-11 21:30:56104
[email protected]765b44502009-10-02 05:01:42105bool Connection::OpenInMemory() {
106 return OpenInternal(":memory:");
[email protected]e5ffd0e42009-09-11 21:30:56107}
108
109void Connection::Close() {
110 statement_cache_.clear();
111 DCHECK(open_statements_.empty());
112 if (db_) {
113 sqlite3_close(db_);
114 db_ = NULL;
115 }
116}
117
118void Connection::Preload() {
119 if (!db_) {
120 NOTREACHED();
121 return;
122 }
123
124 // A statement must be open for the preload command to work. If the meta
125 // table doesn't exist, it probably means this is a new database and there
126 // is nothing to preload (so it's OK we do nothing).
127 if (!DoesTableExist("meta"))
128 return;
129 Statement dummy(GetUniqueStatement("SELECT * FROM meta"));
[email protected]3fb6b1572009-10-07 20:10:30130 if (!dummy || !dummy.Step())
[email protected]e5ffd0e42009-09-11 21:30:56131 return;
132
[email protected]4176eee4b2011-01-26 14:33:32133#if !defined(USE_SYSTEM_SQLITE)
134 // This function is only defined in Chromium's version of sqlite.
135 // Do not call it when using system sqlite.
[email protected]e5ffd0e42009-09-11 21:30:56136 sqlite3Preload(db_);
[email protected]4176eee4b2011-01-26 14:33:32137#endif
[email protected]e5ffd0e42009-09-11 21:30:56138}
139
140bool Connection::BeginTransaction() {
141 if (needs_rollback_) {
[email protected]88563f62011-03-13 22:13:33142 DCHECK_GT(transaction_nesting_, 0);
[email protected]e5ffd0e42009-09-11 21:30:56143
144 // When we're going to rollback, fail on this begin and don't actually
145 // mark us as entering the nested transaction.
146 return false;
147 }
148
149 bool success = true;
150 if (!transaction_nesting_) {
151 needs_rollback_ = false;
152
153 Statement begin(GetCachedStatement(SQL_FROM_HERE, "BEGIN TRANSACTION"));
154 if (!begin || !begin.Run())
155 return false;
156 }
157 transaction_nesting_++;
158 return success;
159}
160
161void Connection::RollbackTransaction() {
162 if (!transaction_nesting_) {
[email protected]e7afe2452010-08-22 16:19:13163 NOTREACHED() << "Rolling back a nonexistent transaction";
[email protected]e5ffd0e42009-09-11 21:30:56164 return;
165 }
166
167 transaction_nesting_--;
168
169 if (transaction_nesting_ > 0) {
170 // Mark the outermost transaction as needing rollback.
171 needs_rollback_ = true;
172 return;
173 }
174
175 DoRollback();
176}
177
178bool Connection::CommitTransaction() {
179 if (!transaction_nesting_) {
[email protected]e7afe2452010-08-22 16:19:13180 NOTREACHED() << "Rolling back a nonexistent transaction";
[email protected]e5ffd0e42009-09-11 21:30:56181 return false;
182 }
183 transaction_nesting_--;
184
185 if (transaction_nesting_ > 0) {
186 // Mark any nested transactions as failing after we've already got one.
187 return !needs_rollback_;
188 }
189
190 if (needs_rollback_) {
191 DoRollback();
192 return false;
193 }
194
195 Statement commit(GetCachedStatement(SQL_FROM_HERE, "COMMIT"));
196 if (!commit)
197 return false;
198 return commit.Run();
199}
200
201bool Connection::Execute(const char* sql) {
202 if (!db_)
203 return false;
204 return sqlite3_exec(db_, sql, NULL, NULL, NULL) == SQLITE_OK;
205}
206
[email protected]5b96f3772010-09-28 16:30:57207bool Connection::ExecuteWithTimeout(const char* sql, base::TimeDelta timeout) {
208 if (!db_)
209 return false;
210
211 ScopedBusyTimeout busy_timeout(db_);
212 busy_timeout.SetTimeout(timeout);
213 return sqlite3_exec(db_, sql, NULL, NULL, NULL) == SQLITE_OK;
214}
215
[email protected]e5ffd0e42009-09-11 21:30:56216bool Connection::HasCachedStatement(const StatementID& id) const {
217 return statement_cache_.find(id) != statement_cache_.end();
218}
219
220scoped_refptr<Connection::StatementRef> Connection::GetCachedStatement(
221 const StatementID& id,
222 const char* sql) {
223 CachedStatementMap::iterator i = statement_cache_.find(id);
224 if (i != statement_cache_.end()) {
225 // Statement is in the cache. It should still be active (we're the only
226 // one invalidating cached statements, and we'll remove it from the cache
227 // if we do that. Make sure we reset it before giving out the cached one in
228 // case it still has some stuff bound.
229 DCHECK(i->second->is_valid());
230 sqlite3_reset(i->second->stmt());
231 return i->second;
232 }
233
234 scoped_refptr<StatementRef> statement = GetUniqueStatement(sql);
235 if (statement->is_valid())
236 statement_cache_[id] = statement; // Only cache valid statements.
237 return statement;
238}
239
240scoped_refptr<Connection::StatementRef> Connection::GetUniqueStatement(
241 const char* sql) {
242 if (!db_)
243 return new StatementRef(this, NULL); // Return inactive statement.
244
245 sqlite3_stmt* stmt = NULL;
246 if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK) {
247 // Treat this as non-fatal, it can occur in a number of valid cases, and
248 // callers should be doing their own error handling.
249 DLOG(WARNING) << "SQL compile error " << GetErrorMessage();
250 return new StatementRef(this, NULL);
251 }
252 return new StatementRef(this, stmt);
253}
254
[email protected]1ed78a32009-09-15 20:24:17255bool Connection::DoesTableExist(const char* table_name) const {
256 // GetUniqueStatement can't be const since statements may modify the
257 // database, but we know ours doesn't modify it, so the cast is safe.
258 Statement statement(const_cast<Connection*>(this)->GetUniqueStatement(
[email protected]e5ffd0e42009-09-11 21:30:56259 "SELECT name FROM sqlite_master "
260 "WHERE type='table' AND name=?"));
261 if (!statement)
262 return false;
263 statement.BindString(0, table_name);
264 return statement.Step(); // Table exists if any row was returned.
265}
266
267bool Connection::DoesColumnExist(const char* table_name,
[email protected]1ed78a32009-09-15 20:24:17268 const char* column_name) const {
[email protected]e5ffd0e42009-09-11 21:30:56269 std::string sql("PRAGMA TABLE_INFO(");
270 sql.append(table_name);
271 sql.append(")");
272
[email protected]1ed78a32009-09-15 20:24:17273 // Our SQL is non-mutating, so this cast is OK.
274 Statement statement(const_cast<Connection*>(this)->GetUniqueStatement(
275 sql.c_str()));
[email protected]e5ffd0e42009-09-11 21:30:56276 if (!statement)
277 return false;
278
279 while (statement.Step()) {
280 if (!statement.ColumnString(1).compare(column_name))
281 return true;
282 }
283 return false;
284}
285
286int64 Connection::GetLastInsertRowId() const {
287 if (!db_) {
288 NOTREACHED();
289 return 0;
290 }
291 return sqlite3_last_insert_rowid(db_);
292}
293
[email protected]1ed78a32009-09-15 20:24:17294int Connection::GetLastChangeCount() const {
295 if (!db_) {
296 NOTREACHED();
297 return 0;
298 }
299 return sqlite3_changes(db_);
300}
301
[email protected]e5ffd0e42009-09-11 21:30:56302int Connection::GetErrorCode() const {
303 if (!db_)
304 return SQLITE_ERROR;
305 return sqlite3_errcode(db_);
306}
307
[email protected]767718e52010-09-21 23:18:49308int Connection::GetLastErrno() const {
309 if (!db_)
310 return -1;
311
312 int err = 0;
313 if (SQLITE_OK != sqlite3_file_control(db_, NULL, SQLITE_LAST_ERRNO, &err))
314 return -2;
315
316 return err;
317}
318
[email protected]e5ffd0e42009-09-11 21:30:56319const char* Connection::GetErrorMessage() const {
320 if (!db_)
321 return "sql::Connection has no connection.";
322 return sqlite3_errmsg(db_);
323}
324
[email protected]765b44502009-10-02 05:01:42325bool Connection::OpenInternal(const std::string& file_name) {
[email protected]9cfbc922009-11-17 20:13:17326 if (db_) {
327 NOTREACHED() << "sql::Connection is already open.";
328 return false;
329 }
330
[email protected]765b44502009-10-02 05:01:42331 int err = sqlite3_open(file_name.c_str(), &db_);
332 if (err != SQLITE_OK) {
333 OnSqliteError(err, NULL);
334 db_ = NULL;
335 return false;
336 }
337
[email protected]658f8332010-09-18 04:40:43338 // Enable extended result codes to provide more color on I/O errors.
339 // Not having extended result codes is not a fatal problem, as
340 // Chromium code does not attempt to handle I/O errors anyhow. The
341 // current implementation always returns SQLITE_OK, the DCHECK is to
342 // quickly notify someone if SQLite changes.
343 err = sqlite3_extended_result_codes(db_, 1);
344 DCHECK_EQ(err, SQLITE_OK) << "Could not enable extended result codes";
345
[email protected]5b96f3772010-09-28 16:30:57346 // If indicated, lock up the database before doing anything else, so
347 // that the following code doesn't have to deal with locking.
348 // TODO(shess): This code is brittle. Find the cases where code
349 // doesn't request |exclusive_locking_| and audit that it does the
350 // right thing with SQLITE_BUSY, and that it doesn't make
351 // assumptions about who might change things in the database.
352 // http://crbug.com/56559
353 if (exclusive_locking_) {
354 // TODO(shess): This should probably be a full CHECK(). Code
355 // which requests exclusive locking but doesn't get it is almost
356 // certain to be ill-tested.
357 if (!Execute("PRAGMA locking_mode=EXCLUSIVE"))
358 NOTREACHED() << "Could not set locking mode: " << GetErrorMessage();
359 }
360
[email protected]765b44502009-10-02 05:01:42361 if (page_size_ != 0) {
[email protected]5b96f3772010-09-28 16:30:57362 // Enforce SQLite restrictions on |page_size_|.
363 DCHECK(!(page_size_ & (page_size_ - 1)))
364 << " page_size_ " << page_size_ << " is not a power of two.";
365 static const int kSqliteMaxPageSize = 32768; // from sqliteLimit.h
366 DCHECK_LE(page_size_, kSqliteMaxPageSize);
367 const std::string sql = StringPrintf("PRAGMA page_size=%d", page_size_);
368 if (!ExecuteWithTimeout(sql.c_str(), kBusyTimeout))
369 NOTREACHED() << "Could not set page size: " << GetErrorMessage();
[email protected]765b44502009-10-02 05:01:42370 }
371
372 if (cache_size_ != 0) {
[email protected]5b96f3772010-09-28 16:30:57373 const std::string sql = StringPrintf("PRAGMA cache_size=%d", cache_size_);
374 if (!ExecuteWithTimeout(sql.c_str(), kBusyTimeout))
375 NOTREACHED() << "Could not set cache size: " << GetErrorMessage();
[email protected]765b44502009-10-02 05:01:42376 }
377
378 return true;
379}
380
[email protected]e5ffd0e42009-09-11 21:30:56381void Connection::DoRollback() {
382 Statement rollback(GetCachedStatement(SQL_FROM_HERE, "ROLLBACK"));
383 if (rollback)
384 rollback.Run();
385}
386
387void Connection::StatementRefCreated(StatementRef* ref) {
388 DCHECK(open_statements_.find(ref) == open_statements_.end());
389 open_statements_.insert(ref);
390}
391
392void Connection::StatementRefDeleted(StatementRef* ref) {
393 StatementRefSet::iterator i = open_statements_.find(ref);
394 if (i == open_statements_.end())
395 NOTREACHED();
396 else
397 open_statements_.erase(i);
398}
399
400void Connection::ClearCache() {
401 statement_cache_.clear();
402
403 // The cache clear will get most statements. There may be still be references
404 // to some statements that are held by others (including one-shot statements).
405 // This will deactivate them so they can't be used again.
406 for (StatementRefSet::iterator i = open_statements_.begin();
407 i != open_statements_.end(); ++i)
408 (*i)->Close();
409}
410
[email protected]faa604e2009-09-25 22:38:59411int Connection::OnSqliteError(int err, sql::Statement *stmt) {
412 if (error_delegate_.get())
413 return error_delegate_->OnError(err, this, stmt);
414 // The default handling is to assert on debug and to ignore on release.
415 NOTREACHED() << GetErrorMessage();
416 return err;
417}
418
[email protected]e5ffd0e42009-09-11 21:30:56419} // namespace sql