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

Side by Side Diff: sql/connection.cc

Issue 10824008: 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, 5 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 // Call to AssertIOAllowed() cannot go at the beginning of the function
80 // because Close() is called unconditionally from destructor to clean
81 // connection_. And if this is inactive statement this won't cause any
82 // disk access and destructor most probably will be called on thread
83 // not allowing disk access.
84 // TODO(paivanof@gmail.com): This should move to the beginning
85 // of the function. http://crbug.com/136655.
86 AssertIOAllowed();
79 sqlite3_finalize(stmt_); 87 sqlite3_finalize(stmt_);
80 stmt_ = NULL; 88 stmt_ = NULL;
81 } 89 }
82 connection_ = NULL; // The connection may be getting deleted. 90 connection_ = NULL; // The connection may be getting deleted.
83 } 91 }
84 92
85 Connection::Connection() 93 Connection::Connection()
86 : db_(NULL), 94 : db_(NULL),
87 page_size_(0), 95 page_size_(0),
88 cache_size_(0), 96 cache_size_(0),
89 exclusive_locking_(false), 97 exclusive_locking_(false),
90 transaction_nesting_(0), 98 transaction_nesting_(0),
91 needs_rollback_(false) { 99 needs_rollback_(false),
100 in_memory_(false) {
92 } 101 }
93 102
94 Connection::~Connection() { 103 Connection::~Connection() {
95 Close(); 104 Close();
96 } 105 }
97 106
98 bool Connection::Open(const FilePath& path) { 107 bool Connection::Open(const FilePath& path) {
99 #if defined(OS_WIN) 108 #if defined(OS_WIN)
100 return OpenInternal(WideToUTF8(path.value())); 109 return OpenInternal(WideToUTF8(path.value()));
101 #elif defined(OS_POSIX) 110 #elif defined(OS_POSIX)
102 return OpenInternal(path.value()); 111 return OpenInternal(path.value());
103 #endif 112 #endif
104 } 113 }
105 114
106 bool Connection::OpenInMemory() { 115 bool Connection::OpenInMemory() {
116 in_memory_ = true;
107 return OpenInternal(":memory:"); 117 return OpenInternal(":memory:");
108 } 118 }
109 119
110 void Connection::Close() { 120 void Connection::Close() {
111 // TODO(shess): Calling "PRAGMA journal_mode = DELETE" at this point 121 // TODO(shess): Calling "PRAGMA journal_mode = DELETE" at this point
112 // will delete the -journal file. For ChromiumOS or other more 122 // will delete the -journal file. For ChromiumOS or other more
113 // embedded systems, this is probably not appropriate, whereas on 123 // embedded systems, this is probably not appropriate, whereas on
114 // desktop it might make some sense. 124 // desktop it might make some sense.
115 125
116 // sqlite3_close() needs all prepared statements to be finalized. 126 // sqlite3_close() needs all prepared statements to be finalized.
117 // Release all cached statements, then assert that the client has 127 // Release all cached statements, then assert that the client has
118 // released all statements. 128 // released all statements.
119 statement_cache_.clear(); 129 statement_cache_.clear();
120 DCHECK(open_statements_.empty()); 130 DCHECK(open_statements_.empty());
121 131
122 // Additionally clear the prepared statements, because they contain 132 // Additionally clear the prepared statements, because they contain
123 // weak references to this connection. This case has come up when 133 // weak references to this connection. This case has come up when
124 // error-handling code is hit in production. 134 // error-handling code is hit in production.
125 ClearCache(); 135 ClearCache();
126 136
127 if (db_) { 137 if (db_) {
138 // Call to AssertIOAllowed() cannot go at the beginning of the function
139 // because Close() must be called from destructor to clean
140 // statement_cache_, it won't cause any disk access and it most probably
141 // will happen on thread not allowing disk access.
142 // TODO(paivanof@gmail.com): This should move to the beginning
143 // of the function. http://crbug.com/136655.
144 AssertIOAllowed();
128 // TODO(shess): Histogram for failure. 145 // TODO(shess): Histogram for failure.
129 sqlite3_close(db_); 146 sqlite3_close(db_);
130 db_ = NULL; 147 db_ = NULL;
131 } 148 }
132 } 149 }
133 150
134 void Connection::Preload() { 151 void Connection::Preload() {
152 AssertIOAllowed();
153
135 if (!db_) { 154 if (!db_) {
136 DLOG(FATAL) << "Cannot preload null db"; 155 DLOG(FATAL) << "Cannot preload null db";
137 return; 156 return;
138 } 157 }
139 158
140 // A statement must be open for the preload command to work. If the meta 159 // 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 160 // 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). 161 // is nothing to preload (so it's OK we do nothing).
143 if (!DoesTableExist("meta")) 162 if (!DoesTableExist("meta"))
144 return; 163 return;
145 Statement dummy(GetUniqueStatement("SELECT * FROM meta")); 164 Statement dummy(GetUniqueStatement("SELECT * FROM meta"));
146 if (!dummy.Step()) 165 if (!dummy.Step())
147 return; 166 return;
148 167
149 #if !defined(USE_SYSTEM_SQLITE) 168 #if !defined(USE_SYSTEM_SQLITE)
150 // This function is only defined in Chromium's version of sqlite. 169 // This function is only defined in Chromium's version of sqlite.
151 // Do not call it when using system sqlite. 170 // Do not call it when using system sqlite.
152 sqlite3_preload(db_); 171 sqlite3_preload(db_);
153 #endif 172 #endif
154 } 173 }
155 174
156 // Create an in-memory database with the existing database's page 175 // Create an in-memory database with the existing database's page
157 // size, then backup that database over the existing database. 176 // size, then backup that database over the existing database.
158 bool Connection::Raze() { 177 bool Connection::Raze() {
178 AssertIOAllowed();
179
159 if (!db_) { 180 if (!db_) {
160 DLOG(FATAL) << "Cannot raze null db"; 181 DLOG(FATAL) << "Cannot raze null db";
161 return false; 182 return false;
162 } 183 }
163 184
164 if (transaction_nesting_ > 0) { 185 if (transaction_nesting_ > 0) {
165 DLOG(FATAL) << "Cannot raze within a transaction"; 186 DLOG(FATAL) << "Cannot raze within a transaction";
166 return false; 187 return false;
167 } 188 }
168 189
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 if (needs_rollback_) { 306 if (needs_rollback_) {
286 DoRollback(); 307 DoRollback();
287 return false; 308 return false;
288 } 309 }
289 310
290 Statement commit(GetCachedStatement(SQL_FROM_HERE, "COMMIT")); 311 Statement commit(GetCachedStatement(SQL_FROM_HERE, "COMMIT"));
291 return commit.Run(); 312 return commit.Run();
292 } 313 }
293 314
294 int Connection::ExecuteAndReturnErrorCode(const char* sql) { 315 int Connection::ExecuteAndReturnErrorCode(const char* sql) {
316 AssertIOAllowed();
295 if (!db_) 317 if (!db_)
296 return false; 318 return false;
297 return sqlite3_exec(db_, sql, NULL, NULL, NULL); 319 return sqlite3_exec(db_, sql, NULL, NULL, NULL);
298 } 320 }
299 321
300 bool Connection::Execute(const char* sql) { 322 bool Connection::Execute(const char* sql) {
301 int error = ExecuteAndReturnErrorCode(sql); 323 int error = ExecuteAndReturnErrorCode(sql);
302 // This needs to be a FATAL log because the error case of arriving here is 324 // 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 325 // that there's a malformed SQL statement. This can arise in development if
304 // a change alters the schema but not all queries adjust. 326 // a change alters the schema but not all queries adjust.
(...skipping 30 matching lines...) Expand all
335 } 357 }
336 358
337 scoped_refptr<StatementRef> statement = GetUniqueStatement(sql); 359 scoped_refptr<StatementRef> statement = GetUniqueStatement(sql);
338 if (statement->is_valid()) 360 if (statement->is_valid())
339 statement_cache_[id] = statement; // Only cache valid statements. 361 statement_cache_[id] = statement; // Only cache valid statements.
340 return statement; 362 return statement;
341 } 363 }
342 364
343 scoped_refptr<Connection::StatementRef> Connection::GetUniqueStatement( 365 scoped_refptr<Connection::StatementRef> Connection::GetUniqueStatement(
344 const char* sql) { 366 const char* sql) {
367 AssertIOAllowed();
368
345 if (!db_) 369 if (!db_)
346 return new StatementRef(this, NULL); // Return inactive statement. 370 return new StatementRef(this, NULL); // Return inactive statement.
347 371
348 sqlite3_stmt* stmt = NULL; 372 sqlite3_stmt* stmt = NULL;
349 if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK) { 373 if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK) {
350 // This is evidence of a syntax error in the incoming SQL. 374 // This is evidence of a syntax error in the incoming SQL.
351 DLOG(FATAL) << "SQL compile error " << GetErrorMessage(); 375 DLOG(FATAL) << "SQL compile error " << GetErrorMessage();
352 return new StatementRef(this, NULL); 376 return new StatementRef(this, NULL);
353 } 377 }
354 return new StatementRef(this, stmt); 378 return new StatementRef(this, stmt);
355 } 379 }
356 380
357 bool Connection::IsSQLValid(const char* sql) { 381 bool Connection::IsSQLValid(const char* sql) {
382 AssertIOAllowed();
358 sqlite3_stmt* stmt = NULL; 383 sqlite3_stmt* stmt = NULL;
359 if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK) 384 if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK)
360 return false; 385 return false;
361 386
362 sqlite3_finalize(stmt); 387 sqlite3_finalize(stmt);
363 return true; 388 return true;
364 } 389 }
365 390
366 bool Connection::DoesTableExist(const char* table_name) const { 391 bool Connection::DoesTableExist(const char* table_name) const {
367 return DoesTableOrIndexExist(table_name, "table"); 392 return DoesTableOrIndexExist(table_name, "table");
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 return err; 459 return err;
435 } 460 }
436 461
437 const char* Connection::GetErrorMessage() const { 462 const char* Connection::GetErrorMessage() const {
438 if (!db_) 463 if (!db_)
439 return "sql::Connection has no connection."; 464 return "sql::Connection has no connection.";
440 return sqlite3_errmsg(db_); 465 return sqlite3_errmsg(db_);
441 } 466 }
442 467
443 bool Connection::OpenInternal(const std::string& file_name) { 468 bool Connection::OpenInternal(const std::string& file_name) {
469 AssertIOAllowed();
470
444 if (db_) { 471 if (db_) {
445 DLOG(FATAL) << "sql::Connection is already open."; 472 DLOG(FATAL) << "sql::Connection is already open.";
446 return false; 473 return false;
447 } 474 }
448 475
449 int err = sqlite3_open(file_name.c_str(), &db_); 476 int err = sqlite3_open(file_name.c_str(), &db_);
450 if (err != SQLITE_OK) { 477 if (err != SQLITE_OK) {
451 OnSqliteError(err, NULL); 478 OnSqliteError(err, NULL);
452 Close(); 479 Close();
453 db_ = NULL; 480 db_ = NULL;
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 576
550 int Connection::OnSqliteError(int err, sql::Statement *stmt) { 577 int Connection::OnSqliteError(int err, sql::Statement *stmt) {
551 if (error_delegate_.get()) 578 if (error_delegate_.get())
552 return error_delegate_->OnError(err, this, stmt); 579 return error_delegate_->OnError(err, this, stmt);
553 // The default handling is to assert on debug and to ignore on release. 580 // The default handling is to assert on debug and to ignore on release.
554 DLOG(FATAL) << GetErrorMessage(); 581 DLOG(FATAL) << GetErrorMessage();
555 return err; 582 return err;
556 } 583 }
557 584
558 } // namespace sql 585 } // 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