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

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: 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
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 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() 77 Connection::StatementRef::StatementRef()
78 : connection_(NULL), 78 : connection_(NULL),
79 stmt_(NULL) { 79 stmt_(NULL),
80 was_valid_(false) {
80 } 81 }
81 82
82 Connection::StatementRef::StatementRef(sqlite3_stmt* stmt) 83 Connection::StatementRef::StatementRef(sqlite3_stmt* stmt)
83 : connection_(NULL), 84 : connection_(NULL),
84 stmt_(stmt) { 85 stmt_(stmt),
86 was_valid_(stmt != NULL) {
85 } 87 }
86 88
87 Connection::StatementRef::StatementRef(Connection* connection, 89 Connection::StatementRef::StatementRef(Connection* connection,
88 sqlite3_stmt* stmt) 90 sqlite3_stmt* stmt)
89 : connection_(connection), 91 : connection_(connection),
90 stmt_(stmt) { 92 stmt_(stmt),
93 was_valid_(stmt != NULL) {
91 connection_->StatementRefCreated(this); 94 connection_->StatementRefCreated(this);
92 } 95 }
93 96
94 Connection::StatementRef::~StatementRef() { 97 Connection::StatementRef::~StatementRef() {
95 if (connection_) 98 if (connection_)
96 connection_->StatementRefDeleted(this); 99 connection_->StatementRefDeleted(this);
97 Close(); 100 Close(false);
98 } 101 }
99 102
100 void Connection::StatementRef::Close() { 103 void Connection::StatementRef::Close(bool forced) {
101 if (stmt_) { 104 if (stmt_) {
102 // Call to AssertIOAllowed() cannot go at the beginning of the function 105 // Call to AssertIOAllowed() cannot go at the beginning of the function
103 // because Close() is called unconditionally from destructor to clean 106 // because Close() is called unconditionally from destructor to clean
104 // connection_. And if this is inactive statement this won't cause any 107 // connection_. And if this is inactive statement this won't cause any
105 // disk access and destructor most probably will be called on thread 108 // disk access and destructor most probably will be called on thread
106 // not allowing disk access. 109 // not allowing disk access.
107 // TODO(paivanof@gmail.com): This should move to the beginning 110 // TODO(paivanof@gmail.com): This should move to the beginning
108 // of the function. http://crbug.com/136655. 111 // of the function. http://crbug.com/136655.
109 AssertIOAllowed(); 112 AssertIOAllowed();
110 sqlite3_finalize(stmt_); 113 sqlite3_finalize(stmt_);
111 stmt_ = NULL; 114 stmt_ = NULL;
112 } 115 }
113 connection_ = NULL; // The connection may be getting deleted. 116 connection_ = NULL; // The connection may be getting deleted.
117
118 // Forced close is expected to happen from a statement error
119 // handler, in that case maintain the sense of |was_valid_| which
pkotwicz 2013/01/31 19:22:00 Nit: Use a ',' instead of a '.'
Scott Hess - ex-Googler 2013/02/05 01:20:25 I'll assume you meant it the other way around, or
120 // previously held for this ref.
121 was_valid_ = was_valid_ && forced;
114 } 122 }
115 123
116 Connection::Connection() 124 Connection::Connection()
117 : db_(NULL), 125 : db_(NULL),
118 page_size_(0), 126 page_size_(0),
119 cache_size_(0), 127 cache_size_(0),
120 exclusive_locking_(false), 128 exclusive_locking_(false),
121 transaction_nesting_(0), 129 transaction_nesting_(0),
122 needs_rollback_(false), 130 needs_rollback_(false),
123 in_memory_(false), 131 in_memory_(false),
(...skipping 10 matching lines...) Expand all
134 #elif defined(OS_POSIX) 142 #elif defined(OS_POSIX)
135 return OpenInternal(path.value()); 143 return OpenInternal(path.value());
136 #endif 144 #endif
137 } 145 }
138 146
139 bool Connection::OpenInMemory() { 147 bool Connection::OpenInMemory() {
140 in_memory_ = true; 148 in_memory_ = true;
141 return OpenInternal(":memory:"); 149 return OpenInternal(":memory:");
142 } 150 }
143 151
144 void Connection::Close() { 152 void Connection::CloseInternal(bool forced) {
145 // TODO(shess): Calling "PRAGMA journal_mode = DELETE" at this point 153 // TODO(shess): Calling "PRAGMA journal_mode = DELETE" at this point
146 // will delete the -journal file. For ChromiumOS or other more 154 // will delete the -journal file. For ChromiumOS or other more
147 // embedded systems, this is probably not appropriate, whereas on 155 // embedded systems, this is probably not appropriate, whereas on
148 // desktop it might make some sense. 156 // desktop it might make some sense.
149 157
150 // sqlite3_close() needs all prepared statements to be finalized. 158 // sqlite3_close() needs all prepared statements to be finalized.
151 // Release all cached statements, then assert that the client has 159
152 // released all statements. 160 // Release cached statements.
153 statement_cache_.clear(); 161 statement_cache_.clear();
154 DCHECK(open_statements_.empty());
155 162
156 // Additionally clear the prepared statements, because they contain 163 // With cached statements released, in-use statements will remain.
157 // weak references to this connection. This case has come up when 164 // Closing the database while statements are in use is an API
158 // error-handling code is hit in production. 165 // violation, except for forced close (which happens from within a
159 ClearCache(); 166 // statement's error handler).
167 DCHECK(forced || open_statements_.empty());
168
169 // Deactivate any outstanding statements so sqlite3_close() works.
170 for (StatementRefSet::iterator i = open_statements_.begin();
171 i != open_statements_.end(); ++i)
172 (*i)->Close(forced);
173 open_statements_.clear();
160 174
161 if (db_) { 175 if (db_) {
162 // Call to AssertIOAllowed() cannot go at the beginning of the function 176 // Call to AssertIOAllowed() cannot go at the beginning of the function
163 // because Close() must be called from destructor to clean 177 // because Close() must be called from destructor to clean
164 // statement_cache_, it won't cause any disk access and it most probably 178 // statement_cache_, it won't cause any disk access and it most probably
165 // will happen on thread not allowing disk access. 179 // will happen on thread not allowing disk access.
166 // TODO(paivanof@gmail.com): This should move to the beginning 180 // TODO(paivanof@gmail.com): This should move to the beginning
167 // of the function. http://crbug.com/136655. 181 // of the function. http://crbug.com/136655.
168 AssertIOAllowed(); 182 AssertIOAllowed();
169 // TODO(shess): Histogram for failure. 183 // TODO(shess): Histogram for failure.
170 sqlite3_close(db_); 184 sqlite3_close(db_);
171 db_ = NULL; 185 db_ = NULL;
172 } 186 }
173 } 187 }
174 188
189 void Connection::Close() {
190 // Database was already closed via RazeAndClose(), ignore.
191 if (poisoned_)
192 return;
193
194 CloseInternal(false);
195 }
196
175 void Connection::Preload() { 197 void Connection::Preload() {
176 AssertIOAllowed(); 198 AssertIOAllowed();
177 199
178 if (!db_) { 200 if (!db_) {
179 DLOG(FATAL) << "Cannot preload null db"; 201 DLOG_IF(FATAL, !poisoned_) << "Cannot preload null db";
180 return; 202 return;
181 } 203 }
182 204
183 // A statement must be open for the preload command to work. If the meta 205 // 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 206 // 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). 207 // is nothing to preload (so it's OK we do nothing).
186 if (!DoesTableExist("meta")) 208 if (!DoesTableExist("meta"))
187 return; 209 return;
188 Statement dummy(GetUniqueStatement("SELECT * FROM meta")); 210 Statement dummy(GetUniqueStatement("SELECT * FROM meta"));
189 if (!dummy.Step()) 211 if (!dummy.Step())
190 return; 212 return;
191 213
192 #if !defined(USE_SYSTEM_SQLITE) 214 #if !defined(USE_SYSTEM_SQLITE)
193 // This function is only defined in Chromium's version of sqlite. 215 // This function is only defined in Chromium's version of sqlite.
194 // Do not call it when using system sqlite. 216 // Do not call it when using system sqlite.
195 sqlite3_preload(db_); 217 sqlite3_preload(db_);
196 #endif 218 #endif
197 } 219 }
198 220
199 // Create an in-memory database with the existing database's page 221 // Create an in-memory database with the existing database's page
200 // size, then backup that database over the existing database. 222 // size, then backup that database over the existing database.
201 bool Connection::Raze() { 223 bool Connection::Raze() {
202 AssertIOAllowed(); 224 AssertIOAllowed();
203 225
204 if (!db_) { 226 if (!db_) {
205 DLOG(FATAL) << "Cannot raze null db"; 227 DLOG_IF(FATAL, !poisoned_) << "Cannot raze null db";
206 return false; 228 return false;
207 } 229 }
208 230
209 if (transaction_nesting_ > 0) { 231 if (transaction_nesting_ > 0) {
210 DLOG(FATAL) << "Cannot raze within a transaction"; 232 DLOG(FATAL) << "Cannot raze within a transaction";
211 return false; 233 return false;
212 } 234 }
213 235
214 sql::Connection null_db; 236 sql::Connection null_db;
215 if (!null_db.OpenInMemory()) { 237 if (!null_db.OpenInMemory()) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 307
286 // Exactly one page should have been backed up. If this breaks, 308 // Exactly one page should have been backed up. If this breaks,
287 // check this function to make sure assumptions aren't being broken. 309 // check this function to make sure assumptions aren't being broken.
288 DCHECK_EQ(pages, 1); 310 DCHECK_EQ(pages, 1);
289 311
290 return true; 312 return true;
291 } 313 }
292 314
293 bool Connection::RazeWithTimout(base::TimeDelta timeout) { 315 bool Connection::RazeWithTimout(base::TimeDelta timeout) {
294 if (!db_) { 316 if (!db_) {
295 DLOG(FATAL) << "Cannot raze null db"; 317 DLOG_IF(FATAL, !poisoned_) << "Cannot raze null db";
296 return false; 318 return false;
297 } 319 }
298 320
299 ScopedBusyTimeout busy_timeout(db_); 321 ScopedBusyTimeout busy_timeout(db_);
300 busy_timeout.SetTimeout(timeout); 322 busy_timeout.SetTimeout(timeout);
301 return Raze(); 323 return Raze();
302 } 324 }
303 325
326 bool Connection::RazeAndClose() {
327 if (!db_) {
328 DLOG_IF(FATAL, !poisoned_) << "Cannot raze null db";
329 return false;
330 }
331
332 // Raze() cannot run in a transaction.
333 while (transaction_nesting_) {
pkotwicz 2013/01/31 19:22:00 Nit: The braces are not necessary
Scott Hess - ex-Googler 2013/02/05 01:20:25 I'll plead the personal-preference exemption in th
334 RollbackTransaction();
335 }
336
337 bool result = Raze();
338
339 CloseInternal(true);
340
341 // Mark the database so that future API calls fail appropriately,
342 // but don't DCHECK (because after calling this function they are
343 // expected to fail).
344 poisoned_ = true;
345
346 return result;
347 }
348
304 bool Connection::BeginTransaction() { 349 bool Connection::BeginTransaction() {
305 if (needs_rollback_) { 350 if (needs_rollback_) {
306 DCHECK_GT(transaction_nesting_, 0); 351 DCHECK_GT(transaction_nesting_, 0);
307 352
308 // When we're going to rollback, fail on this begin and don't actually 353 // When we're going to rollback, fail on this begin and don't actually
309 // mark us as entering the nested transaction. 354 // mark us as entering the nested transaction.
310 return false; 355 return false;
311 } 356 }
312 357
313 bool success = true; 358 bool success = true;
314 if (!transaction_nesting_) { 359 if (!transaction_nesting_) {
315 needs_rollback_ = false; 360 needs_rollback_ = false;
316 361
317 Statement begin(GetCachedStatement(SQL_FROM_HERE, "BEGIN TRANSACTION")); 362 Statement begin(GetCachedStatement(SQL_FROM_HERE, "BEGIN TRANSACTION"));
318 if (!begin.Run()) 363 if (!begin.Run())
319 return false; 364 return false;
320 } 365 }
321 transaction_nesting_++; 366 transaction_nesting_++;
322 return success; 367 return success;
323 } 368 }
324 369
325 void Connection::RollbackTransaction() { 370 void Connection::RollbackTransaction() {
326 if (!transaction_nesting_) { 371 if (!transaction_nesting_) {
327 DLOG(FATAL) << "Rolling back a nonexistent transaction"; 372 DLOG_IF(FATAL, !poisoned_) << "Rolling back a nonexistent transaction";
328 return; 373 return;
329 } 374 }
330 375
331 transaction_nesting_--; 376 transaction_nesting_--;
332 377
333 if (transaction_nesting_ > 0) { 378 if (transaction_nesting_ > 0) {
334 // Mark the outermost transaction as needing rollback. 379 // Mark the outermost transaction as needing rollback.
335 needs_rollback_ = true; 380 needs_rollback_ = true;
336 return; 381 return;
337 } 382 }
338 383
339 DoRollback(); 384 DoRollback();
340 } 385 }
341 386
342 bool Connection::CommitTransaction() { 387 bool Connection::CommitTransaction() {
343 if (!transaction_nesting_) { 388 if (!transaction_nesting_) {
344 DLOG(FATAL) << "Rolling back a nonexistent transaction"; 389 DLOG_IF(FATAL, !poisoned_) << "Rolling back a nonexistent transaction";
345 return false; 390 return false;
346 } 391 }
347 transaction_nesting_--; 392 transaction_nesting_--;
348 393
349 if (transaction_nesting_ > 0) { 394 if (transaction_nesting_ > 0) {
350 // Mark any nested transactions as failing after we've already got one. 395 // Mark any nested transactions as failing after we've already got one.
351 return !needs_rollback_; 396 return !needs_rollback_;
352 } 397 }
353 398
354 if (needs_rollback_) { 399 if (needs_rollback_) {
355 DoRollback(); 400 DoRollback();
356 return false; 401 return false;
357 } 402 }
358 403
359 Statement commit(GetCachedStatement(SQL_FROM_HERE, "COMMIT")); 404 Statement commit(GetCachedStatement(SQL_FROM_HERE, "COMMIT"));
360 return commit.Run(); 405 return commit.Run();
361 } 406 }
362 407
363 int Connection::ExecuteAndReturnErrorCode(const char* sql) { 408 int Connection::ExecuteAndReturnErrorCode(const char* sql) {
364 AssertIOAllowed(); 409 AssertIOAllowed();
365 if (!db_) 410 if (!db_)
366 return false; 411 return false;
pkotwicz 2013/01/31 19:22:00 false == SQLITE_OK ?
Scott Hess - ex-Googler 2013/02/05 01:20:25 GOOD CATCH! I hope that nobody is currently hitti
367 return sqlite3_exec(db_, sql, NULL, NULL, NULL); 412 return sqlite3_exec(db_, sql, NULL, NULL, NULL);
368 } 413 }
369 414
370 bool Connection::Execute(const char* sql) { 415 bool Connection::Execute(const char* sql) {
371 int error = ExecuteAndReturnErrorCode(sql); 416 int error = ExecuteAndReturnErrorCode(sql);
372 if (error != SQLITE_OK) 417 if (error != SQLITE_OK)
373 error = OnSqliteError(error, NULL); 418 error = OnSqliteError(error, NULL);
374 419
375 // This needs to be a FATAL log because the error case of arriving here is 420 // 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 421 // that there's a malformed SQL statement. This can arise in development if
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 if (rc != SQLITE_OK) { 488 if (rc != SQLITE_OK) {
444 // This is evidence of a syntax error in the incoming SQL. 489 // This is evidence of a syntax error in the incoming SQL.
445 DLOG(FATAL) << "SQL compile error " << GetErrorMessage(); 490 DLOG(FATAL) << "SQL compile error " << GetErrorMessage();
446 return new StatementRef(); 491 return new StatementRef();
447 } 492 }
448 return new StatementRef(stmt); 493 return new StatementRef(stmt);
449 } 494 }
450 495
451 bool Connection::IsSQLValid(const char* sql) { 496 bool Connection::IsSQLValid(const char* sql) {
452 AssertIOAllowed(); 497 AssertIOAllowed();
498 if (!db_) {
499 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db";
500 return false;
501 }
502
453 sqlite3_stmt* stmt = NULL; 503 sqlite3_stmt* stmt = NULL;
454 if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK) 504 if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK)
455 return false; 505 return false;
456 506
457 sqlite3_finalize(stmt); 507 sqlite3_finalize(stmt);
458 return true; 508 return true;
459 } 509 }
460 510
461 bool Connection::DoesTableExist(const char* table_name) const { 511 bool Connection::DoesTableExist(const char* table_name) const {
462 return DoesTableOrIndexExist(table_name, "table"); 512 return DoesTableOrIndexExist(table_name, "table");
463 } 513 }
464 514
465 bool Connection::DoesIndexExist(const char* index_name) const { 515 bool Connection::DoesIndexExist(const char* index_name) const {
466 return DoesTableOrIndexExist(index_name, "index"); 516 return DoesTableOrIndexExist(index_name, "index");
467 } 517 }
468 518
469 bool Connection::DoesTableOrIndexExist( 519 bool Connection::DoesTableOrIndexExist(
pkotwicz 2013/01/31 19:22:00 Comment: Calling this method after the connection
Scott Hess - ex-Googler 2013/02/05 01:20:25 I don't think so - it should fail comprehensively
470 const char* name, const char* type) const { 520 const char* name, const char* type) const {
471 const char* kSql = "SELECT name FROM sqlite_master WHERE type=? AND name=?"; 521 const char* kSql = "SELECT name FROM sqlite_master WHERE type=? AND name=?";
472 Statement statement(GetUntrackedStatement(kSql)); 522 Statement statement(GetUntrackedStatement(kSql));
473 statement.BindString(0, type); 523 statement.BindString(0, type);
474 statement.BindString(1, name); 524 statement.BindString(1, name);
475 525
476 return statement.Step(); // Table exists if any row was returned. 526 return statement.Step(); // Table exists if any row was returned.
477 } 527 }
478 528
479 bool Connection::DoesColumnExist(const char* table_name, 529 bool Connection::DoesColumnExist(const char* table_name,
480 const char* column_name) const { 530 const char* column_name) const {
481 std::string sql("PRAGMA TABLE_INFO("); 531 std::string sql("PRAGMA TABLE_INFO(");
482 sql.append(table_name); 532 sql.append(table_name);
483 sql.append(")"); 533 sql.append(")");
484 534
485 Statement statement(GetUntrackedStatement(sql.c_str())); 535 Statement statement(GetUntrackedStatement(sql.c_str()));
486 while (statement.Step()) { 536 while (statement.Step()) {
487 if (!statement.ColumnString(1).compare(column_name)) 537 if (!statement.ColumnString(1).compare(column_name))
488 return true; 538 return true;
489 } 539 }
490 return false; 540 return false;
491 } 541 }
492 542
493 int64 Connection::GetLastInsertRowId() const { 543 int64 Connection::GetLastInsertRowId() const {
494 if (!db_) { 544 if (!db_) {
495 DLOG(FATAL) << "Illegal use of connection without a db"; 545 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db";
496 return 0; 546 return 0;
497 } 547 }
498 return sqlite3_last_insert_rowid(db_); 548 return sqlite3_last_insert_rowid(db_);
499 } 549 }
500 550
501 int Connection::GetLastChangeCount() const { 551 int Connection::GetLastChangeCount() const {
502 if (!db_) { 552 if (!db_) {
503 DLOG(FATAL) << "Illegal use of connection without a db"; 553 DLOG_IF(FATAL, !poisoned_) << "Illegal use of connection without a db";
504 return 0; 554 return 0;
505 } 555 }
506 return sqlite3_changes(db_); 556 return sqlite3_changes(db_);
507 } 557 }
508 558
509 int Connection::GetErrorCode() const { 559 int Connection::GetErrorCode() const {
510 if (!db_) 560 if (!db_)
511 return SQLITE_ERROR; 561 return SQLITE_ERROR;
512 return sqlite3_errcode(db_); 562 return sqlite3_errcode(db_);
513 } 563 }
(...skipping 11 matching lines...) Expand all
525 575
526 const char* Connection::GetErrorMessage() const { 576 const char* Connection::GetErrorMessage() const {
527 if (!db_) 577 if (!db_)
528 return "sql::Connection has no connection."; 578 return "sql::Connection has no connection.";
529 return sqlite3_errmsg(db_); 579 return sqlite3_errmsg(db_);
530 } 580 }
531 581
532 bool Connection::OpenInternal(const std::string& file_name) { 582 bool Connection::OpenInternal(const std::string& file_name) {
533 AssertIOAllowed(); 583 AssertIOAllowed();
534 584
585 // Reset, in case connection is re-used. This usage may not be an
586 // intentional API contract, but tests do it.
587 poisoned_ = false;
588
535 if (db_) { 589 if (db_) {
536 DLOG(FATAL) << "sql::Connection is already open."; 590 DLOG(FATAL) << "sql::Connection is already open.";
537 return false; 591 return false;
538 } 592 }
539 593
540 int err = sqlite3_open(file_name.c_str(), &db_); 594 int err = sqlite3_open(file_name.c_str(), &db_);
541 if (err != SQLITE_OK) { 595 if (err != SQLITE_OK) {
542 // Histogram failures specific to initial open for debugging 596 // Histogram failures specific to initial open for debugging
543 // purposes. 597 // purposes.
544 UMA_HISTOGRAM_ENUMERATION("Sqlite.OpenFailure", err & 0xff, 50); 598 UMA_HISTOGRAM_ENUMERATION("Sqlite.OpenFailure", err & 0xff, 50);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 } 688 }
635 689
636 void Connection::StatementRefDeleted(StatementRef* ref) { 690 void Connection::StatementRefDeleted(StatementRef* ref) {
637 StatementRefSet::iterator i = open_statements_.find(ref); 691 StatementRefSet::iterator i = open_statements_.find(ref);
638 if (i == open_statements_.end()) 692 if (i == open_statements_.end())
639 DLOG(FATAL) << "Could not find statement"; 693 DLOG(FATAL) << "Could not find statement";
640 else 694 else
641 open_statements_.erase(i); 695 open_statements_.erase(i);
642 } 696 }
643 697
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) { 698 int Connection::OnSqliteError(int err, sql::Statement *stmt) {
656 // Strip extended error codes. 699 // Strip extended error codes.
657 int base_err = err&0xff; 700 int base_err = err&0xff;
658 701
659 static size_t kSqliteErrorMax = 50; 702 static size_t kSqliteErrorMax = 50;
660 UMA_HISTOGRAM_ENUMERATION("Sqlite.Error", base_err, kSqliteErrorMax); 703 UMA_HISTOGRAM_ENUMERATION("Sqlite.Error", base_err, kSqliteErrorMax);
661 if (!error_histogram_name_.empty()) { 704 if (!error_histogram_name_.empty()) {
662 // TODO(shess): The histogram macros create a bit of static 705 // TODO(shess): The histogram macros create a bit of static
663 // storage for caching the histogram object. Since SQLite is 706 // storage for caching the histogram object. Since SQLite is
664 // being used for I/O, generally without error, this code 707 // being used for I/O, generally without error, this code
(...skipping 15 matching lines...) Expand all
680 723
681 if (error_delegate_.get()) 724 if (error_delegate_.get())
682 return error_delegate_->OnError(err, this, stmt); 725 return error_delegate_->OnError(err, this, stmt);
683 726
684 // The default handling is to assert on debug and to ignore on release. 727 // The default handling is to assert on debug and to ignore on release.
685 DLOG(FATAL) << GetErrorMessage(); 728 DLOG(FATAL) << GetErrorMessage();
686 return err; 729 return err;
687 } 730 }
688 731
689 } // namespace sql 732 } // namespace sql
OLDNEW
« sql/connection.h ('K') | « sql/connection.h ('k') | sql/connection_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698