Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Side by Side Diff: sql/connection.cc

Issue 10540155: Annotate calls to SQLite functions - they have to be executed on a thread allowing IO access. (Closed) Base URL: https://src.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sql/connection.h ('k') | sql/statement.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "sql/connection.h" 5 #include "sql/connection.h"
6 6
7 #include <string.h> 7 #include <string.h>
8 8
9 #include "base/file_path.h" 9 #include "base/file_path.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 } 69 }
70 70
71 Connection::StatementRef::~StatementRef() { 71 Connection::StatementRef::~StatementRef() {
72 if (connection_) 72 if (connection_)
73 connection_->StatementRefDeleted(this); 73 connection_->StatementRefDeleted(this);
74 Close(); 74 Close();
75 } 75 }
76 76
77 void Connection::StatementRef::Close() { 77 void Connection::StatementRef::Close() {
78 if (stmt_) { 78 if (stmt_) {
79 AssertIOAllowed();
Scott Hess - ex-Googler 2012/06/26 16:39:47 In cases like this, I would prefer the assert move
79 sqlite3_finalize(stmt_); 80 sqlite3_finalize(stmt_);
80 stmt_ = NULL; 81 stmt_ = NULL;
81 } 82 }
82 connection_ = NULL; // The connection may be getting deleted. 83 connection_ = NULL; // The connection may be getting deleted.
83 } 84 }
84 85
85 Connection::Connection() 86 Connection::Connection()
86 : db_(NULL), 87 : db_(NULL),
87 page_size_(0), 88 page_size_(0),
88 cache_size_(0), 89 cache_size_(0),
89 exclusive_locking_(false), 90 exclusive_locking_(false),
90 transaction_nesting_(0), 91 transaction_nesting_(0),
91 needs_rollback_(false) { 92 needs_rollback_(false),
93 in_memory_(false) {
92 } 94 }
93 95
94 Connection::~Connection() { 96 Connection::~Connection() {
95 Close(); 97 Close();
96 } 98 }
97 99
98 bool Connection::Open(const FilePath& path) { 100 bool Connection::Open(const FilePath& path) {
99 #if defined(OS_WIN) 101 #if defined(OS_WIN)
100 return OpenInternal(WideToUTF8(path.value())); 102 return OpenInternal(WideToUTF8(path.value()));
101 #elif defined(OS_POSIX) 103 #elif defined(OS_POSIX)
102 return OpenInternal(path.value()); 104 return OpenInternal(path.value());
103 #endif 105 #endif
104 } 106 }
105 107
106 bool Connection::OpenInMemory() { 108 bool Connection::OpenInMemory() {
109 in_memory_ = true;
107 return OpenInternal(":memory:"); 110 return OpenInternal(":memory:");
108 } 111 }
109 112
110 void Connection::Close() { 113 void Connection::Close() {
111 // TODO(shess): Calling "PRAGMA journal_mode = DELETE" at this point 114 // TODO(shess): Calling "PRAGMA journal_mode = DELETE" at this point
112 // will delete the -journal file. For ChromiumOS or other more 115 // will delete the -journal file. For ChromiumOS or other more
113 // embedded systems, this is probably not appropriate, whereas on 116 // embedded systems, this is probably not appropriate, whereas on
114 // desktop it might make some sense. 117 // desktop it might make some sense.
115 118
116 // sqlite3_close() needs all prepared statements to be finalized. 119 // sqlite3_close() needs all prepared statements to be finalized.
117 // Release all cached statements, then assert that the client has 120 // Release all cached statements, then assert that the client has
118 // released all statements. 121 // released all statements.
119 statement_cache_.clear(); 122 statement_cache_.clear();
120 DCHECK(open_statements_.empty()); 123 DCHECK(open_statements_.empty());
121 124
122 // Additionally clear the prepared statements, because they contain 125 // Additionally clear the prepared statements, because they contain
123 // weak references to this connection. This case has come up when 126 // weak references to this connection. This case has come up when
124 // error-handling code is hit in production. 127 // error-handling code is hit in production.
125 ClearCache(); 128 ClearCache();
126 129
127 if (db_) { 130 if (db_) {
131 AssertIOAllowed();
128 // TODO(shess): Histogram for failure. 132 // TODO(shess): Histogram for failure.
129 sqlite3_close(db_); 133 sqlite3_close(db_);
130 db_ = NULL; 134 db_ = NULL;
131 } 135 }
132 } 136 }
133 137
134 void Connection::Preload() { 138 void Connection::Preload() {
135 if (!db_) { 139 if (!db_) {
136 DLOG(FATAL) << "Cannot preload null db"; 140 DLOG(FATAL) << "Cannot preload null db";
137 return; 141 return;
138 } 142 }
139 143
140 // A statement must be open for the preload command to work. If the meta 144 // A statement must be open for the preload command to work. If the meta
141 // table doesn't exist, it probably means this is a new database and there 145 // table doesn't exist, it probably means this is a new database and there
142 // is nothing to preload (so it's OK we do nothing). 146 // is nothing to preload (so it's OK we do nothing).
143 if (!DoesTableExist("meta")) 147 if (!DoesTableExist("meta"))
144 return; 148 return;
145 Statement dummy(GetUniqueStatement("SELECT * FROM meta")); 149 Statement dummy(GetUniqueStatement("SELECT * FROM meta"));
146 if (!dummy.Step()) 150 if (!dummy.Step())
147 return; 151 return;
148 152
149 #if !defined(USE_SYSTEM_SQLITE) 153 #if !defined(USE_SYSTEM_SQLITE)
154 AssertIOAllowed();
150 // This function is only defined in Chromium's version of sqlite. 155 // This function is only defined in Chromium's version of sqlite.
151 // Do not call it when using system sqlite. 156 // Do not call it when using system sqlite.
152 sqlite3_preload(db_); 157 sqlite3_preload(db_);
153 #endif 158 #endif
154 } 159 }
155 160
156 // Create an in-memory database with the existing database's page 161 // Create an in-memory database with the existing database's page
157 // size, then backup that database over the existing database. 162 // size, then backup that database over the existing database.
158 bool Connection::Raze() { 163 bool Connection::Raze() {
159 if (!db_) { 164 if (!db_) {
(...skipping 24 matching lines...) Expand all
184 // The page size doesn't take effect until a database has pages, and 189 // The page size doesn't take effect until a database has pages, and
185 // at this point the null database has none. Changing the schema 190 // at this point the null database has none. Changing the schema
186 // version will create the first page. This will not affect the 191 // version will create the first page. This will not affect the
187 // schema version in the resulting database, as SQLite's backup 192 // schema version in the resulting database, as SQLite's backup
188 // implementation propagates the schema version from the original 193 // implementation propagates the schema version from the original
189 // connection to the new version of the database, incremented by one 194 // connection to the new version of the database, incremented by one
190 // so that other readers see the schema change and act accordingly. 195 // so that other readers see the schema change and act accordingly.
191 if (!null_db.Execute("PRAGMA schema_version = 1")) 196 if (!null_db.Execute("PRAGMA schema_version = 1"))
192 return false; 197 return false;
193 198
199 AssertIOAllowed();
194 sqlite3_backup* backup = sqlite3_backup_init(db_, "main", 200 sqlite3_backup* backup = sqlite3_backup_init(db_, "main",
195 null_db.db_, "main"); 201 null_db.db_, "main");
196 if (!backup) { 202 if (!backup) {
197 DLOG(FATAL) << "Unable to start sqlite3_backup()."; 203 DLOG(FATAL) << "Unable to start sqlite3_backup().";
198 return false; 204 return false;
199 } 205 }
200 206
201 // -1 backs up the entire database. 207 // -1 backs up the entire database.
202 int rc = sqlite3_backup_step(backup, -1); 208 int rc = sqlite3_backup_step(backup, -1);
203 int pages = sqlite3_backup_pagecount(backup); 209 int pages = sqlite3_backup_pagecount(backup);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 return false; 293 return false;
288 } 294 }
289 295
290 Statement commit(GetCachedStatement(SQL_FROM_HERE, "COMMIT")); 296 Statement commit(GetCachedStatement(SQL_FROM_HERE, "COMMIT"));
291 return commit.Run(); 297 return commit.Run();
292 } 298 }
293 299
294 int Connection::ExecuteAndReturnErrorCode(const char* sql) { 300 int Connection::ExecuteAndReturnErrorCode(const char* sql) {
295 if (!db_) 301 if (!db_)
296 return false; 302 return false;
303 AssertIOAllowed();
297 return sqlite3_exec(db_, sql, NULL, NULL, NULL); 304 return sqlite3_exec(db_, sql, NULL, NULL, NULL);
298 } 305 }
299 306
300 bool Connection::Execute(const char* sql) { 307 bool Connection::Execute(const char* sql) {
301 int error = ExecuteAndReturnErrorCode(sql); 308 int error = ExecuteAndReturnErrorCode(sql);
302 // This needs to be a FATAL log because the error case of arriving here is 309 // This needs to be a FATAL log because the error case of arriving here is
303 // that there's a malformed SQL statement. This can arise in development if 310 // that there's a malformed SQL statement. This can arise in development if
304 // a change alters the schema but not all queries adjust. 311 // a change alters the schema but not all queries adjust.
305 if (error == SQLITE_ERROR) 312 if (error == SQLITE_ERROR)
306 DLOG(FATAL) << "SQL Error in " << sql << ", " << GetErrorMessage(); 313 DLOG(FATAL) << "SQL Error in " << sql << ", " << GetErrorMessage();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 if (statement->is_valid()) 345 if (statement->is_valid())
339 statement_cache_[id] = statement; // Only cache valid statements. 346 statement_cache_[id] = statement; // Only cache valid statements.
340 return statement; 347 return statement;
341 } 348 }
342 349
343 scoped_refptr<Connection::StatementRef> Connection::GetUniqueStatement( 350 scoped_refptr<Connection::StatementRef> Connection::GetUniqueStatement(
344 const char* sql) { 351 const char* sql) {
345 if (!db_) 352 if (!db_)
346 return new StatementRef(this, NULL); // Return inactive statement. 353 return new StatementRef(this, NULL); // Return inactive statement.
347 354
355 AssertIOAllowed();
348 sqlite3_stmt* stmt = NULL; 356 sqlite3_stmt* stmt = NULL;
349 if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK) { 357 if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK) {
350 // This is evidence of a syntax error in the incoming SQL. 358 // This is evidence of a syntax error in the incoming SQL.
351 DLOG(FATAL) << "SQL compile error " << GetErrorMessage(); 359 DLOG(FATAL) << "SQL compile error " << GetErrorMessage();
352 return new StatementRef(this, NULL); 360 return new StatementRef(this, NULL);
353 } 361 }
354 return new StatementRef(this, stmt); 362 return new StatementRef(this, stmt);
355 } 363 }
356 364
357 bool Connection::IsSQLValid(const char* sql) { 365 bool Connection::IsSQLValid(const char* sql) {
366 AssertIOAllowed();
358 sqlite3_stmt* stmt = NULL; 367 sqlite3_stmt* stmt = NULL;
359 if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK) 368 if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK)
360 return false; 369 return false;
361 370
362 sqlite3_finalize(stmt); 371 sqlite3_finalize(stmt);
363 return true; 372 return true;
364 } 373 }
365 374
366 bool Connection::DoesTableExist(const char* table_name) const { 375 bool Connection::DoesTableExist(const char* table_name) const {
367 return DoesTableOrIndexExist(table_name, "table"); 376 return DoesTableOrIndexExist(table_name, "table");
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 return "sql::Connection has no connection."; 448 return "sql::Connection has no connection.";
440 return sqlite3_errmsg(db_); 449 return sqlite3_errmsg(db_);
441 } 450 }
442 451
443 bool Connection::OpenInternal(const std::string& file_name) { 452 bool Connection::OpenInternal(const std::string& file_name) {
444 if (db_) { 453 if (db_) {
445 DLOG(FATAL) << "sql::Connection is already open."; 454 DLOG(FATAL) << "sql::Connection is already open.";
446 return false; 455 return false;
447 } 456 }
448 457
458 AssertIOAllowed();
449 int err = sqlite3_open(file_name.c_str(), &db_); 459 int err = sqlite3_open(file_name.c_str(), &db_);
450 if (err != SQLITE_OK) { 460 if (err != SQLITE_OK) {
451 OnSqliteError(err, NULL); 461 OnSqliteError(err, NULL);
452 Close(); 462 Close();
453 db_ = NULL; 463 db_ = NULL;
454 return false; 464 return false;
455 } 465 }
456 466
457 // Enable extended result codes to provide more color on I/O errors. 467 // Enable extended result codes to provide more color on I/O errors.
458 // Not having extended result codes is not a fatal problem, as 468 // Not having extended result codes is not a fatal problem, as
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 559
550 int Connection::OnSqliteError(int err, sql::Statement *stmt) { 560 int Connection::OnSqliteError(int err, sql::Statement *stmt) {
551 if (error_delegate_.get()) 561 if (error_delegate_.get())
552 return error_delegate_->OnError(err, this, stmt); 562 return error_delegate_->OnError(err, this, stmt);
553 // The default handling is to assert on debug and to ignore on release. 563 // The default handling is to assert on debug and to ignore on release.
554 DLOG(FATAL) << GetErrorMessage(); 564 DLOG(FATAL) << GetErrorMessage();
555 return err; 565 return err;
556 } 566 }
557 567
558 } // namespace sql 568 } // namespace sql
OLDNEW
« no previous file with comments | « sql/connection.h ('k') | sql/statement.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698