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