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 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
161 if (!dummy.Step()) | 161 if (!dummy.Step()) |
162 return; | 162 return; |
163 | 163 |
164 #if !defined(USE_SYSTEM_SQLITE) | 164 #if !defined(USE_SYSTEM_SQLITE) |
165 // This function is only defined in Chromium's version of sqlite. | 165 // This function is only defined in Chromium's version of sqlite. |
166 // Do not call it when using system sqlite. | 166 // Do not call it when using system sqlite. |
167 sqlite3_preload(db_); | 167 sqlite3_preload(db_); |
168 #endif | 168 #endif |
169 } | 169 } |
170 | 170 |
171 // Create an in-memory database with the existing database's page | |
172 // size, then backup that database over the existing database. | |
173 bool Connection::Raze() { | |
174 if (!db_) { | |
175 DLOG(FATAL) << "Cannot raze null db"; | |
176 return false; | |
177 } | |
178 | |
179 if (transaction_nesting_ > 0) { | |
180 DLOG(FATAL) << "Cannot raze within a transaction"; | |
181 return false; | |
182 } | |
183 | |
184 sql::Connection null_db; | |
185 if (!null_db.OpenInMemory()) { | |
186 DLOG(FATAL) << "Unable to open in-memory database."; | |
187 return false; | |
188 } | |
189 | |
190 // Get the page size from the current connection, then propagate it | |
191 // to the null database. | |
192 Statement s(GetUniqueStatement("PRAGMA page_size")); | |
193 if (!s.Step()) | |
194 return false; | |
195 const std::string sql = StringPrintf("PRAGMA page_size=%d", s.ColumnInt(0)); | |
196 if (!null_db.Execute(sql.c_str())) | |
197 return false; | |
198 | |
199 // The page size doesn't take effect until a database has pages, and | |
200 // at this point the null database has none. Changing the schema | |
201 // version will create the first page. This will not affect the | |
202 // schema version in the resulting database, as SQLite's backup | |
203 // implementation propagates the schema version from the original | |
204 // connection to the new version of the database, incremented by one | |
205 // so that other readers see the schema change and act accordingly. | |
206 if (!null_db.Execute("PRAGMA schema_version = 1")) | |
207 return false; | |
208 | |
209 sqlite3_backup* backup = sqlite3_backup_init(db_, "main", | |
210 null_db.db_, "main"); | |
211 if (!backup) { | |
212 DLOG(FATAL) << "Unable to start sqlite3_backup()."; | |
213 return false; | |
214 } | |
215 | |
216 // -1 backs up the entire database. | |
217 int rc = sqlite3_backup_step(backup, -1); | |
218 int pages = sqlite3_backup_pagecount(backup); | |
219 sqlite3_backup_finish(backup); | |
220 | |
221 // The destination database was locked. | |
222 if (rc == SQLITE_BUSY) { | |
223 return false; | |
224 } | |
225 | |
226 // The entire database should have been backed up. | |
227 if (rc != SQLITE_DONE) { | |
228 DLOG(FATAL) << "Unable to copy entire null database."; | |
229 return false; | |
230 } | |
231 | |
232 // Exactly one page should have been backed up. If this breaks, | |
233 // check this function to make sure assumptions aren't being broken. | |
234 DCHECK_EQ(pages, 1); | |
Greg Billock
2012/04/04 19:49:21
Likes it. That should get the attention of a versi
| |
235 | |
236 return true; | |
237 } | |
238 | |
239 bool Connection::RazeWithTimout(base::TimeDelta timeout) { | |
240 if (!db_) { | |
241 DLOG(FATAL) << "Cannot raze null db"; | |
242 return false; | |
243 } | |
244 | |
245 ScopedBusyTimeout busy_timeout(db_); | |
246 busy_timeout.SetTimeout(timeout); | |
247 return Raze(); | |
248 } | |
249 | |
171 bool Connection::BeginTransaction() { | 250 bool Connection::BeginTransaction() { |
172 if (needs_rollback_) { | 251 if (needs_rollback_) { |
173 DCHECK_GT(transaction_nesting_, 0); | 252 DCHECK_GT(transaction_nesting_, 0); |
174 | 253 |
175 // When we're going to rollback, fail on this begin and don't actually | 254 // When we're going to rollback, fail on this begin and don't actually |
176 // mark us as entering the nested transaction. | 255 // mark us as entering the nested transaction. |
177 return false; | 256 return false; |
178 } | 257 } |
179 | 258 |
180 bool success = true; | 259 bool success = true; |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
485 | 564 |
486 int Connection::OnSqliteError(int err, sql::Statement *stmt) { | 565 int Connection::OnSqliteError(int err, sql::Statement *stmt) { |
487 if (error_delegate_.get()) | 566 if (error_delegate_.get()) |
488 return error_delegate_->OnError(err, this, stmt); | 567 return error_delegate_->OnError(err, this, stmt); |
489 // 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. |
490 DLOG(FATAL) << GetErrorMessage(); | 569 DLOG(FATAL) << GetErrorMessage(); |
491 return err; | 570 return err; |
492 } | 571 } |
493 | 572 |
494 } // namespace sql | 573 } // namespace sql |
OLD | NEW |