OLD | NEW |
| (Empty) |
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/stringprintf.h" | |
13 #include "base/string_util.h" | |
14 #include "base/utf_string_conversions.h" | |
15 #include "third_party/sqlite/sqlite3.h" | |
16 | |
17 namespace { | |
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 | |
22 const base::TimeDelta kBusyTimeout = base::TimeDelta::FromSeconds(1); | |
23 | |
24 class 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 | |
45 namespace sql { | |
46 | |
47 bool 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 | |
53 ErrorDelegate::ErrorDelegate() { | |
54 } | |
55 | |
56 ErrorDelegate::~ErrorDelegate() { | |
57 } | |
58 | |
59 Connection::StatementRef::StatementRef() | |
60 : connection_(NULL), | |
61 stmt_(NULL) { | |
62 } | |
63 | |
64 Connection::StatementRef::StatementRef(Connection* connection, | |
65 sqlite3_stmt* stmt) | |
66 : connection_(connection), | |
67 stmt_(stmt) { | |
68 connection_->StatementRefCreated(this); | |
69 } | |
70 | |
71 Connection::StatementRef::~StatementRef() { | |
72 if (connection_) | |
73 connection_->StatementRefDeleted(this); | |
74 Close(); | |
75 } | |
76 | |
77 void 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 | |
85 Connection::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 | |
94 Connection::~Connection() { | |
95 Close(); | |
96 } | |
97 | |
98 bool Connection::Open(const FilePath& path) { | |
99 #if defined(OS_WIN) | |
100 return OpenInternal(WideToUTF8(path.value())); | |
101 #elif defined(OS_POSIX) | |
102 return OpenInternal(path.value()); | |
103 #endif | |
104 } | |
105 | |
106 bool Connection::OpenInMemory() { | |
107 return OpenInternal(":memory:"); | |
108 } | |
109 | |
110 void Connection::Close() { | |
111 statement_cache_.clear(); | |
112 DCHECK(open_statements_.empty()); | |
113 if (db_) { | |
114 sqlite3_close(db_); | |
115 db_ = NULL; | |
116 } | |
117 } | |
118 | |
119 void 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")); | |
131 if (!dummy || !dummy.Step()) | |
132 return; | |
133 | |
134 #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. | |
137 sqlite3_preload(db_); | |
138 #endif | |
139 } | |
140 | |
141 bool Connection::BeginTransaction() { | |
142 if (needs_rollback_) { | |
143 DCHECK_GT(transaction_nesting_, 0); | |
144 | |
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 | |
162 void Connection::RollbackTransaction() { | |
163 if (!transaction_nesting_) { | |
164 NOTREACHED() << "Rolling back a nonexistent transaction"; | |
165 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 | |
179 bool Connection::CommitTransaction() { | |
180 if (!transaction_nesting_) { | |
181 NOTREACHED() << "Rolling back a nonexistent transaction"; | |
182 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 | |
202 bool Connection::Execute(const char* sql) { | |
203 if (!db_) | |
204 return false; | |
205 return sqlite3_exec(db_, sql, NULL, NULL, NULL) == SQLITE_OK; | |
206 } | |
207 | |
208 bool 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 | |
217 bool Connection::HasCachedStatement(const StatementID& id) const { | |
218 return statement_cache_.find(id) != statement_cache_.end(); | |
219 } | |
220 | |
221 scoped_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 | |
241 scoped_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 | |
256 bool 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( | |
260 "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 | |
268 bool Connection::DoesColumnExist(const char* table_name, | |
269 const char* column_name) const { | |
270 std::string sql("PRAGMA TABLE_INFO("); | |
271 sql.append(table_name); | |
272 sql.append(")"); | |
273 | |
274 // Our SQL is non-mutating, so this cast is OK. | |
275 Statement statement(const_cast<Connection*>(this)->GetUniqueStatement( | |
276 sql.c_str())); | |
277 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 | |
287 int64 Connection::GetLastInsertRowId() const { | |
288 if (!db_) { | |
289 NOTREACHED(); | |
290 return 0; | |
291 } | |
292 return sqlite3_last_insert_rowid(db_); | |
293 } | |
294 | |
295 int Connection::GetLastChangeCount() const { | |
296 if (!db_) { | |
297 NOTREACHED(); | |
298 return 0; | |
299 } | |
300 return sqlite3_changes(db_); | |
301 } | |
302 | |
303 int Connection::GetErrorCode() const { | |
304 if (!db_) | |
305 return SQLITE_ERROR; | |
306 return sqlite3_errcode(db_); | |
307 } | |
308 | |
309 int 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 | |
320 const char* Connection::GetErrorMessage() const { | |
321 if (!db_) | |
322 return "sql::Connection has no connection."; | |
323 return sqlite3_errmsg(db_); | |
324 } | |
325 | |
326 bool Connection::OpenInternal(const std::string& file_name) { | |
327 if (db_) { | |
328 NOTREACHED() << "sql::Connection is already open."; | |
329 return false; | |
330 } | |
331 | |
332 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 | |
339 // 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 | |
347 // 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 | |
362 if (page_size_ != 0) { | |
363 // 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(); | |
371 } | |
372 | |
373 if (cache_size_ != 0) { | |
374 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(); | |
377 } | |
378 | |
379 return true; | |
380 } | |
381 | |
382 void Connection::DoRollback() { | |
383 Statement rollback(GetCachedStatement(SQL_FROM_HERE, "ROLLBACK")); | |
384 if (rollback) | |
385 rollback.Run(); | |
386 } | |
387 | |
388 void Connection::StatementRefCreated(StatementRef* ref) { | |
389 DCHECK(open_statements_.find(ref) == open_statements_.end()); | |
390 open_statements_.insert(ref); | |
391 } | |
392 | |
393 void 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 | |
401 void 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 | |
412 int 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 | |
420 } // namespace sql | |
OLD | NEW |