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

Side by Side Diff: sql/connection.cc

Issue 12096073: Implement sql::Connection::RazeAndClose(). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Disable DEATH test on android and ios. Created 7 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « sql/connection.h ('k') | sql/connection_unittest.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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 67
68 bool StatementID::operator<(const StatementID& other) const { 68 bool StatementID::operator<(const StatementID& other) const {
69 if (number_ != other.number_) 69 if (number_ != other.number_)
70 return number_ < other.number_; 70 return number_ < other.number_;
71 return strcmp(str_, other.str_) < 0; 71 return strcmp(str_, other.str_) < 0;
72 } 72 }
73 73
74 ErrorDelegate::~ErrorDelegate() { 74 ErrorDelegate::~ErrorDelegate() {
75 } 75 }
76 76
77 Connection::StatementRef::StatementRef()
78 : connection_(NULL),
79 stmt_(NULL) {
80 }
81
82 Connection::StatementRef::StatementRef(sqlite3_stmt* stmt)
83 : connection_(NULL),
84 stmt_(stmt) {
85 }
86
87 Connection::StatementRef::StatementRef(Connection* connection, 77 Connection::StatementRef::StatementRef(Connection* connection,
88 sqlite3_stmt* stmt) 78 sqlite3_stmt* stmt,
79 bool was_valid)
89 : connection_(connection), 80 : connection_(connection),
90 stmt_(stmt) { 81 stmt_(stmt),
91 connection_->StatementRefCreated(this); 82 was_valid_(was_valid) {
83 if (connection)
84 connection_->StatementRefCreated(this);
92 } 85 }
93 86
94 Connection::StatementRef::~StatementRef() { 87 Connection::StatementRef::~StatementRef() {
95 if (connection_) 88 if (connection_)
96 connection_->StatementRefDeleted(this); 89 connection_->StatementRefDeleted(this);
97 Close(); 90 Close(false);
98 } 91 }
99 92
100 void Connection::StatementRef::Close() { 93 void Connection::StatementRef::Close(bool forced) {
101 if (stmt_) { 94 if (stmt_) {
102 // Call to AssertIOAllowed() cannot go at the beginning of the function 95 // Call to AssertIOAllowed() cannot go at the beginning of the function
103 // because Close() is called unconditionally from destructor to clean 96 // because Close() is called unconditionally from destructor to clean
104 // connection_. And if this is inactive statement this won't cause any 97 // connection_. And if this is inactive statement this won't cause any
105 // disk access and destructor most probably will be called on thread 98 // disk access and destructor most probably will be called on thread
106 // not allowing disk access. 99 // not allowing disk access.
107 // TODO(paivanof@gmail.com): This should move to the beginning 100 // TODO(paivanof@gmail.com): This should move to the beginning
108 // of the function. http://crbug.com/136655. 101 // of the function. http://crbug.com/136655.
109 AssertIOAllowed(); 102 AssertIOAllowed();
110 sqlite3_finalize(stmt_); 103 sqlite3_finalize(stmt_);
111 stmt_ = NULL; 104 stmt_ = NULL;
112 } 105 }
113 connection_ = NULL; // The connection may be getting deleted. 106 connection_ = NULL; // The connection may be getting deleted.
107
108 // Forced close is expected to happen from a statement error
109 // handler. In that case maintain the sense of |was_valid_| which
110 // previously held for this ref.
111 was_valid_ = was_valid_ && forced;
114 } 112 }
115 113
116 Connection::Connection() 114 Connection::Connection()
117 : db_(NULL), 115 : db_(NULL),
118 page_size_(0), 116 page_size_(0),
119 cache_size_(0), 117 cache_size_(0),
120 exclusive_locking_(false), 118 exclusive_locking_(false),
121 transaction_nesting_(0), 119 transaction_nesting_(0),
122 needs_rollback_(false), 120 needs_rollback_(false),
123 in_memory_(false), 121 in_memory_(false),
122 poisoned_(false),
124 error_delegate_(NULL) { 123 error_delegate_(NULL) {
125 } 124 }
126 125
127 Connection::~Connection() { 126 Connection::~Connection() {
128 Close(); 127 Close();
129 } 128 }
130 129
131 bool Connection::Open(const base::FilePath& path) { 130 bool Connection::Open(const base::FilePath& path) {
132 #if defined(OS_WIN) 131 #if defined(OS_WIN)
133 return OpenInternal(WideToUTF8(path.value())); 132 return OpenInternal(WideToUTF8(path.value()));
134 #elif defined(OS_POSIX) 133 #elif defined(OS_POSIX)
135 return OpenInternal(path.value()); 134 return OpenInternal(path.value());
136 #endif 135 #endif
137 } 136 }
138 137
139 bool Connection::OpenInMemory() { 138 bool Connection::OpenInMemory() {
140 in_memory_ = true; 139 in_memory_ = true;
141 return OpenInternal(":memory:"); 140 return OpenInternal(":memory:");
142 } 141 }
143 142
144 void Connection::Close() { 143 void Connection::CloseInternal(bool forced) {
145 // TODO(shess): Calling "PRAGMA journal_mode = DELETE" at this point 144 // TODO(shess): Calling "PRAGMA journal_mode = DELETE" at this point
146 // will delete the -journal file. For ChromiumOS or other more 145 // will delete the -journal file. For ChromiumOS or other more
147 // embedded systems, this is probably not appropriate, whereas on 146 // embedded systems, this is probably not appropriate, whereas on
148 // desktop it might make some sense. 147 // desktop it might make some sense.
149 148
150 // sqlite3_close() needs all prepared statements to be finalized. 149 // sqlite3_close() needs all prepared statements to be finalized.
151 // Release all cached statements, then assert that the client has 150
152 // released all statements. 151 // Release cached statements.
153 statement_cache_.clear(); 152 statement_cache_.clear();
154 DCHECK(open_statements_.empty());
155 153
156 // Additionally clear the prepared statements, because they contain 154 // With cached statements released, in-use statements will remain.
157 // weak references to this connection. This case has come up when 155 // Closing the database while statements are in use is an API
158 // error-handling code is hit in production. 156 // violation, except for forced close (which happens from within a
159 ClearCache(); 157 // statement's error handler).
158 DCHECK(forced || open_statements_.empty());
159
160 // Deactivate any outstanding statements so sqlite3_close() works.
161 for (StatementRefSet::iterator i = open_statements_.begin();
162 i != open_statements_.end(); ++i)
163 (*i)->Close(forced);
164 open_statements_.clear();
160 165
161 if (db_) { 166 if (db_) {
162 // Call to AssertIOAllowed() cannot go at the beginning of the function 167 // Call to AssertIOAllowed() cannot go at the beginning of the function
163 // because Close() must be called from destructor to clean 168 // because Close() must be called from destructor to clean
164 // statement_cache_, it won't cause any disk access and it most probably 169 // statement_cache_, it won't cause any disk access and it most probably
165 // will happen on thread not allowing disk access. 170 // will happen on thread not allowing disk access.
166 // TODO(paivanof@gmail.com): This should move to the beginning 171 // TODO(paivanof@gmail.com): This should move to the beginning
167 // of the function. http://crbug.com/136655. 172 // of the function. http://crbug.com/136655.
168 AssertIOAllowed(); 173 AssertIOAllowed();
169 // TODO(shess): Histogram for failure. 174 // TODO(shess): Histogram for failure.
170 sqlite3_close(db_); 175 sqlite3_close(db_);
171 db_ = NULL; 176 db_ = NULL;
172 } 177 }
173 } 178 }
174 179
180 void Connection::Close() {
181 // If the database was already closed by RazeAndClose(), then no
182 // need to close again. Clear the |poisoned_| bit so that incorrect
183 // API calls are caught.
184 if (poisoned_) {
185 poisoned_ = false;
186 return;
187 }
188
189 CloseInternal(false);
190 }
191
175 void Connection::Preload() { 192 void Connection::Preload() {
176 AssertIOAllowed(); 193 AssertIOAllowed();
177 194
178 if (!db_) { 195 if (!db_) {
179 DLOG(FATAL) << "Cannot preload null db"; 196 DLOG_IF(FATAL, !poisoned_) << "Cannot preload null db";
180 return; 197 return;
181 } 198 }
182 199
183 // A statement must be open for the preload command to work. If the meta 200 // A statement must be open for the preload command to work. If the meta
184 // table doesn't exist, it probably means this is a new database and there 201 // table doesn't exist, it probably means this is a new database and there
185 // is nothing to preload (so it's OK we do nothing). 202 // is nothing to preload (so it's OK we do nothing).
186 if (!DoesTableExist("meta")) 203 if (!DoesTableExist("meta"))
187 return; 204 return;
188 Statement dummy(GetUniqueStatement("SELECT * FROM meta")); 205 Statement dummy(GetUniqueStatement("SELECT * FROM meta"));
189 if (!dummy.Step()) 206 if (!dummy.Step())
190 return; 207 return;
191 208
192 #if !defined(USE_SYSTEM_SQLITE) 209 #if !defined(USE_SYSTEM_SQLITE)
193 // This function is only defined in Chromium's version of sqlite. 210 // This function is only defined in Chromium's version of sqlite.
194 // Do not call it when using system sqlite. 211 // Do not call it when using system sqlite.
195 sqlite3_preload(db_); 212 sqlite3_preload(db_);
196 #endif 213 #endif
197 } 214 }
198 215
199 // Create an in-memory database with the existing database's page 216 // Create an in-memory database with the existing database's page
200 // size, then backup that database over the existing database. 217 // size, then backup that database over the existing database.
201 bool Connection::Raze() { 218 bool Connection::Raze() {
202 AssertIOAllowed(); 219 AssertIOAllowed();
203 220
204 if (!db_) { 221 if (!db_) {
205 DLOG(FATAL) << "Cannot raze null db"; 222 DLOG_IF(FATAL, !poisoned_) << "Cannot raze null db";
206 return false; 223 return false;
207 } 224 }
208 225
209 if (transaction_nesting_ > 0) { 226 if (transaction_nesting_ > 0) {
210 DLOG(FATAL) << "Cannot raze within a transaction"; 227 DLOG(FATAL) << "Cannot raze within a transaction";
211 return false; 228 return false;
212 } 229 }
213 230
214 sql::Connection null_db; 231 sql::Connection null_db;
215 if (!null_db.OpenInMemory()) { 232 if (!null_db.OpenInMemory()) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 302
286 // Exactly one page should have been backed up. If this breaks, 303 // Exactly one page should have been backed up. If this breaks,
287 // check this function to make sure assumptions aren't being broken. 304 // check this function to make sure assumptions aren't being broken.
288 DCHECK_EQ(pages, 1); 305 DCHECK_EQ(pages, 1);
289 306
290 return true; 307 return true;
291 } 308 }
292 309
293 bool Connection::RazeWithTimout(base::TimeDelta timeout) { 310 bool Connection::RazeWithTimout(base::TimeDelta timeout) {
294 if (!db_) { 311 if (!db_) {
295 DLOG(FATAL) << "Cannot raze null db"; 312 DLOG_IF(FATAL, !poisoned_) << "Cannot raze null db";
296 return false; 313 return false;
297 } 314 }
298 315
299 ScopedBusyTimeout busy_timeout(db_); 316 ScopedBusyTimeout busy_timeout(db_);
300 busy_timeout.SetTimeout(timeout); 317 busy_timeout.SetTimeout(timeout);
301 return Raze(); 318 return Raze();
302 } 319 }
303 320
321 bool Connection::RazeAndClose() {
322 if (!db_) {
323 DLOG_IF(FATAL, !poisoned_) << "Cannot raze null db";
324 return false;
325 }
326
327 // Raze() cannot run in a transaction.
328 while (transaction_nesting_) {
329 RollbackTransaction();
330 }
331
332 bool result = Raze();
333
334 CloseInternal(true);
335
336 // Mark the database so that future API calls fail appropriately,
337 // but don't DCHECK (because after calling this function they are
338 // expected to fail).
339 poisoned_ = true;
340
341 return result;
342 }
343
304 bool Connection::BeginTransaction() { 344 bool Connection::BeginTransaction() {
305 if (needs_rollback_) { 345 if (needs_rollback_) {
306 DCHECK_GT(transaction_nesting_, 0); 346 DCHECK_GT(transaction_nesting_, 0);
307 347
308 // When we're going to rollback, fail on this begin and don't actually 348 // When we're going to rollback, fail on this begin and don't actually
309 // mark us as entering the nested transaction. 349 // mark us as entering the nested transaction.
310 return false; 350 return false;
311 } 351 }
312 352
313 bool success = true; 353 bool success = true;
314 if (!transaction_nesting_) { 354 if (!transaction_nesting_) {
315 needs_rollback_ = false; 355 needs_rollback_ = false;
316 356
317 Statement begin(GetCachedStatement(SQL_FROM_HERE, "BEGIN TRANSACTION")); 357 Statement begin(GetCachedStatement(SQL_FROM_HERE, "BEGIN TRANSACTION"));
318 if (!begin.Run()) 358 if (!begin.Run())
319 return false; 359 return false;
320 } 360 }
321 transaction_nesting_++; 361 transaction_nesting_++;
322 return success; 362 return success;
323 } 363 }
324 364
325 void Connection::RollbackTransaction() { 365 void Connection::RollbackTransaction() {
326 if (!transaction_nesting_) { 366 if (!transaction_nesting_) {
327 DLOG(FATAL) << "Rolling back a nonexistent transaction"; 367 DLOG_IF(FATAL, !poisoned_) << "Rolling back a nonexistent transaction";
328 return; 368 return;
329 } 369 }
330 370
331 transaction_nesting_--; 371 transaction_nesting_--;
332 372
333 if (transaction_nesting_ > 0) { 373 if (transaction_nesting_ > 0) {
334 // Mark the outermost transaction as needing rollback. 374 // Mark the outermost transaction as needing rollback.
335 needs_rollback_ = true; 375 needs_rollback_ = true;
336 return; 376 return;
337 } 377 }
338 378
339 DoRollback(); 379 DoRollback();
340 } 380 }
341 381
342 bool Connection::CommitTransaction() { 382 bool Connection::CommitTransaction() {
343 if (!transaction_nesting_) { 383 if (!transaction_nesting_) {
344 DLOG(FATAL) << "Rolling back a nonexistent transaction"; 384 DLOG_IF(FATAL, !poisoned_) << "Rolling back a nonexistent transaction";
345 return false; 385 return false;
346 } 386 }
347 transaction_nesting_--; 387 transaction_nesting_--;
348 388
349 if (transaction_nesting_ > 0) { 389 if (transaction_nesting_ > 0) {
350 // Mark any nested transactions as failing after we've already got one. 390 // Mark any nested transactions as failing after we've already got one.
351 return !needs_rollback_; 391 return !needs_rollback_;
352 } 392 }
353 393
354 if (needs_rollback_) { 394 if (needs_rollback_) {
355 DoRollback(); 395 DoRollback();
356 return false; 396 return false;
357 } 397 }
358 398
359 Statement commit(GetCachedStatement(SQL_FROM_HERE, "COMMIT")); 399 Statement commit(GetCachedStatement(SQL_FROM_HERE, "COMMIT"));
360 return commit.Run(); 400 return commit.Run();
361 } 401 }
362 402
363 int Connection::ExecuteAndReturnErrorCode(const char* sql) { 403 int Connection::ExecuteAndReturnErrorCode(const char* sql) {
364 AssertIOAllowed(); 404 AssertIOAllowed();
365 if (!db_) 405 if (!db_) {
366 return false; 406 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db";
407 return SQLITE_ERROR;
408 }
367 return sqlite3_exec(db_, sql, NULL, NULL, NULL); 409 return sqlite3_exec(db_, sql, NULL, NULL, NULL);
368 } 410 }
369 411
370 bool Connection::Execute(const char* sql) { 412 bool Connection::Execute(const char* sql) {
413 if (!db_) {
414 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db";
415 return false;
416 }
417
371 int error = ExecuteAndReturnErrorCode(sql); 418 int error = ExecuteAndReturnErrorCode(sql);
372 if (error != SQLITE_OK) 419 if (error != SQLITE_OK)
373 error = OnSqliteError(error, NULL); 420 error = OnSqliteError(error, NULL);
374 421
375 // This needs to be a FATAL log because the error case of arriving here is 422 // This needs to be a FATAL log because the error case of arriving here is
376 // that there's a malformed SQL statement. This can arise in development if 423 // that there's a malformed SQL statement. This can arise in development if
377 // a change alters the schema but not all queries adjust. 424 // a change alters the schema but not all queries adjust.
378 if (error == SQLITE_ERROR) 425 if (error == SQLITE_ERROR)
379 DLOG(FATAL) << "SQL Error in " << sql << ", " << GetErrorMessage(); 426 DLOG(FATAL) << "SQL Error in " << sql << ", " << GetErrorMessage();
380 return error == SQLITE_OK; 427 return error == SQLITE_OK;
381 } 428 }
382 429
383 bool Connection::ExecuteWithTimeout(const char* sql, base::TimeDelta timeout) { 430 bool Connection::ExecuteWithTimeout(const char* sql, base::TimeDelta timeout) {
384 if (!db_) 431 if (!db_) {
432 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db";
385 return false; 433 return false;
434 }
386 435
387 ScopedBusyTimeout busy_timeout(db_); 436 ScopedBusyTimeout busy_timeout(db_);
388 busy_timeout.SetTimeout(timeout); 437 busy_timeout.SetTimeout(timeout);
389 return Execute(sql); 438 return Execute(sql);
390 } 439 }
391 440
392 bool Connection::HasCachedStatement(const StatementID& id) const { 441 bool Connection::HasCachedStatement(const StatementID& id) const {
393 return statement_cache_.find(id) != statement_cache_.end(); 442 return statement_cache_.find(id) != statement_cache_.end();
394 } 443 }
395 444
(...skipping 14 matching lines...) Expand all
410 scoped_refptr<StatementRef> statement = GetUniqueStatement(sql); 459 scoped_refptr<StatementRef> statement = GetUniqueStatement(sql);
411 if (statement->is_valid()) 460 if (statement->is_valid())
412 statement_cache_[id] = statement; // Only cache valid statements. 461 statement_cache_[id] = statement; // Only cache valid statements.
413 return statement; 462 return statement;
414 } 463 }
415 464
416 scoped_refptr<Connection::StatementRef> Connection::GetUniqueStatement( 465 scoped_refptr<Connection::StatementRef> Connection::GetUniqueStatement(
417 const char* sql) { 466 const char* sql) {
418 AssertIOAllowed(); 467 AssertIOAllowed();
419 468
469 // Return inactive statement.
420 if (!db_) 470 if (!db_)
421 return new StatementRef(); // Return inactive statement. 471 return new StatementRef(NULL, NULL, poisoned_);
422 472
423 sqlite3_stmt* stmt = NULL; 473 sqlite3_stmt* stmt = NULL;
424 int rc = sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL); 474 int rc = sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL);
425 if (rc != SQLITE_OK) { 475 if (rc != SQLITE_OK) {
426 // This is evidence of a syntax error in the incoming SQL. 476 // This is evidence of a syntax error in the incoming SQL.
427 DLOG(FATAL) << "SQL compile error " << GetErrorMessage(); 477 DLOG(FATAL) << "SQL compile error " << GetErrorMessage();
428 478
429 // It could also be database corruption. 479 // It could also be database corruption.
430 OnSqliteError(rc, NULL); 480 OnSqliteError(rc, NULL);
431 return new StatementRef(); 481 return new StatementRef(NULL, NULL, false);
432 } 482 }
433 return new StatementRef(this, stmt); 483 return new StatementRef(this, stmt, true);
434 } 484 }
435 485
436 scoped_refptr<Connection::StatementRef> Connection::GetUntrackedStatement( 486 scoped_refptr<Connection::StatementRef> Connection::GetUntrackedStatement(
437 const char* sql) const { 487 const char* sql) const {
488 // Return inactive statement.
438 if (!db_) 489 if (!db_)
439 return new StatementRef(); // Return inactive statement. 490 return new StatementRef(NULL, NULL, poisoned_);
440 491
441 sqlite3_stmt* stmt = NULL; 492 sqlite3_stmt* stmt = NULL;
442 int rc = sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL); 493 int rc = sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL);
443 if (rc != SQLITE_OK) { 494 if (rc != SQLITE_OK) {
444 // This is evidence of a syntax error in the incoming SQL. 495 // This is evidence of a syntax error in the incoming SQL.
445 DLOG(FATAL) << "SQL compile error " << GetErrorMessage(); 496 DLOG(FATAL) << "SQL compile error " << GetErrorMessage();
446 return new StatementRef(); 497 return new StatementRef(NULL, NULL, false);
447 } 498 }
448 return new StatementRef(stmt); 499 return new StatementRef(NULL, stmt, true);
449 } 500 }
450 501
451 bool Connection::IsSQLValid(const char* sql) { 502 bool Connection::IsSQLValid(const char* sql) {
452 AssertIOAllowed(); 503 AssertIOAllowed();
504 if (!db_) {
505 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db";
506 return false;
507 }
508
453 sqlite3_stmt* stmt = NULL; 509 sqlite3_stmt* stmt = NULL;
454 if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK) 510 if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK)
455 return false; 511 return false;
456 512
457 sqlite3_finalize(stmt); 513 sqlite3_finalize(stmt);
458 return true; 514 return true;
459 } 515 }
460 516
461 bool Connection::DoesTableExist(const char* table_name) const { 517 bool Connection::DoesTableExist(const char* table_name) const {
462 return DoesTableOrIndexExist(table_name, "table"); 518 return DoesTableOrIndexExist(table_name, "table");
(...skipping 22 matching lines...) Expand all
485 Statement statement(GetUntrackedStatement(sql.c_str())); 541 Statement statement(GetUntrackedStatement(sql.c_str()));
486 while (statement.Step()) { 542 while (statement.Step()) {
487 if (!statement.ColumnString(1).compare(column_name)) 543 if (!statement.ColumnString(1).compare(column_name))
488 return true; 544 return true;
489 } 545 }
490 return false; 546 return false;
491 } 547 }
492 548
493 int64 Connection::GetLastInsertRowId() const { 549 int64 Connection::GetLastInsertRowId() const {
494 if (!db_) { 550 if (!db_) {
495 DLOG(FATAL) << "Illegal use of connection without a db"; 551 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db";
496 return 0; 552 return 0;
497 } 553 }
498 return sqlite3_last_insert_rowid(db_); 554 return sqlite3_last_insert_rowid(db_);
499 } 555 }
500 556
501 int Connection::GetLastChangeCount() const { 557 int Connection::GetLastChangeCount() const {
502 if (!db_) { 558 if (!db_) {
503 DLOG(FATAL) << "Illegal use of connection without a db"; 559 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db";
504 return 0; 560 return 0;
505 } 561 }
506 return sqlite3_changes(db_); 562 return sqlite3_changes(db_);
507 } 563 }
508 564
509 int Connection::GetErrorCode() const { 565 int Connection::GetErrorCode() const {
510 if (!db_) 566 if (!db_)
511 return SQLITE_ERROR; 567 return SQLITE_ERROR;
512 return sqlite3_errcode(db_); 568 return sqlite3_errcode(db_);
513 } 569 }
(...skipping 16 matching lines...) Expand all
530 } 586 }
531 587
532 bool Connection::OpenInternal(const std::string& file_name) { 588 bool Connection::OpenInternal(const std::string& file_name) {
533 AssertIOAllowed(); 589 AssertIOAllowed();
534 590
535 if (db_) { 591 if (db_) {
536 DLOG(FATAL) << "sql::Connection is already open."; 592 DLOG(FATAL) << "sql::Connection is already open.";
537 return false; 593 return false;
538 } 594 }
539 595
596 // If |poisoned_| is set, it means an error handler called
597 // RazeAndClose(). Until regular Close() is called, the caller
598 // should be treating the database as open, but is_open() currently
599 // only considers the sqlite3 handle's state.
600 // TODO(shess): Revise is_open() to consider poisoned_, and review
601 // to see if any non-testing code even depends on it.
602 DLOG_IF(FATAL, poisoned_) << "sql::Connection is already open.";
603
540 int err = sqlite3_open(file_name.c_str(), &db_); 604 int err = sqlite3_open(file_name.c_str(), &db_);
541 if (err != SQLITE_OK) { 605 if (err != SQLITE_OK) {
542 // Histogram failures specific to initial open for debugging 606 // Histogram failures specific to initial open for debugging
543 // purposes. 607 // purposes.
544 UMA_HISTOGRAM_ENUMERATION("Sqlite.OpenFailure", err & 0xff, 50); 608 UMA_HISTOGRAM_ENUMERATION("Sqlite.OpenFailure", err & 0xff, 50);
545 609
546 OnSqliteError(err, NULL); 610 OnSqliteError(err, NULL);
547 Close(); 611 Close();
548 db_ = NULL; 612 db_ = NULL;
549 return false; 613 return false;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 } 698 }
635 699
636 void Connection::StatementRefDeleted(StatementRef* ref) { 700 void Connection::StatementRefDeleted(StatementRef* ref) {
637 StatementRefSet::iterator i = open_statements_.find(ref); 701 StatementRefSet::iterator i = open_statements_.find(ref);
638 if (i == open_statements_.end()) 702 if (i == open_statements_.end())
639 DLOG(FATAL) << "Could not find statement"; 703 DLOG(FATAL) << "Could not find statement";
640 else 704 else
641 open_statements_.erase(i); 705 open_statements_.erase(i);
642 } 706 }
643 707
644 void Connection::ClearCache() {
645 statement_cache_.clear();
646
647 // The cache clear will get most statements. There may be still be references
648 // to some statements that are held by others (including one-shot statements).
649 // This will deactivate them so they can't be used again.
650 for (StatementRefSet::iterator i = open_statements_.begin();
651 i != open_statements_.end(); ++i)
652 (*i)->Close();
653 }
654
655 int Connection::OnSqliteError(int err, sql::Statement *stmt) { 708 int Connection::OnSqliteError(int err, sql::Statement *stmt) {
656 // Strip extended error codes. 709 // Strip extended error codes.
657 int base_err = err&0xff; 710 int base_err = err&0xff;
658 711
659 static size_t kSqliteErrorMax = 50; 712 static size_t kSqliteErrorMax = 50;
660 UMA_HISTOGRAM_ENUMERATION("Sqlite.Error", base_err, kSqliteErrorMax); 713 UMA_HISTOGRAM_ENUMERATION("Sqlite.Error", base_err, kSqliteErrorMax);
661 if (!error_histogram_name_.empty()) { 714 if (!error_histogram_name_.empty()) {
662 // TODO(shess): The histogram macros create a bit of static 715 // TODO(shess): The histogram macros create a bit of static
663 // storage for caching the histogram object. Since SQLite is 716 // storage for caching the histogram object. Since SQLite is
664 // being used for I/O, generally without error, this code 717 // being used for I/O, generally without error, this code
(...skipping 15 matching lines...) Expand all
680 733
681 if (error_delegate_.get()) 734 if (error_delegate_.get())
682 return error_delegate_->OnError(err, this, stmt); 735 return error_delegate_->OnError(err, this, stmt);
683 736
684 // The default handling is to assert on debug and to ignore on release. 737 // The default handling is to assert on debug and to ignore on release.
685 DLOG(FATAL) << GetErrorMessage(); 738 DLOG(FATAL) << GetErrorMessage();
686 return err; 739 return err;
687 } 740 }
688 741
689 } // namespace sql 742 } // namespace sql
OLDNEW
« no previous file with comments | « sql/connection.h ('k') | sql/connection_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698