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