| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 634 } | 690 } |
| 635 | 691 |
| 636 void Connection::StatementRefDeleted(StatementRef* ref) { | 692 void Connection::StatementRefDeleted(StatementRef* ref) { |
| 637 StatementRefSet::iterator i = open_statements_.find(ref); | 693 StatementRefSet::iterator i = open_statements_.find(ref); |
| 638 if (i == open_statements_.end()) | 694 if (i == open_statements_.end()) |
| 639 DLOG(FATAL) << "Could not find statement"; | 695 DLOG(FATAL) << "Could not find statement"; |
| 640 else | 696 else |
| 641 open_statements_.erase(i); | 697 open_statements_.erase(i); |
| 642 } | 698 } |
| 643 | 699 |
| 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) { | 700 int Connection::OnSqliteError(int err, sql::Statement *stmt) { |
| 656 // Strip extended error codes. | 701 // Strip extended error codes. |
| 657 int base_err = err&0xff; | 702 int base_err = err&0xff; |
| 658 | 703 |
| 659 static size_t kSqliteErrorMax = 50; | 704 static size_t kSqliteErrorMax = 50; |
| 660 UMA_HISTOGRAM_ENUMERATION("Sqlite.Error", base_err, kSqliteErrorMax); | 705 UMA_HISTOGRAM_ENUMERATION("Sqlite.Error", base_err, kSqliteErrorMax); |
| 661 if (!error_histogram_name_.empty()) { | 706 if (!error_histogram_name_.empty()) { |
| 662 // TODO(shess): The histogram macros create a bit of static | 707 // TODO(shess): The histogram macros create a bit of static |
| 663 // storage for caching the histogram object. Since SQLite is | 708 // storage for caching the histogram object. Since SQLite is |
| 664 // being used for I/O, generally without error, this code | 709 // being used for I/O, generally without error, this code |
| (...skipping 15 matching lines...) Expand all Loading... |
| 680 | 725 |
| 681 if (error_delegate_.get()) | 726 if (error_delegate_.get()) |
| 682 return error_delegate_->OnError(err, this, stmt); | 727 return error_delegate_->OnError(err, this, stmt); |
| 683 | 728 |
| 684 // The default handling is to assert on debug and to ignore on release. | 729 // The default handling is to assert on debug and to ignore on release. |
| 685 DLOG(FATAL) << GetErrorMessage(); | 730 DLOG(FATAL) << GetErrorMessage(); |
| 686 return err; | 731 return err; |
| 687 } | 732 } |
| 688 | 733 |
| 689 } // namespace sql | 734 } // namespace sql |
| OLD | NEW |