blob: 3f63301ace0115f30add936a3a0639ba52327b77 [file] [log] [blame]
[email protected]67361b32011-04-12 20:13:061// Copyright (c) 2011 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
[email protected]f0a54b22011-07-19 18:40:215#include "sql/connection.h"
[email protected]e5ffd0e42009-09-11 21:30:566
7#include <string.h>
8
[email protected]e5ffd0e42009-09-11 21:30:569#include "base/file_path.h"
10#include "base/logging.h"
11#include "base/string_util.h"
[email protected]f0a54b22011-07-19 18:40:2112#include "base/stringprintf.h"
[email protected]d55194ca2010-03-11 18:25:4513#include "base/utf_string_conversions.h"
[email protected]f0a54b22011-07-19 18:40:2114#include "sql/statement.h"
[email protected]e33cba42010-08-18 23:37:0315#include "third_party/sqlite/sqlite3.h"
[email protected]e5ffd0e42009-09-11 21:30:5616
[email protected]5b96f3772010-09-28 16:30:5717namespace {
18
19// Spin for up to a second waiting for the lock to clear when setting
20// up the database.
21// TODO(shess): Better story on this. http://crbug.com/56559
22const base::TimeDelta kBusyTimeout = base::TimeDelta::FromSeconds(1);
23
24class ScopedBusyTimeout {
25 public:
26 explicit ScopedBusyTimeout(sqlite3* db)
27 : db_(db) {
28 }
29 ~ScopedBusyTimeout() {
30 sqlite3_busy_timeout(db_, 0);
31 }
32
33 int SetTimeout(base::TimeDelta timeout) {
34 DCHECK_LT(timeout.InMilliseconds(), INT_MAX);
35 return sqlite3_busy_timeout(db_,
36 static_cast<int>(timeout.InMilliseconds()));
37 }
38
39 private:
40 sqlite3* db_;
41};
42
43} // namespace
44
[email protected]e5ffd0e42009-09-11 21:30:5645namespace sql {
46
47bool StatementID::operator<(const StatementID& other) const {
48 if (number_ != other.number_)
49 return number_ < other.number_;
50 return strcmp(str_, other.str_) < 0;
51}
52
[email protected]d4799a32010-09-28 22:54:5853ErrorDelegate::ErrorDelegate() {
54}
55
56ErrorDelegate::~ErrorDelegate() {
57}
58
[email protected]e5ffd0e42009-09-11 21:30:5659Connection::StatementRef::StatementRef()
60 : connection_(NULL),
61 stmt_(NULL) {
62}
63
64Connection::StatementRef::StatementRef(Connection* connection,
65 sqlite3_stmt* stmt)
66 : connection_(connection),
67 stmt_(stmt) {
68 connection_->StatementRefCreated(this);
69}
70
71Connection::StatementRef::~StatementRef() {
72 if (connection_)
73 connection_->StatementRefDeleted(this);
74 Close();
75}
76
77void Connection::StatementRef::Close() {
78 if (stmt_) {
79 sqlite3_finalize(stmt_);
80 stmt_ = NULL;
81 }
82 connection_ = NULL; // The connection may be getting deleted.
83}
84
85Connection::Connection()
86 : db_(NULL),
87 page_size_(0),
88 cache_size_(0),
89 exclusive_locking_(false),
90 transaction_nesting_(0),
91 needs_rollback_(false) {
92}
93
94Connection::~Connection() {
95 Close();
96}
97
[email protected]765b44502009-10-02 05:01:4298bool Connection::Open(const FilePath& path) {
[email protected]e5ffd0e42009-09-11 21:30:5699#if defined(OS_WIN)
[email protected]765b44502009-10-02 05:01:42100 return OpenInternal(WideToUTF8(path.value()));
[email protected]e5ffd0e42009-09-11 21:30:56101#elif defined(OS_POSIX)
[email protected]765b44502009-10-02 05:01:42102 return OpenInternal(path.value());
[email protected]e5ffd0e42009-09-11 21:30:56103#endif
[email protected]765b44502009-10-02 05:01:42104}
[email protected]e5ffd0e42009-09-11 21:30:56105
[email protected]765b44502009-10-02 05:01:42106bool Connection::OpenInMemory() {
107 return OpenInternal(":memory:");
[email protected]e5ffd0e42009-09-11 21:30:56108}
109
110void Connection::Close() {
111 statement_cache_.clear();
112 DCHECK(open_statements_.empty());
113 if (db_) {
114 sqlite3_close(db_);
115 db_ = NULL;
116 }
117}
118
119void Connection::Preload() {
120 if (!db_) {
121 NOTREACHED();
122 return;
123 }
124
125 // A statement must be open for the preload command to work. If the meta
126 // table doesn't exist, it probably means this is a new database and there
127 // is nothing to preload (so it's OK we do nothing).
128 if (!DoesTableExist("meta"))
129 return;
130 Statement dummy(GetUniqueStatement("SELECT * FROM meta"));
[email protected]3fb6b1572009-10-07 20:10:30131 if (!dummy || !dummy.Step())
[email protected]e5ffd0e42009-09-11 21:30:56132 return;
133
[email protected]4176eee4b2011-01-26 14:33:32134#if !defined(USE_SYSTEM_SQLITE)
135 // This function is only defined in Chromium's version of sqlite.
136 // Do not call it when using system sqlite.
[email protected]67361b32011-04-12 20:13:06137 sqlite3_preload(db_);
[email protected]4176eee4b2011-01-26 14:33:32138#endif
[email protected]e5ffd0e42009-09-11 21:30:56139}
140
141bool Connection::BeginTransaction() {
142 if (needs_rollback_) {
[email protected]88563f62011-03-13 22:13:33143 DCHECK_GT(transaction_nesting_, 0);
[email protected]e5ffd0e42009-09-11 21:30:56144
145 // When we're going to rollback, fail on this begin and don't actually
146 // mark us as entering the nested transaction.
147 return false;
148 }
149
150 bool success = true;
151 if (!transaction_nesting_) {
152 needs_rollback_ = false;
153
154 Statement begin(GetCachedStatement(SQL_FROM_HERE, "BEGIN TRANSACTION"));
155 if (!begin || !begin.Run())
156 return false;
157 }
158 transaction_nesting_++;
159 return success;
160}
161
162void Connection::RollbackTransaction() {
163 if (!transaction_nesting_) {
[email protected]e7afe2452010-08-22 16:19:13164 NOTREACHED() << "Rolling back a nonexistent transaction";
[email protected]e5ffd0e42009-09-11 21:30:56165 return;
166 }
167
168 transaction_nesting_--;
169
170 if (transaction_nesting_ > 0) {
171 // Mark the outermost transaction as needing rollback.
172 needs_rollback_ = true;
173 return;
174 }
175
176 DoRollback();
177}
178
179bool Connection::CommitTransaction() {
180 if (!transaction_nesting_) {
[email protected]e7afe2452010-08-22 16:19:13181 NOTREACHED() << "Rolling back a nonexistent transaction";
[email protected]e5ffd0e42009-09-11 21:30:56182 return false;
183 }
184 transaction_nesting_--;
185
186 if (transaction_nesting_ > 0) {
187 // Mark any nested transactions as failing after we've already got one.
188 return !needs_rollback_;
189 }
190
191 if (needs_rollback_) {
192 DoRollback();
193 return false;
194 }
195
196 Statement commit(GetCachedStatement(SQL_FROM_HERE, "COMMIT"));
197 if (!commit)
198 return false;
199 return commit.Run();
200}
201
202bool Connection::Execute(const char* sql) {
203 if (!db_)
204 return false;
205 return sqlite3_exec(db_, sql, NULL, NULL, NULL) == SQLITE_OK;
206}
207
[email protected]5b96f3772010-09-28 16:30:57208bool Connection::ExecuteWithTimeout(const char* sql, base::TimeDelta timeout) {
209 if (!db_)
210 return false;
211
212 ScopedBusyTimeout busy_timeout(db_);
213 busy_timeout.SetTimeout(timeout);
214 return sqlite3_exec(db_, sql, NULL, NULL, NULL) == SQLITE_OK;
215}
216
[email protected]e5ffd0e42009-09-11 21:30:56217bool Connection::HasCachedStatement(const StatementID& id) const {
218 return statement_cache_.find(id) != statement_cache_.end();
219}
220
221scoped_refptr<Connection::StatementRef> Connection::GetCachedStatement(
222 const StatementID& id,
223 const char* sql) {
224 CachedStatementMap::iterator i = statement_cache_.find(id);
225 if (i != statement_cache_.end()) {
226 // Statement is in the cache. It should still be active (we're the only
227 // one invalidating cached statements, and we'll remove it from the cache
228 // if we do that. Make sure we reset it before giving out the cached one in
229 // case it still has some stuff bound.
230 DCHECK(i->second->is_valid());
231 sqlite3_reset(i->second->stmt());
232 return i->second;
233 }
234
235 scoped_refptr<StatementRef> statement = GetUniqueStatement(sql);
236 if (statement->is_valid())
237 statement_cache_[id] = statement; // Only cache valid statements.
238 return statement;
239}
240
241scoped_refptr<Connection::StatementRef> Connection::GetUniqueStatement(
242 const char* sql) {
243 if (!db_)
244 return new StatementRef(this, NULL); // Return inactive statement.
245
246 sqlite3_stmt* stmt = NULL;
247 if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK) {
248 // Treat this as non-fatal, it can occur in a number of valid cases, and
249 // callers should be doing their own error handling.
250 DLOG(WARNING) << "SQL compile error " << GetErrorMessage();
251 return new StatementRef(this, NULL);
252 }
253 return new StatementRef(this, stmt);
254}
255
[email protected]1ed78a32009-09-15 20:24:17256bool Connection::DoesTableExist(const char* table_name) const {
257 // GetUniqueStatement can't be const since statements may modify the
258 // database, but we know ours doesn't modify it, so the cast is safe.
259 Statement statement(const_cast<Connection*>(this)->GetUniqueStatement(
[email protected]e5ffd0e42009-09-11 21:30:56260 "SELECT name FROM sqlite_master "
261 "WHERE type='table' AND name=?"));
262 if (!statement)
263 return false;
264 statement.BindString(0, table_name);
265 return statement.Step(); // Table exists if any row was returned.
266}
267
268bool Connection::DoesColumnExist(const char* table_name,
[email protected]1ed78a32009-09-15 20:24:17269 const char* column_name) const {
[email protected]e5ffd0e42009-09-11 21:30:56270 std::string sql("PRAGMA TABLE_INFO(");
271 sql.append(table_name);
272 sql.append(")");
273
[email protected]1ed78a32009-09-15 20:24:17274 // Our SQL is non-mutating, so this cast is OK.
275 Statement statement(const_cast<Connection*>(this)->GetUniqueStatement(
276 sql.c_str()));
[email protected]e5ffd0e42009-09-11 21:30:56277 if (!statement)
278 return false;
279
280 while (statement.Step()) {
281 if (!statement.ColumnString(1).compare(column_name))
282 return true;
283 }
284 return false;
285}
286
287int64 Connection::GetLastInsertRowId() const {
288 if (!db_) {
289 NOTREACHED();
290 return 0;
291 }
292 return sqlite3_last_insert_rowid(db_);
293}
294
[email protected]1ed78a32009-09-15 20:24:17295int Connection::GetLastChangeCount() const {
296 if (!db_) {
297 NOTREACHED();
298 return 0;
299 }
300 return sqlite3_changes(db_);
301}
302
[email protected]e5ffd0e42009-09-11 21:30:56303int Connection::GetErrorCode() const {
304 if (!db_)
305 return SQLITE_ERROR;
306 return sqlite3_errcode(db_);
307}
308
[email protected]767718e52010-09-21 23:18:49309int Connection::GetLastErrno() const {
310 if (!db_)
311 return -1;
312
313 int err = 0;
314 if (SQLITE_OK != sqlite3_file_control(db_, NULL, SQLITE_LAST_ERRNO, &err))
315 return -2;
316
317 return err;
318}
319
[email protected]e5ffd0e42009-09-11 21:30:56320const char* Connection::GetErrorMessage() const {
321 if (!db_)
322 return "sql::Connection has no connection.";
323 return sqlite3_errmsg(db_);
324}
325
[email protected]765b44502009-10-02 05:01:42326bool Connection::OpenInternal(const std::string& file_name) {
[email protected]9cfbc922009-11-17 20:13:17327 if (db_) {
328 NOTREACHED() << "sql::Connection is already open.";
329 return false;
330 }
331
[email protected]765b44502009-10-02 05:01:42332 int err = sqlite3_open(file_name.c_str(), &db_);
333 if (err != SQLITE_OK) {
334 OnSqliteError(err, NULL);
335 db_ = NULL;
336 return false;
337 }
338
[email protected]658f8332010-09-18 04:40:43339 // Enable extended result codes to provide more color on I/O errors.
340 // Not having extended result codes is not a fatal problem, as
341 // Chromium code does not attempt to handle I/O errors anyhow. The
342 // current implementation always returns SQLITE_OK, the DCHECK is to
343 // quickly notify someone if SQLite changes.
344 err = sqlite3_extended_result_codes(db_, 1);
345 DCHECK_EQ(err, SQLITE_OK) << "Could not enable extended result codes";
346
[email protected]5b96f3772010-09-28 16:30:57347 // If indicated, lock up the database before doing anything else, so
348 // that the following code doesn't have to deal with locking.
349 // TODO(shess): This code is brittle. Find the cases where code
350 // doesn't request |exclusive_locking_| and audit that it does the
351 // right thing with SQLITE_BUSY, and that it doesn't make
352 // assumptions about who might change things in the database.
353 // http://crbug.com/56559
354 if (exclusive_locking_) {
355 // TODO(shess): This should probably be a full CHECK(). Code
356 // which requests exclusive locking but doesn't get it is almost
357 // certain to be ill-tested.
358 if (!Execute("PRAGMA locking_mode=EXCLUSIVE"))
359 NOTREACHED() << "Could not set locking mode: " << GetErrorMessage();
360 }
361
[email protected]765b44502009-10-02 05:01:42362 if (page_size_ != 0) {
[email protected]5b96f3772010-09-28 16:30:57363 // Enforce SQLite restrictions on |page_size_|.
364 DCHECK(!(page_size_ & (page_size_ - 1)))
365 << " page_size_ " << page_size_ << " is not a power of two.";
366 static const int kSqliteMaxPageSize = 32768; // from sqliteLimit.h
367 DCHECK_LE(page_size_, kSqliteMaxPageSize);
368 const std::string sql = StringPrintf("PRAGMA page_size=%d", page_size_);
369 if (!ExecuteWithTimeout(sql.c_str(), kBusyTimeout))
370 NOTREACHED() << "Could not set page size: " << GetErrorMessage();
[email protected]765b44502009-10-02 05:01:42371 }
372
373 if (cache_size_ != 0) {
[email protected]5b96f3772010-09-28 16:30:57374 const std::string sql = StringPrintf("PRAGMA cache_size=%d", cache_size_);
375 if (!ExecuteWithTimeout(sql.c_str(), kBusyTimeout))
376 NOTREACHED() << "Could not set cache size: " << GetErrorMessage();
[email protected]765b44502009-10-02 05:01:42377 }
378
379 return true;
380}
381
[email protected]e5ffd0e42009-09-11 21:30:56382void Connection::DoRollback() {
383 Statement rollback(GetCachedStatement(SQL_FROM_HERE, "ROLLBACK"));
384 if (rollback)
385 rollback.Run();
386}
387
388void Connection::StatementRefCreated(StatementRef* ref) {
389 DCHECK(open_statements_.find(ref) == open_statements_.end());
390 open_statements_.insert(ref);
391}
392
393void Connection::StatementRefDeleted(StatementRef* ref) {
394 StatementRefSet::iterator i = open_statements_.find(ref);
395 if (i == open_statements_.end())
396 NOTREACHED();
397 else
398 open_statements_.erase(i);
399}
400
401void Connection::ClearCache() {
402 statement_cache_.clear();
403
404 // The cache clear will get most statements. There may be still be references
405 // to some statements that are held by others (including one-shot statements).
406 // This will deactivate them so they can't be used again.
407 for (StatementRefSet::iterator i = open_statements_.begin();
408 i != open_statements_.end(); ++i)
409 (*i)->Close();
410}
411
[email protected]faa604e2009-09-25 22:38:59412int Connection::OnSqliteError(int err, sql::Statement *stmt) {
413 if (error_delegate_.get())
414 return error_delegate_->OnError(err, this, stmt);
415 // The default handling is to assert on debug and to ignore on release.
416 NOTREACHED() << GetErrorMessage();
417 return err;
418}
419
[email protected]e5ffd0e42009-09-11 21:30:56420} // namespace sql