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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 connection_->StatementRefCreated(this); | 68 connection_->StatementRefCreated(this); |
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 AssertIOAllowed(); |
78 if (stmt_) { | 79 if (stmt_) { |
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() { |
| 114 AssertIOAllowed(); |
| 115 |
111 // TODO(shess): Calling "PRAGMA journal_mode = DELETE" at this point | 116 // TODO(shess): Calling "PRAGMA journal_mode = DELETE" at this point |
112 // will delete the -journal file. For ChromiumOS or other more | 117 // will delete the -journal file. For ChromiumOS or other more |
113 // embedded systems, this is probably not appropriate, whereas on | 118 // embedded systems, this is probably not appropriate, whereas on |
114 // desktop it might make some sense. | 119 // desktop it might make some sense. |
115 | 120 |
116 // sqlite3_close() needs all prepared statements to be finalized. | 121 // sqlite3_close() needs all prepared statements to be finalized. |
117 // Release all cached statements, then assert that the client has | 122 // Release all cached statements, then assert that the client has |
118 // released all statements. | 123 // released all statements. |
119 statement_cache_.clear(); | 124 statement_cache_.clear(); |
120 DCHECK(open_statements_.empty()); | 125 DCHECK(open_statements_.empty()); |
121 | 126 |
122 // Additionally clear the prepared statements, because they contain | 127 // Additionally clear the prepared statements, because they contain |
123 // weak references to this connection. This case has come up when | 128 // weak references to this connection. This case has come up when |
124 // error-handling code is hit in production. | 129 // error-handling code is hit in production. |
125 ClearCache(); | 130 ClearCache(); |
126 | 131 |
127 if (db_) { | 132 if (db_) { |
128 // TODO(shess): Histogram for failure. | 133 // TODO(shess): Histogram for failure. |
129 sqlite3_close(db_); | 134 sqlite3_close(db_); |
130 db_ = NULL; | 135 db_ = NULL; |
131 } | 136 } |
132 } | 137 } |
133 | 138 |
134 void Connection::Preload() { | 139 void Connection::Preload() { |
| 140 AssertIOAllowed(); |
| 141 |
135 if (!db_) { | 142 if (!db_) { |
136 DLOG(FATAL) << "Cannot preload null db"; | 143 DLOG(FATAL) << "Cannot preload null db"; |
137 return; | 144 return; |
138 } | 145 } |
139 | 146 |
140 // A statement must be open for the preload command to work. If the meta | 147 // 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 | 148 // 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). | 149 // is nothing to preload (so it's OK we do nothing). |
143 if (!DoesTableExist("meta")) | 150 if (!DoesTableExist("meta")) |
144 return; | 151 return; |
145 Statement dummy(GetUniqueStatement("SELECT * FROM meta")); | 152 Statement dummy(GetUniqueStatement("SELECT * FROM meta")); |
146 if (!dummy.Step()) | 153 if (!dummy.Step()) |
147 return; | 154 return; |
148 | 155 |
149 #if !defined(USE_SYSTEM_SQLITE) | 156 #if !defined(USE_SYSTEM_SQLITE) |
150 // This function is only defined in Chromium's version of sqlite. | 157 // This function is only defined in Chromium's version of sqlite. |
151 // Do not call it when using system sqlite. | 158 // Do not call it when using system sqlite. |
152 sqlite3_preload(db_); | 159 sqlite3_preload(db_); |
153 #endif | 160 #endif |
154 } | 161 } |
155 | 162 |
156 // Create an in-memory database with the existing database's page | 163 // Create an in-memory database with the existing database's page |
157 // size, then backup that database over the existing database. | 164 // size, then backup that database over the existing database. |
158 bool Connection::Raze() { | 165 bool Connection::Raze() { |
| 166 AssertIOAllowed(); |
| 167 |
159 if (!db_) { | 168 if (!db_) { |
160 DLOG(FATAL) << "Cannot raze null db"; | 169 DLOG(FATAL) << "Cannot raze null db"; |
161 return false; | 170 return false; |
162 } | 171 } |
163 | 172 |
164 if (transaction_nesting_ > 0) { | 173 if (transaction_nesting_ > 0) { |
165 DLOG(FATAL) << "Cannot raze within a transaction"; | 174 DLOG(FATAL) << "Cannot raze within a transaction"; |
166 return false; | 175 return false; |
167 } | 176 } |
168 | 177 |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 if (needs_rollback_) { | 294 if (needs_rollback_) { |
286 DoRollback(); | 295 DoRollback(); |
287 return false; | 296 return false; |
288 } | 297 } |
289 | 298 |
290 Statement commit(GetCachedStatement(SQL_FROM_HERE, "COMMIT")); | 299 Statement commit(GetCachedStatement(SQL_FROM_HERE, "COMMIT")); |
291 return commit.Run(); | 300 return commit.Run(); |
292 } | 301 } |
293 | 302 |
294 int Connection::ExecuteAndReturnErrorCode(const char* sql) { | 303 int Connection::ExecuteAndReturnErrorCode(const char* sql) { |
| 304 AssertIOAllowed(); |
295 if (!db_) | 305 if (!db_) |
296 return false; | 306 return false; |
297 return sqlite3_exec(db_, sql, NULL, NULL, NULL); | 307 return sqlite3_exec(db_, sql, NULL, NULL, NULL); |
298 } | 308 } |
299 | 309 |
300 bool Connection::Execute(const char* sql) { | 310 bool Connection::Execute(const char* sql) { |
301 int error = ExecuteAndReturnErrorCode(sql); | 311 int error = ExecuteAndReturnErrorCode(sql); |
302 // This needs to be a FATAL log because the error case of arriving here is | 312 // 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 | 313 // that there's a malformed SQL statement. This can arise in development if |
304 // a change alters the schema but not all queries adjust. | 314 // a change alters the schema but not all queries adjust. |
(...skipping 30 matching lines...) Expand all Loading... |
335 } | 345 } |
336 | 346 |
337 scoped_refptr<StatementRef> statement = GetUniqueStatement(sql); | 347 scoped_refptr<StatementRef> statement = GetUniqueStatement(sql); |
338 if (statement->is_valid()) | 348 if (statement->is_valid()) |
339 statement_cache_[id] = statement; // Only cache valid statements. | 349 statement_cache_[id] = statement; // Only cache valid statements. |
340 return statement; | 350 return statement; |
341 } | 351 } |
342 | 352 |
343 scoped_refptr<Connection::StatementRef> Connection::GetUniqueStatement( | 353 scoped_refptr<Connection::StatementRef> Connection::GetUniqueStatement( |
344 const char* sql) { | 354 const char* sql) { |
| 355 AssertIOAllowed(); |
| 356 |
345 if (!db_) | 357 if (!db_) |
346 return new StatementRef(this, NULL); // Return inactive statement. | 358 return new StatementRef(this, NULL); // Return inactive statement. |
347 | 359 |
348 sqlite3_stmt* stmt = NULL; | 360 sqlite3_stmt* stmt = NULL; |
349 if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK) { | 361 if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK) { |
350 // This is evidence of a syntax error in the incoming SQL. | 362 // This is evidence of a syntax error in the incoming SQL. |
351 DLOG(FATAL) << "SQL compile error " << GetErrorMessage(); | 363 DLOG(FATAL) << "SQL compile error " << GetErrorMessage(); |
352 return new StatementRef(this, NULL); | 364 return new StatementRef(this, NULL); |
353 } | 365 } |
354 return new StatementRef(this, stmt); | 366 return new StatementRef(this, stmt); |
355 } | 367 } |
356 | 368 |
357 bool Connection::IsSQLValid(const char* sql) { | 369 bool Connection::IsSQLValid(const char* sql) { |
| 370 AssertIOAllowed(); |
358 sqlite3_stmt* stmt = NULL; | 371 sqlite3_stmt* stmt = NULL; |
359 if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK) | 372 if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK) |
360 return false; | 373 return false; |
361 | 374 |
362 sqlite3_finalize(stmt); | 375 sqlite3_finalize(stmt); |
363 return true; | 376 return true; |
364 } | 377 } |
365 | 378 |
366 bool Connection::DoesTableExist(const char* table_name) const { | 379 bool Connection::DoesTableExist(const char* table_name) const { |
367 return DoesTableOrIndexExist(table_name, "table"); | 380 return DoesTableOrIndexExist(table_name, "table"); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 return err; | 447 return err; |
435 } | 448 } |
436 | 449 |
437 const char* Connection::GetErrorMessage() const { | 450 const char* Connection::GetErrorMessage() const { |
438 if (!db_) | 451 if (!db_) |
439 return "sql::Connection has no connection."; | 452 return "sql::Connection has no connection."; |
440 return sqlite3_errmsg(db_); | 453 return sqlite3_errmsg(db_); |
441 } | 454 } |
442 | 455 |
443 bool Connection::OpenInternal(const std::string& file_name) { | 456 bool Connection::OpenInternal(const std::string& file_name) { |
| 457 AssertIOAllowed(); |
| 458 |
444 if (db_) { | 459 if (db_) { |
445 DLOG(FATAL) << "sql::Connection is already open."; | 460 DLOG(FATAL) << "sql::Connection is already open."; |
446 return false; | 461 return false; |
447 } | 462 } |
448 | 463 |
449 int err = sqlite3_open(file_name.c_str(), &db_); | 464 int err = sqlite3_open(file_name.c_str(), &db_); |
450 if (err != SQLITE_OK) { | 465 if (err != SQLITE_OK) { |
451 OnSqliteError(err, NULL); | 466 OnSqliteError(err, NULL); |
452 Close(); | 467 Close(); |
453 db_ = NULL; | 468 db_ = NULL; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 | 564 |
550 int Connection::OnSqliteError(int err, sql::Statement *stmt) { | 565 int Connection::OnSqliteError(int err, sql::Statement *stmt) { |
551 if (error_delegate_.get()) | 566 if (error_delegate_.get()) |
552 return error_delegate_->OnError(err, this, stmt); | 567 return error_delegate_->OnError(err, this, stmt); |
553 // The default handling is to assert on debug and to ignore on release. | 568 // The default handling is to assert on debug and to ignore on release. |
554 DLOG(FATAL) << GetErrorMessage(); | 569 DLOG(FATAL) << GetErrorMessage(); |
555 return err; | 570 return err; |
556 } | 571 } |
557 | 572 |
558 } // namespace sql | 573 } // namespace sql |
OLD | NEW |