| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "chrome/browser/sync/syncable/directory_backing_store.h" | 5 #include "chrome/browser/sync/syncable/directory_backing_store.h" |
| 6 | 6 |
| 7 #include "build/build_config.h" | 7 #include "build/build_config.h" |
| 8 | 8 |
| 9 #if defined(OS_MACOSX) | 9 #if defined(OS_MACOSX) |
| 10 #include <CoreFoundation/CoreFoundation.h> | 10 #include <CoreFoundation/CoreFoundation.h> |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 // modifies all the columns in the entry table. | 42 // modifies all the columns in the entry table. |
| 43 static const string::size_type kUpdateStatementBufferSize = 2048; | 43 static const string::size_type kUpdateStatementBufferSize = 2048; |
| 44 | 44 |
| 45 // Increment this version whenever updating DB tables. | 45 // Increment this version whenever updating DB tables. |
| 46 extern const int32 kCurrentDBVersion; // Global visibility for our unittest. | 46 extern const int32 kCurrentDBVersion; // Global visibility for our unittest. |
| 47 const int32 kCurrentDBVersion = 76; | 47 const int32 kCurrentDBVersion = 76; |
| 48 | 48 |
| 49 namespace { | 49 namespace { |
| 50 | 50 |
| 51 int ExecQuery(sqlite3* dbhandle, const char* query) { | 51 int ExecQuery(sqlite3* dbhandle, const char* query) { |
| 52 SQLStatement statement; | 52 sqlite_utils::SQLStatement statement; |
| 53 int result = statement.prepare(dbhandle, query); | 53 int result = statement.prepare(dbhandle, query); |
| 54 if (SQLITE_OK != result) | 54 if (SQLITE_OK != result) |
| 55 return result; | 55 return result; |
| 56 do { | 56 do { |
| 57 result = statement.step(); | 57 result = statement.step(); |
| 58 } while (SQLITE_ROW == result); | 58 } while (SQLITE_ROW == result); |
| 59 | 59 |
| 60 return result; | 60 return result; |
| 61 } | 61 } |
| 62 | 62 |
| 63 string GenerateCacheGUID() { | 63 string GenerateCacheGUID() { |
| 64 return Generate128BitRandomBase64String(); | 64 return Generate128BitRandomBase64String(); |
| 65 } | 65 } |
| 66 | 66 |
| 67 } // namespace | 67 } // namespace |
| 68 | 68 |
| 69 | 69 |
| 70 // Iterate over the fields of |entry| and bind each to |statement| for | 70 // Iterate over the fields of |entry| and bind each to |statement| for |
| 71 // updating. Returns the number of args bound. | 71 // updating. Returns the number of args bound. |
| 72 int BindFields(const EntryKernel& entry, SQLStatement* statement) { | 72 int BindFields(const EntryKernel& entry, |
| 73 sqlite_utils::SQLStatement* statement) { |
| 73 int index = 0; | 74 int index = 0; |
| 74 int i = 0; | 75 int i = 0; |
| 75 for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) { | 76 for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) { |
| 76 statement->bind_int64(index++, entry.ref(static_cast<Int64Field>(i))); | 77 statement->bind_int64(index++, entry.ref(static_cast<Int64Field>(i))); |
| 77 } | 78 } |
| 78 for ( ; i < ID_FIELDS_END; ++i) { | 79 for ( ; i < ID_FIELDS_END; ++i) { |
| 79 statement->bind_string(index++, entry.ref(static_cast<IdField>(i)).s_); | 80 statement->bind_string(index++, entry.ref(static_cast<IdField>(i)).s_); |
| 80 } | 81 } |
| 81 for ( ; i < BIT_FIELDS_END; ++i) { | 82 for ( ; i < BIT_FIELDS_END; ++i) { |
| 82 statement->bind_int(index++, entry.ref(static_cast<BitField>(i))); | 83 statement->bind_int(index++, entry.ref(static_cast<BitField>(i))); |
| 83 } | 84 } |
| 84 for ( ; i < STRING_FIELDS_END; ++i) { | 85 for ( ; i < STRING_FIELDS_END; ++i) { |
| 85 statement->bind_string(index++, entry.ref(static_cast<StringField>(i))); | 86 statement->bind_string(index++, entry.ref(static_cast<StringField>(i))); |
| 86 } | 87 } |
| 87 std::string temp; | 88 std::string temp; |
| 88 for ( ; i < PROTO_FIELDS_END; ++i) { | 89 for ( ; i < PROTO_FIELDS_END; ++i) { |
| 89 entry.ref(static_cast<ProtoField>(i)).SerializeToString(&temp); | 90 entry.ref(static_cast<ProtoField>(i)).SerializeToString(&temp); |
| 90 statement->bind_blob(index++, temp.data(), temp.length()); | 91 statement->bind_blob(index++, temp.data(), temp.length()); |
| 91 } | 92 } |
| 92 return index; | 93 return index; |
| 93 } | 94 } |
| 94 | 95 |
| 95 // The caller owns the returned EntryKernel*. | 96 // The caller owns the returned EntryKernel*. |
| 96 int UnpackEntry(SQLStatement* statement, EntryKernel** kernel) { | 97 int UnpackEntry(sqlite_utils::SQLStatement* statement, EntryKernel** kernel) { |
| 97 *kernel = NULL; | 98 *kernel = NULL; |
| 98 int query_result = statement->step(); | 99 int query_result = statement->step(); |
| 99 if (SQLITE_ROW == query_result) { | 100 if (SQLITE_ROW == query_result) { |
| 100 *kernel = new EntryKernel; | 101 *kernel = new EntryKernel; |
| 101 (*kernel)->clear_dirty(NULL); | 102 (*kernel)->clear_dirty(NULL); |
| 102 DCHECK(statement->column_count() == static_cast<int>(FIELD_COUNT)); | 103 DCHECK(statement->column_count() == static_cast<int>(FIELD_COUNT)); |
| 103 int i = 0; | 104 int i = 0; |
| 104 for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) { | 105 for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) { |
| 105 (*kernel)->put(static_cast<Int64Field>(i), statement->column_int64(i)); | 106 (*kernel)->put(static_cast<Int64Field>(i), statement->column_int64(i)); |
| 106 } | 107 } |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 sqlite3_busy_timeout(scoped_handle.get(), std::numeric_limits<int>::max()); | 189 sqlite3_busy_timeout(scoped_handle.get(), std::numeric_limits<int>::max()); |
| 189 { | 190 { |
| 190 string integrity_error; | 191 string integrity_error; |
| 191 bool is_ok = CheckIntegrity(scoped_handle.get(), &integrity_error); | 192 bool is_ok = CheckIntegrity(scoped_handle.get(), &integrity_error); |
| 192 if (!is_ok) { | 193 if (!is_ok) { |
| 193 LOG(ERROR) << "Integrity check failed: " << integrity_error; | 194 LOG(ERROR) << "Integrity check failed: " << integrity_error; |
| 194 return false; | 195 return false; |
| 195 } | 196 } |
| 196 } | 197 } |
| 197 { | 198 { |
| 198 SQLStatement statement; | 199 sqlite_utils::SQLStatement statement; |
| 199 statement.prepare(scoped_handle.get(), "PRAGMA fullfsync = 1"); | 200 statement.prepare(scoped_handle.get(), "PRAGMA fullfsync = 1"); |
| 200 if (SQLITE_DONE != statement.step()) { | 201 if (SQLITE_DONE != statement.step()) { |
| 201 LOG(ERROR) << sqlite3_errmsg(scoped_handle.get()); | 202 LOG(ERROR) << sqlite3_errmsg(scoped_handle.get()); |
| 202 return false; | 203 return false; |
| 203 } | 204 } |
| 204 } | 205 } |
| 205 { | 206 { |
| 206 SQLStatement statement; | 207 sqlite_utils::SQLStatement statement; |
| 207 statement.prepare(scoped_handle.get(), "PRAGMA synchronous = 2"); | 208 statement.prepare(scoped_handle.get(), "PRAGMA synchronous = 2"); |
| 208 if (SQLITE_DONE != statement.step()) { | 209 if (SQLITE_DONE != statement.step()) { |
| 209 LOG(ERROR) << sqlite3_errmsg(scoped_handle.get()); | 210 LOG(ERROR) << sqlite3_errmsg(scoped_handle.get()); |
| 210 return false; | 211 return false; |
| 211 } | 212 } |
| 212 } | 213 } |
| 213 sqlite3_busy_timeout(scoped_handle.release(), | 214 sqlite3_busy_timeout(scoped_handle.release(), |
| 214 kDirectoryBackingStoreBusyTimeoutMs); | 215 kDirectoryBackingStoreBusyTimeoutMs); |
| 215 #if defined(OS_WIN) | 216 #if defined(OS_WIN) |
| 216 // Do not index this file. Scanning can occur every time we close the file, | 217 // Do not index this file. Scanning can occur every time we close the file, |
| 217 // which causes long delays in SQLite's file locking. | 218 // which causes long delays in SQLite's file locking. |
| 218 const DWORD attrs = GetFileAttributes(backing_filepath_.value().c_str()); | 219 const DWORD attrs = GetFileAttributes(backing_filepath_.value().c_str()); |
| 219 const BOOL attrs_set = | 220 const BOOL attrs_set = |
| 220 SetFileAttributes(backing_filepath_.value().c_str(), | 221 SetFileAttributes(backing_filepath_.value().c_str(), |
| 221 attrs | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); | 222 attrs | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); |
| 222 #endif | 223 #endif |
| 223 | 224 |
| 224 return true; | 225 return true; |
| 225 } | 226 } |
| 226 return false; | 227 return false; |
| 227 } | 228 } |
| 228 | 229 |
| 229 bool DirectoryBackingStore::CheckIntegrity(sqlite3* handle, string* error) | 230 bool DirectoryBackingStore::CheckIntegrity(sqlite3* handle, string* error) |
| 230 const { | 231 const { |
| 231 SQLStatement statement; | 232 sqlite_utils::SQLStatement statement; |
| 232 statement.prepare(handle, "PRAGMA integrity_check(1)"); | 233 statement.prepare(handle, "PRAGMA integrity_check(1)"); |
| 233 if (SQLITE_ROW != statement.step()) { | 234 if (SQLITE_ROW != statement.step()) { |
| 234 *error = sqlite3_errmsg(handle); | 235 *error = sqlite3_errmsg(handle); |
| 235 return false; | 236 return false; |
| 236 } | 237 } |
| 237 string integrity_result = statement.column_text(0); | 238 string integrity_result = statement.column_text(0); |
| 238 if (integrity_result != "ok") { | 239 if (integrity_result != "ok") { |
| 239 *error = integrity_result; | 240 *error = integrity_result; |
| 240 return false; | 241 return false; |
| 241 } | 242 } |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 sqlite3* dbhandle = LazyGetSaveHandle(); | 333 sqlite3* dbhandle = LazyGetSaveHandle(); |
| 333 | 334 |
| 334 string query = "DELETE FROM metas WHERE metahandle IN ("; | 335 string query = "DELETE FROM metas WHERE metahandle IN ("; |
| 335 for (MetahandleSet::const_iterator it = handles.begin(); it != handles.end(); | 336 for (MetahandleSet::const_iterator it = handles.begin(); it != handles.end(); |
| 336 ++it) { | 337 ++it) { |
| 337 if (it != handles.begin()) | 338 if (it != handles.begin()) |
| 338 query.append(","); | 339 query.append(","); |
| 339 query.append(base::Int64ToString(*it)); | 340 query.append(base::Int64ToString(*it)); |
| 340 } | 341 } |
| 341 query.append(")"); | 342 query.append(")"); |
| 342 SQLStatement statement; | 343 sqlite_utils::SQLStatement statement; |
| 343 int result = statement.prepare(dbhandle, query.data(), query.size()); | 344 int result = statement.prepare(dbhandle, query.data(), query.size()); |
| 344 if (SQLITE_OK == result) | 345 if (SQLITE_OK == result) |
| 345 result = statement.step(); | 346 result = statement.step(); |
| 346 | 347 |
| 347 return SQLITE_DONE == result; | 348 return SQLITE_DONE == result; |
| 348 } | 349 } |
| 349 | 350 |
| 350 bool DirectoryBackingStore::SaveChanges( | 351 bool DirectoryBackingStore::SaveChanges( |
| 351 const Directory::SaveChangesSnapshot& snapshot) { | 352 const Directory::SaveChangesSnapshot& snapshot) { |
| 352 sqlite3* dbhandle = LazyGetSaveHandle(); | 353 sqlite3* dbhandle = LazyGetSaveHandle(); |
| 353 | 354 |
| 354 // SQLTransaction::BeginExclusive causes a disk write to occur. This is not | 355 // SQLTransaction::BeginExclusive causes a disk write to occur. This is not |
| 355 // something that should happen every 10 seconds when this function runs, so | 356 // something that should happen every 10 seconds when this function runs, so |
| 356 // just stop here if there's nothing to save. | 357 // just stop here if there's nothing to save. |
| 357 bool save_info = | 358 bool save_info = |
| 358 (Directory::KERNEL_SHARE_INFO_DIRTY == snapshot.kernel_info_status); | 359 (Directory::KERNEL_SHARE_INFO_DIRTY == snapshot.kernel_info_status); |
| 359 if (snapshot.dirty_metas.size() < 1 && !save_info) | 360 if (snapshot.dirty_metas.size() < 1 && !save_info) |
| 360 return true; | 361 return true; |
| 361 | 362 |
| 362 SQLTransaction transaction(dbhandle); | 363 sqlite_utils::SQLTransaction transaction(dbhandle); |
| 363 if (SQLITE_OK != transaction.BeginExclusive()) | 364 if (SQLITE_OK != transaction.BeginExclusive()) |
| 364 return false; | 365 return false; |
| 365 | 366 |
| 366 for (EntryKernelSet::const_iterator i = snapshot.dirty_metas.begin(); | 367 for (EntryKernelSet::const_iterator i = snapshot.dirty_metas.begin(); |
| 367 i != snapshot.dirty_metas.end(); ++i) { | 368 i != snapshot.dirty_metas.end(); ++i) { |
| 368 DCHECK(i->is_dirty()); | 369 DCHECK(i->is_dirty()); |
| 369 if (!SaveEntryToDB(*i)) | 370 if (!SaveEntryToDB(*i)) |
| 370 return false; | 371 return false; |
| 371 } | 372 } |
| 372 | 373 |
| 373 if (!DeleteEntries(snapshot.metahandles_to_purge)) | 374 if (!DeleteEntries(snapshot.metahandles_to_purge)) |
| 374 return false; | 375 return false; |
| 375 | 376 |
| 376 if (save_info) { | 377 if (save_info) { |
| 377 const Directory::PersistedKernelInfo& info = snapshot.kernel_info; | 378 const Directory::PersistedKernelInfo& info = snapshot.kernel_info; |
| 378 SQLStatement update; | 379 sqlite_utils::SQLStatement update; |
| 379 update.prepare(dbhandle, "UPDATE share_info " | 380 update.prepare(dbhandle, "UPDATE share_info " |
| 380 "SET store_birthday = ?, " | 381 "SET store_birthday = ?, " |
| 381 "next_id = ?, " | 382 "next_id = ?, " |
| 382 "notification_state = ? "); | 383 "notification_state = ? "); |
| 383 | 384 |
| 384 update.bind_string(0, info.store_birthday); | 385 update.bind_string(0, info.store_birthday); |
| 385 update.bind_int64(1, info.next_id); | 386 update.bind_int64(1, info.next_id); |
| 386 update.bind_blob(2, info.notification_state.data(), | 387 update.bind_blob(2, info.notification_state.data(), |
| 387 info.notification_state.size()); | 388 info.notification_state.size()); |
| 388 | 389 |
| 389 if (!(SQLITE_DONE == update.step() && | 390 if (!(SQLITE_DONE == update.step() && |
| 390 SQLITE_OK == update.reset() && | 391 SQLITE_OK == update.reset() && |
| 391 1 == update.changes())) { | 392 1 == update.changes())) { |
| 392 return false; | 393 return false; |
| 393 } | 394 } |
| 394 | 395 |
| 395 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { | 396 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { |
| 396 SQLStatement op; | 397 sqlite_utils::SQLStatement op; |
| 397 op.prepare(dbhandle, "INSERT OR REPLACE INTO models (model_id, " | 398 op.prepare(dbhandle, "INSERT OR REPLACE INTO models (model_id, " |
| 398 "progress_marker, initial_sync_ended) VALUES ( ?, ?, ?)"); | 399 "progress_marker, initial_sync_ended) VALUES ( ?, ?, ?)"); |
| 399 // We persist not ModelType but rather a protobuf-derived ID. | 400 // We persist not ModelType but rather a protobuf-derived ID. |
| 400 string model_id = ModelTypeEnumToModelId(ModelTypeFromInt(i)); | 401 string model_id = ModelTypeEnumToModelId(ModelTypeFromInt(i)); |
| 401 string progress_marker; | 402 string progress_marker; |
| 402 info.download_progress[i].SerializeToString(&progress_marker); | 403 info.download_progress[i].SerializeToString(&progress_marker); |
| 403 op.bind_blob(0, model_id.data(), model_id.length()); | 404 op.bind_blob(0, model_id.data(), model_id.length()); |
| 404 op.bind_blob(1, progress_marker.data(), progress_marker.length()); | 405 op.bind_blob(1, progress_marker.data(), progress_marker.length()); |
| 405 op.bind_bool(2, info.initial_sync_ended[i]); | 406 op.bind_bool(2, info.initial_sync_ended[i]); |
| 406 | 407 |
| 407 if (!(SQLITE_DONE == op.step() && | 408 if (!(SQLITE_DONE == op.step() && |
| 408 SQLITE_OK == op.reset() && | 409 SQLITE_OK == op.reset() && |
| 409 1 == op.changes())) { | 410 1 == op.changes())) { |
| 410 return false; | 411 return false; |
| 411 } | 412 } |
| 412 } | 413 } |
| 413 } | 414 } |
| 414 | 415 |
| 415 return (SQLITE_OK == transaction.Commit()); | 416 return (SQLITE_OK == transaction.Commit()); |
| 416 } | 417 } |
| 417 | 418 |
| 418 DirOpenResult DirectoryBackingStore::InitializeTables() { | 419 DirOpenResult DirectoryBackingStore::InitializeTables() { |
| 419 SQLTransaction transaction(load_dbhandle_); | 420 sqlite_utils::SQLTransaction transaction(load_dbhandle_); |
| 420 if (SQLITE_OK != transaction.BeginExclusive()) { | 421 if (SQLITE_OK != transaction.BeginExclusive()) { |
| 421 return FAILED_DISK_FULL; | 422 return FAILED_DISK_FULL; |
| 422 } | 423 } |
| 423 int version_on_disk = GetVersion(); | 424 int version_on_disk = GetVersion(); |
| 424 int last_result = SQLITE_DONE; | 425 int last_result = SQLITE_DONE; |
| 425 | 426 |
| 426 // Upgrade from version 67. Version 67 was widely distributed as the original | 427 // Upgrade from version 67. Version 67 was widely distributed as the original |
| 427 // Bookmark Sync release. Version 68 removed unique naming. | 428 // Bookmark Sync release. Version 68 removed unique naming. |
| 428 if (version_on_disk == 67) { | 429 if (version_on_disk == 67) { |
| 429 if (MigrateVersion67To68()) | 430 if (MigrateVersion67To68()) |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 return FAILED_NEWER_VERSION; | 493 return FAILED_NEWER_VERSION; |
| 493 } | 494 } |
| 494 // Fallback (re-sync everything) migration path. | 495 // Fallback (re-sync everything) migration path. |
| 495 VLOG(1) << "Old/null sync database, version " << version_on_disk; | 496 VLOG(1) << "Old/null sync database, version " << version_on_disk; |
| 496 // Delete the existing database (if any), and create a fresh one. | 497 // Delete the existing database (if any), and create a fresh one. |
| 497 DropAllTables(); | 498 DropAllTables(); |
| 498 last_result = CreateTables(); | 499 last_result = CreateTables(); |
| 499 } | 500 } |
| 500 if (SQLITE_DONE == last_result) { | 501 if (SQLITE_DONE == last_result) { |
| 501 { | 502 { |
| 502 SQLStatement statement; | 503 sqlite_utils::SQLStatement statement; |
| 503 statement.prepare(load_dbhandle_, | 504 statement.prepare(load_dbhandle_, |
| 504 "SELECT db_create_version, db_create_time FROM share_info"); | 505 "SELECT db_create_version, db_create_time FROM share_info"); |
| 505 if (SQLITE_ROW != statement.step()) { | 506 if (SQLITE_ROW != statement.step()) { |
| 506 transaction.Rollback(); | 507 transaction.Rollback(); |
| 507 return FAILED_DISK_FULL; | 508 return FAILED_DISK_FULL; |
| 508 } | 509 } |
| 509 string db_create_version = statement.column_text(0); | 510 string db_create_version = statement.column_text(0); |
| 510 int db_create_time = statement.column_int(1); | 511 int db_create_time = statement.column_int(1); |
| 511 statement.reset(); | 512 statement.reset(); |
| 512 VLOG(1) << "DB created at " << db_create_time << " by version " << | 513 VLOG(1) << "DB created at " << db_create_time << " by version " << |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 needs_column_refresh_ = false; | 572 needs_column_refresh_ = false; |
| 572 return true; | 573 return true; |
| 573 } | 574 } |
| 574 | 575 |
| 575 bool DirectoryBackingStore::LoadEntries(MetahandlesIndex* entry_bucket) { | 576 bool DirectoryBackingStore::LoadEntries(MetahandlesIndex* entry_bucket) { |
| 576 string select; | 577 string select; |
| 577 select.reserve(kUpdateStatementBufferSize); | 578 select.reserve(kUpdateStatementBufferSize); |
| 578 select.append("SELECT "); | 579 select.append("SELECT "); |
| 579 AppendColumnList(&select); | 580 AppendColumnList(&select); |
| 580 select.append(" FROM metas "); | 581 select.append(" FROM metas "); |
| 581 SQLStatement statement; | 582 sqlite_utils::SQLStatement statement; |
| 582 statement.prepare(load_dbhandle_, select.c_str()); | 583 statement.prepare(load_dbhandle_, select.c_str()); |
| 583 base::hash_set<int64> handles; | 584 base::hash_set<int64> handles; |
| 584 EntryKernel* kernel = NULL; | 585 EntryKernel* kernel = NULL; |
| 585 int query_result; | 586 int query_result; |
| 586 while (SQLITE_ROW == (query_result = UnpackEntry(&statement, &kernel))) { | 587 while (SQLITE_ROW == (query_result = UnpackEntry(&statement, &kernel))) { |
| 587 DCHECK(handles.insert(kernel->ref(META_HANDLE)).second); // Only in debug. | 588 DCHECK(handles.insert(kernel->ref(META_HANDLE)).second); // Only in debug. |
| 588 entry_bucket->insert(kernel); | 589 entry_bucket->insert(kernel); |
| 589 } | 590 } |
| 590 return SQLITE_DONE == query_result; | 591 return SQLITE_DONE == query_result; |
| 591 } | 592 } |
| 592 | 593 |
| 593 bool DirectoryBackingStore::LoadInfo(Directory::KernelLoadInfo* info) { | 594 bool DirectoryBackingStore::LoadInfo(Directory::KernelLoadInfo* info) { |
| 594 { | 595 { |
| 595 SQLStatement query; | 596 sqlite_utils::SQLStatement query; |
| 596 query.prepare(load_dbhandle_, | 597 query.prepare(load_dbhandle_, |
| 597 "SELECT store_birthday, next_id, cache_guid, " | 598 "SELECT store_birthday, next_id, cache_guid, " |
| 598 "notification_state " | 599 "notification_state " |
| 599 "FROM share_info"); | 600 "FROM share_info"); |
| 600 if (SQLITE_ROW != query.step()) | 601 if (SQLITE_ROW != query.step()) |
| 601 return false; | 602 return false; |
| 602 info->kernel_info.store_birthday = query.column_string(0); | 603 info->kernel_info.store_birthday = query.column_string(0); |
| 603 info->kernel_info.next_id = query.column_int64(1); | 604 info->kernel_info.next_id = query.column_int64(1); |
| 604 info->cache_guid = query.column_string(2); | 605 info->cache_guid = query.column_string(2); |
| 605 query.column_blob_as_string(3, &info->kernel_info.notification_state); | 606 query.column_blob_as_string(3, &info->kernel_info.notification_state); |
| 606 } | 607 } |
| 607 { | 608 { |
| 608 SQLStatement query; | 609 sqlite_utils::SQLStatement query; |
| 609 query.prepare(load_dbhandle_, | 610 query.prepare(load_dbhandle_, |
| 610 "SELECT model_id, progress_marker, initial_sync_ended " | 611 "SELECT model_id, progress_marker, initial_sync_ended " |
| 611 "FROM models"); | 612 "FROM models"); |
| 612 while (SQLITE_ROW == query.step()) { | 613 while (SQLITE_ROW == query.step()) { |
| 613 ModelType type = ModelIdToModelTypeEnum(query.column_blob(0), | 614 ModelType type = ModelIdToModelTypeEnum(query.column_blob(0), |
| 614 query.column_bytes(0)); | 615 query.column_bytes(0)); |
| 615 if (type != UNSPECIFIED && type != TOP_LEVEL_FOLDER) { | 616 if (type != UNSPECIFIED && type != TOP_LEVEL_FOLDER) { |
| 616 info->kernel_info.download_progress[type].ParseFromArray( | 617 info->kernel_info.download_progress[type].ParseFromArray( |
| 617 query.column_blob(1), query.column_bytes(1)); | 618 query.column_blob(1), query.column_bytes(1)); |
| 618 info->kernel_info.initial_sync_ended[type] = query.column_bool(2); | 619 info->kernel_info.initial_sync_ended[type] = query.column_bool(2); |
| 619 } | 620 } |
| 620 } | 621 } |
| 621 } | 622 } |
| 622 { | 623 { |
| 623 SQLStatement query; | 624 sqlite_utils::SQLStatement query; |
| 624 query.prepare(load_dbhandle_, | 625 query.prepare(load_dbhandle_, |
| 625 "SELECT MAX(metahandle) FROM metas"); | 626 "SELECT MAX(metahandle) FROM metas"); |
| 626 if (SQLITE_ROW != query.step()) | 627 if (SQLITE_ROW != query.step()) |
| 627 return false; | 628 return false; |
| 628 info->max_metahandle = query.column_int64(0); | 629 info->max_metahandle = query.column_int64(0); |
| 629 } | 630 } |
| 630 return true; | 631 return true; |
| 631 } | 632 } |
| 632 | 633 |
| 633 bool DirectoryBackingStore::SaveEntryToDB(const EntryKernel& entry) { | 634 bool DirectoryBackingStore::SaveEntryToDB(const EntryKernel& entry) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 644 query.append(separator); | 645 query.append(separator); |
| 645 values.append(separator); | 646 values.append(separator); |
| 646 separator = ", "; | 647 separator = ", "; |
| 647 query.append(ColumnName(i)); | 648 query.append(ColumnName(i)); |
| 648 values.append("?"); | 649 values.append("?"); |
| 649 } | 650 } |
| 650 | 651 |
| 651 query.append(" ) "); | 652 query.append(" ) "); |
| 652 values.append(" )"); | 653 values.append(" )"); |
| 653 query.append(values); | 654 query.append(values); |
| 654 SQLStatement statement; | 655 sqlite_utils::SQLStatement statement; |
| 655 statement.prepare(save_dbhandle_, query.c_str()); | 656 statement.prepare(save_dbhandle_, query.c_str()); |
| 656 BindFields(entry, &statement); | 657 BindFields(entry, &statement); |
| 657 return (SQLITE_DONE == statement.step() && | 658 return (SQLITE_DONE == statement.step() && |
| 658 SQLITE_OK == statement.reset() && | 659 SQLITE_OK == statement.reset() && |
| 659 1 == statement.changes()); | 660 1 == statement.changes()); |
| 660 } | 661 } |
| 661 | 662 |
| 662 bool DirectoryBackingStore::DropDeletedEntries() { | 663 bool DirectoryBackingStore::DropDeletedEntries() { |
| 663 static const char delete_metas[] = "DELETE FROM metas WHERE metahandle IN " | 664 static const char delete_metas[] = "DELETE FROM metas WHERE metahandle IN " |
| 664 "(SELECT metahandle from death_row)"; | 665 "(SELECT metahandle from death_row)"; |
| 665 // Put all statements into a transaction for better performance | 666 // Put all statements into a transaction for better performance |
| 666 SQLTransaction transaction(load_dbhandle_); | 667 sqlite_utils::SQLTransaction transaction(load_dbhandle_); |
| 667 transaction.Begin(); | 668 transaction.Begin(); |
| 668 if (SQLITE_DONE != ExecQuery( | 669 if (SQLITE_DONE != ExecQuery( |
| 669 load_dbhandle_, | 670 load_dbhandle_, |
| 670 "CREATE TEMP TABLE death_row (metahandle BIGINT)")) { | 671 "CREATE TEMP TABLE death_row (metahandle BIGINT)")) { |
| 671 return false; | 672 return false; |
| 672 } | 673 } |
| 673 if (SQLITE_DONE != ExecQuery(load_dbhandle_, | 674 if (SQLITE_DONE != ExecQuery(load_dbhandle_, |
| 674 "INSERT INTO death_row " | 675 "INSERT INTO death_row " |
| 675 "SELECT metahandle from metas WHERE is_del > 0 " | 676 "SELECT metahandle from metas WHERE is_del > 0 " |
| 676 " AND is_unsynced < 1" | 677 " AND is_unsynced < 1" |
| 677 " AND is_unapplied_update < 1")) { | 678 " AND is_unapplied_update < 1")) { |
| 678 return false; | 679 return false; |
| 679 } | 680 } |
| 680 if (SQLITE_DONE != ExecQuery(load_dbhandle_, delete_metas)) { | 681 if (SQLITE_DONE != ExecQuery(load_dbhandle_, delete_metas)) { |
| 681 return false; | 682 return false; |
| 682 } | 683 } |
| 683 if (SQLITE_DONE != ExecQuery(load_dbhandle_, "DROP TABLE death_row")) { | 684 if (SQLITE_DONE != ExecQuery(load_dbhandle_, "DROP TABLE death_row")) { |
| 684 return false; | 685 return false; |
| 685 } | 686 } |
| 686 transaction.Commit(); | 687 transaction.Commit(); |
| 687 return true; | 688 return true; |
| 688 } | 689 } |
| 689 | 690 |
| 690 int DirectoryBackingStore::SafeDropTable(const char* table_name) { | 691 int DirectoryBackingStore::SafeDropTable(const char* table_name) { |
| 691 string query = "DROP TABLE IF EXISTS "; | 692 string query = "DROP TABLE IF EXISTS "; |
| 692 query.append(table_name); | 693 query.append(table_name); |
| 693 SQLStatement statement; | 694 sqlite_utils::SQLStatement statement; |
| 694 int result = statement.prepare(load_dbhandle_, query.data(), | 695 int result = statement.prepare(load_dbhandle_, query.data(), |
| 695 query.size()); | 696 query.size()); |
| 696 if (SQLITE_OK == result) { | 697 if (SQLITE_OK == result) { |
| 697 result = statement.step(); | 698 result = statement.step(); |
| 698 if (SQLITE_DONE == result) | 699 if (SQLITE_DONE == result) |
| 699 statement.finalize(); | 700 statement.finalize(); |
| 700 } | 701 } |
| 701 | 702 |
| 702 return result; | 703 return result; |
| 703 } | 704 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 726 // static | 727 // static |
| 727 string DirectoryBackingStore::ModelTypeEnumToModelId(ModelType model_type) { | 728 string DirectoryBackingStore::ModelTypeEnumToModelId(ModelType model_type) { |
| 728 sync_pb::EntitySpecifics specifics; | 729 sync_pb::EntitySpecifics specifics; |
| 729 syncable::AddDefaultExtensionValue(model_type, &specifics); | 730 syncable::AddDefaultExtensionValue(model_type, &specifics); |
| 730 return specifics.SerializeAsString(); | 731 return specifics.SerializeAsString(); |
| 731 } | 732 } |
| 732 | 733 |
| 733 bool DirectoryBackingStore::MigrateToSpecifics( | 734 bool DirectoryBackingStore::MigrateToSpecifics( |
| 734 const char* old_columns, | 735 const char* old_columns, |
| 735 const char* specifics_column, | 736 const char* specifics_column, |
| 736 void (*handler_function)(SQLStatement* old_value_query, | 737 void (*handler_function)(sqlite_utils::SQLStatement* old_value_query, |
| 737 int old_value_column, | 738 int old_value_column, |
| 738 sync_pb::EntitySpecifics* mutable_new_value)) { | 739 sync_pb::EntitySpecifics* mutable_new_value)) { |
| 739 std::string query_sql = base::StringPrintf( | 740 std::string query_sql = base::StringPrintf( |
| 740 "SELECT metahandle, %s, %s FROM metas", specifics_column, old_columns); | 741 "SELECT metahandle, %s, %s FROM metas", specifics_column, old_columns); |
| 741 std::string update_sql = base::StringPrintf( | 742 std::string update_sql = base::StringPrintf( |
| 742 "UPDATE metas SET %s = ? WHERE metahandle = ?", specifics_column); | 743 "UPDATE metas SET %s = ? WHERE metahandle = ?", specifics_column); |
| 743 SQLStatement query; | 744 sqlite_utils::SQLStatement query; |
| 744 query.prepare(load_dbhandle_, query_sql.c_str()); | 745 query.prepare(load_dbhandle_, query_sql.c_str()); |
| 745 while (query.step() == SQLITE_ROW) { | 746 while (query.step() == SQLITE_ROW) { |
| 746 int64 metahandle = query.column_int64(0); | 747 int64 metahandle = query.column_int64(0); |
| 747 std::string new_value_bytes; | 748 std::string new_value_bytes; |
| 748 query.column_blob_as_string(1, &new_value_bytes); | 749 query.column_blob_as_string(1, &new_value_bytes); |
| 749 sync_pb::EntitySpecifics new_value; | 750 sync_pb::EntitySpecifics new_value; |
| 750 new_value.ParseFromString(new_value_bytes); | 751 new_value.ParseFromString(new_value_bytes); |
| 751 handler_function(&query, 2, &new_value); | 752 handler_function(&query, 2, &new_value); |
| 752 new_value.SerializeToString(&new_value_bytes); | 753 new_value.SerializeToString(&new_value_bytes); |
| 753 | 754 |
| 754 SQLStatement update; | 755 sqlite_utils::SQLStatement update; |
| 755 update.prepare(load_dbhandle_, update_sql.data(), update_sql.length()); | 756 update.prepare(load_dbhandle_, update_sql.data(), update_sql.length()); |
| 756 update.bind_blob(0, new_value_bytes.data(), new_value_bytes.length()); | 757 update.bind_blob(0, new_value_bytes.data(), new_value_bytes.length()); |
| 757 update.bind_int64(1, metahandle); | 758 update.bind_int64(1, metahandle); |
| 758 if (update.step() != SQLITE_DONE) { | 759 if (update.step() != SQLITE_DONE) { |
| 759 NOTREACHED(); | 760 NOTREACHED(); |
| 760 return false; | 761 return false; |
| 761 } | 762 } |
| 762 } | 763 } |
| 763 return true; | 764 return true; |
| 764 } | 765 } |
| 765 | 766 |
| 766 bool DirectoryBackingStore::AddColumn(const ColumnSpec* column) { | 767 bool DirectoryBackingStore::AddColumn(const ColumnSpec* column) { |
| 767 SQLStatement add_column; | 768 sqlite_utils::SQLStatement add_column; |
| 768 std::string sql = base::StringPrintf( | 769 std::string sql = base::StringPrintf( |
| 769 "ALTER TABLE metas ADD COLUMN %s %s", column->name, column->spec); | 770 "ALTER TABLE metas ADD COLUMN %s %s", column->name, column->spec); |
| 770 add_column.prepare(load_dbhandle_, sql.c_str()); | 771 add_column.prepare(load_dbhandle_, sql.c_str()); |
| 771 return add_column.step() == SQLITE_DONE; | 772 return add_column.step() == SQLITE_DONE; |
| 772 } | 773 } |
| 773 | 774 |
| 774 bool DirectoryBackingStore::SetVersion(int version) { | 775 bool DirectoryBackingStore::SetVersion(int version) { |
| 775 SQLStatement statement; | 776 sqlite_utils::SQLStatement statement; |
| 776 statement.prepare(load_dbhandle_, "UPDATE share_version SET data = ?"); | 777 statement.prepare(load_dbhandle_, "UPDATE share_version SET data = ?"); |
| 777 statement.bind_int(0, version); | 778 statement.bind_int(0, version); |
| 778 return statement.step() == SQLITE_DONE; | 779 return statement.step() == SQLITE_DONE; |
| 779 } | 780 } |
| 780 | 781 |
| 781 int DirectoryBackingStore::GetVersion() { | 782 int DirectoryBackingStore::GetVersion() { |
| 782 if (!sqlite_utils::DoesSqliteTableExist(load_dbhandle_, "share_version")) | 783 if (!sqlite_utils::DoesSqliteTableExist(load_dbhandle_, "share_version")) |
| 783 return 0; | 784 return 0; |
| 784 SQLStatement version_query; | 785 sqlite_utils::SQLStatement version_query; |
| 785 version_query.prepare(load_dbhandle_, "SELECT data from share_version"); | 786 version_query.prepare(load_dbhandle_, "SELECT data from share_version"); |
| 786 if (SQLITE_ROW != version_query.step()) | 787 if (SQLITE_ROW != version_query.step()) |
| 787 return 0; | 788 return 0; |
| 788 int value = version_query.column_int(0); | 789 int value = version_query.column_int(0); |
| 789 if (version_query.reset() != SQLITE_OK) | 790 if (version_query.reset() != SQLITE_OK) |
| 790 return 0; | 791 return 0; |
| 791 return value; | 792 return value; |
| 792 } | 793 } |
| 793 | 794 |
| 794 bool DirectoryBackingStore::MigrateVersion67To68() { | 795 bool DirectoryBackingStore::MigrateVersion67To68() { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 809 // we rename the column again, we need to inline the old | 810 // we rename the column again, we need to inline the old |
| 810 // intermediate name / column spec. | 811 // intermediate name / column spec. |
| 811 if (!AddColumn(&g_metas_columns[UNIQUE_SERVER_TAG])) { | 812 if (!AddColumn(&g_metas_columns[UNIQUE_SERVER_TAG])) { |
| 812 return false; | 813 return false; |
| 813 } | 814 } |
| 814 if (!AddColumn(&g_metas_columns[UNIQUE_CLIENT_TAG])) { | 815 if (!AddColumn(&g_metas_columns[UNIQUE_CLIENT_TAG])) { |
| 815 return false; | 816 return false; |
| 816 } | 817 } |
| 817 needs_column_refresh_ = true; | 818 needs_column_refresh_ = true; |
| 818 | 819 |
| 819 SQLStatement statement; | 820 sqlite_utils::SQLStatement statement; |
| 820 statement.prepare(load_dbhandle_, | 821 statement.prepare(load_dbhandle_, |
| 821 "UPDATE metas SET unique_server_tag = singleton_tag"); | 822 "UPDATE metas SET unique_server_tag = singleton_tag"); |
| 822 return statement.step() == SQLITE_DONE; | 823 return statement.step() == SQLITE_DONE; |
| 823 } | 824 } |
| 824 | 825 |
| 825 namespace { | 826 namespace { |
| 826 | 827 |
| 827 // Callback passed to MigrateToSpecifics for the v68->v69 migration. See | 828 // Callback passed to MigrateToSpecifics for the v68->v69 migration. See |
| 828 // MigrateVersion68To69(). | 829 // MigrateVersion68To69(). |
| 829 void EncodeBookmarkURLAndFavicon(SQLStatement* old_value_query, | 830 void EncodeBookmarkURLAndFavicon(sqlite_utils::SQLStatement* old_value_query, |
| 830 int old_value_column, | 831 int old_value_column, |
| 831 sync_pb::EntitySpecifics* mutable_new_value) { | 832 sync_pb::EntitySpecifics* mutable_new_value) { |
| 832 // Extract data from the column trio we expect. | 833 // Extract data from the column trio we expect. |
| 833 bool old_is_bookmark_object = old_value_query->column_bool(old_value_column); | 834 bool old_is_bookmark_object = old_value_query->column_bool(old_value_column); |
| 834 std::string old_url = old_value_query->column_string(old_value_column + 1); | 835 std::string old_url = old_value_query->column_string(old_value_column + 1); |
| 835 std::string old_favicon; | 836 std::string old_favicon; |
| 836 old_value_query->column_blob_as_string(old_value_column + 2, &old_favicon); | 837 old_value_query->column_blob_as_string(old_value_column + 2, &old_favicon); |
| 837 bool old_is_dir = old_value_query->column_bool(old_value_column + 3); | 838 bool old_is_dir = old_value_query->column_bool(old_value_column + 3); |
| 838 | 839 |
| 839 if (old_is_bookmark_object) { | 840 if (old_is_bookmark_object) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 879 "server_bookmark_url, " | 880 "server_bookmark_url, " |
| 880 "server_bookmark_favicon, " | 881 "server_bookmark_favicon, " |
| 881 "server_is_dir"), | 882 "server_is_dir"), |
| 882 "server_specifics", | 883 "server_specifics", |
| 883 &EncodeBookmarkURLAndFavicon)) { | 884 &EncodeBookmarkURLAndFavicon)) { |
| 884 return false; | 885 return false; |
| 885 } | 886 } |
| 886 | 887 |
| 887 // Lastly, fix up the "Google Chrome" folder, which is of the TOP_LEVEL_FOLDER | 888 // Lastly, fix up the "Google Chrome" folder, which is of the TOP_LEVEL_FOLDER |
| 888 // ModelType: it shouldn't have BookmarkSpecifics. | 889 // ModelType: it shouldn't have BookmarkSpecifics. |
| 889 SQLStatement clear_permanent_items; | 890 sqlite_utils::SQLStatement clear_permanent_items; |
| 890 clear_permanent_items.prepare(load_dbhandle_, | 891 clear_permanent_items.prepare(load_dbhandle_, |
| 891 "UPDATE metas SET specifics = NULL, server_specifics = NULL WHERE " | 892 "UPDATE metas SET specifics = NULL, server_specifics = NULL WHERE " |
| 892 "singleton_tag IN ('google_chrome')"); | 893 "singleton_tag IN ('google_chrome')"); |
| 893 if (clear_permanent_items.step() != SQLITE_DONE) | 894 if (clear_permanent_items.step() != SQLITE_DONE) |
| 894 return false; | 895 return false; |
| 895 | 896 |
| 896 SetVersion(69); | 897 SetVersion(69); |
| 897 needs_column_refresh_ = true; // Trigger deletion of old columns. | 898 needs_column_refresh_ = true; // Trigger deletion of old columns. |
| 898 return true; | 899 return true; |
| 899 } | 900 } |
| 900 | 901 |
| 901 // Version 71, the columns 'initial_sync_ended' and 'last_sync_timestamp' | 902 // Version 71, the columns 'initial_sync_ended' and 'last_sync_timestamp' |
| 902 // were removed from the share_info table. They were replaced by | 903 // were removed from the share_info table. They were replaced by |
| 903 // the 'models' table, which has these values on a per-datatype basis. | 904 // the 'models' table, which has these values on a per-datatype basis. |
| 904 bool DirectoryBackingStore::MigrateVersion70To71() { | 905 bool DirectoryBackingStore::MigrateVersion70To71() { |
| 905 if (SQLITE_DONE != CreateV71ModelsTable()) | 906 if (SQLITE_DONE != CreateV71ModelsTable()) |
| 906 return false; | 907 return false; |
| 907 | 908 |
| 908 // Move data from the old share_info columns to the new models table. | 909 // Move data from the old share_info columns to the new models table. |
| 909 { | 910 { |
| 910 SQLStatement fetch; | 911 sqlite_utils::SQLStatement fetch; |
| 911 fetch.prepare(load_dbhandle_, | 912 fetch.prepare(load_dbhandle_, |
| 912 "SELECT last_sync_timestamp, initial_sync_ended FROM share_info"); | 913 "SELECT last_sync_timestamp, initial_sync_ended FROM share_info"); |
| 913 | 914 |
| 914 if (SQLITE_ROW != fetch.step()) | 915 if (SQLITE_ROW != fetch.step()) |
| 915 return false; | 916 return false; |
| 916 int64 last_sync_timestamp = fetch.column_int64(0); | 917 int64 last_sync_timestamp = fetch.column_int64(0); |
| 917 bool initial_sync_ended = fetch.column_bool(1); | 918 bool initial_sync_ended = fetch.column_bool(1); |
| 918 if (SQLITE_DONE != fetch.step()) | 919 if (SQLITE_DONE != fetch.step()) |
| 919 return false; | 920 return false; |
| 920 SQLStatement update; | 921 sqlite_utils::SQLStatement update; |
| 921 update.prepare(load_dbhandle_, "INSERT INTO models (model_id, " | 922 update.prepare(load_dbhandle_, "INSERT INTO models (model_id, " |
| 922 "last_download_timestamp, initial_sync_ended) VALUES (?, ?, ?)"); | 923 "last_download_timestamp, initial_sync_ended) VALUES (?, ?, ?)"); |
| 923 string bookmark_model_id = ModelTypeEnumToModelId(BOOKMARKS); | 924 string bookmark_model_id = ModelTypeEnumToModelId(BOOKMARKS); |
| 924 update.bind_blob(0, bookmark_model_id.data(), bookmark_model_id.size()); | 925 update.bind_blob(0, bookmark_model_id.data(), bookmark_model_id.size()); |
| 925 update.bind_int64(1, last_sync_timestamp); | 926 update.bind_int64(1, last_sync_timestamp); |
| 926 update.bind_bool(2, initial_sync_ended); | 927 update.bind_bool(2, initial_sync_ended); |
| 927 if (SQLITE_DONE != update.step()) | 928 if (SQLITE_DONE != update.step()) |
| 928 return false; | 929 return false; |
| 929 } | 930 } |
| 930 | 931 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1032 // last_download_timestamp, thereby preserving the download state. | 1033 // last_download_timestamp, thereby preserving the download state. |
| 1033 | 1034 |
| 1034 // Move aside the old table and create a new empty one at the current schema. | 1035 // Move aside the old table and create a new empty one at the current schema. |
| 1035 if (SQLITE_DONE != ExecQuery(load_dbhandle_, | 1036 if (SQLITE_DONE != ExecQuery(load_dbhandle_, |
| 1036 "ALTER TABLE models RENAME TO temp_models")) { | 1037 "ALTER TABLE models RENAME TO temp_models")) { |
| 1037 return false; | 1038 return false; |
| 1038 } | 1039 } |
| 1039 if (!CreateModelsTable()) | 1040 if (!CreateModelsTable()) |
| 1040 return false; | 1041 return false; |
| 1041 | 1042 |
| 1042 SQLStatement query; | 1043 sqlite_utils::SQLStatement query; |
| 1043 query.prepare(load_dbhandle_, | 1044 query.prepare(load_dbhandle_, |
| 1044 "SELECT model_id, last_download_timestamp, initial_sync_ended " | 1045 "SELECT model_id, last_download_timestamp, initial_sync_ended " |
| 1045 "FROM temp_models"); | 1046 "FROM temp_models"); |
| 1046 while (SQLITE_ROW == query.step()) { | 1047 while (SQLITE_ROW == query.step()) { |
| 1047 ModelType type = ModelIdToModelTypeEnum(query.column_blob(0), | 1048 ModelType type = ModelIdToModelTypeEnum(query.column_blob(0), |
| 1048 query.column_bytes(0)); | 1049 query.column_bytes(0)); |
| 1049 if (type != UNSPECIFIED) { | 1050 if (type != UNSPECIFIED) { |
| 1050 // Set the |timestamp_token_for_migration| on a new | 1051 // Set the |timestamp_token_for_migration| on a new |
| 1051 // DataTypeProgressMarker, using the old value of last_download_timestamp. | 1052 // DataTypeProgressMarker, using the old value of last_download_timestamp. |
| 1052 // The server will turn this into a real token on our behalf the next | 1053 // The server will turn this into a real token on our behalf the next |
| 1053 // time we check for updates. | 1054 // time we check for updates. |
| 1054 sync_pb::DataTypeProgressMarker progress_marker; | 1055 sync_pb::DataTypeProgressMarker progress_marker; |
| 1055 progress_marker.set_data_type_id( | 1056 progress_marker.set_data_type_id( |
| 1056 GetExtensionFieldNumberFromModelType(type)); | 1057 GetExtensionFieldNumberFromModelType(type)); |
| 1057 progress_marker.set_timestamp_token_for_migration(query.column_int64(1)); | 1058 progress_marker.set_timestamp_token_for_migration(query.column_int64(1)); |
| 1058 std::string progress_blob; | 1059 std::string progress_blob; |
| 1059 progress_marker.SerializeToString(&progress_blob); | 1060 progress_marker.SerializeToString(&progress_blob); |
| 1060 | 1061 |
| 1061 SQLStatement update; | 1062 sqlite_utils::SQLStatement update; |
| 1062 update.prepare(load_dbhandle_, "INSERT INTO models (model_id, " | 1063 update.prepare(load_dbhandle_, "INSERT INTO models (model_id, " |
| 1063 "progress_marker, initial_sync_ended) VALUES (?, ?, ?)"); | 1064 "progress_marker, initial_sync_ended) VALUES (?, ?, ?)"); |
| 1064 update.bind_blob(0, query.column_blob(0), query.column_bytes(0)); | 1065 update.bind_blob(0, query.column_blob(0), query.column_bytes(0)); |
| 1065 update.bind_blob(1, progress_blob.data(), progress_blob.length()); | 1066 update.bind_blob(1, progress_blob.data(), progress_blob.length()); |
| 1066 update.bind_bool(2, query.column_bool(2)); | 1067 update.bind_bool(2, query.column_bool(2)); |
| 1067 if (SQLITE_DONE != update.step()) | 1068 if (SQLITE_DONE != update.step()) |
| 1068 return false; | 1069 return false; |
| 1069 } | 1070 } |
| 1070 } | 1071 } |
| 1071 // Drop the old table. | 1072 // Drop the old table. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1090 | 1091 |
| 1091 int DirectoryBackingStore::CreateTables() { | 1092 int DirectoryBackingStore::CreateTables() { |
| 1092 VLOG(1) << "First run, creating tables"; | 1093 VLOG(1) << "First run, creating tables"; |
| 1093 // Create two little tables share_version and share_info | 1094 // Create two little tables share_version and share_info |
| 1094 int result = ExecQuery(load_dbhandle_, | 1095 int result = ExecQuery(load_dbhandle_, |
| 1095 "CREATE TABLE share_version (" | 1096 "CREATE TABLE share_version (" |
| 1096 "id VARCHAR(128) primary key, data INT)"); | 1097 "id VARCHAR(128) primary key, data INT)"); |
| 1097 if (result != SQLITE_DONE) | 1098 if (result != SQLITE_DONE) |
| 1098 return result; | 1099 return result; |
| 1099 { | 1100 { |
| 1100 SQLStatement statement; | 1101 sqlite_utils::SQLStatement statement; |
| 1101 statement.prepare(load_dbhandle_, "INSERT INTO share_version VALUES(?, ?)"); | 1102 statement.prepare(load_dbhandle_, "INSERT INTO share_version VALUES(?, ?)"); |
| 1102 statement.bind_string(0, dir_name_); | 1103 statement.bind_string(0, dir_name_); |
| 1103 statement.bind_int(1, kCurrentDBVersion); | 1104 statement.bind_int(1, kCurrentDBVersion); |
| 1104 result = statement.step(); | 1105 result = statement.step(); |
| 1105 } | 1106 } |
| 1106 if (result != SQLITE_DONE) | 1107 if (result != SQLITE_DONE) |
| 1107 return result; | 1108 return result; |
| 1108 | 1109 |
| 1109 const bool kCreateAsTempShareInfo = false; | 1110 const bool kCreateAsTempShareInfo = false; |
| 1110 result = CreateShareInfoTable(kCreateAsTempShareInfo); | 1111 result = CreateShareInfoTable(kCreateAsTempShareInfo); |
| 1111 if (result != SQLITE_DONE) | 1112 if (result != SQLITE_DONE) |
| 1112 return result; | 1113 return result; |
| 1113 { | 1114 { |
| 1114 SQLStatement statement; | 1115 sqlite_utils::SQLStatement statement; |
| 1115 statement.prepare(load_dbhandle_, "INSERT INTO share_info VALUES" | 1116 statement.prepare(load_dbhandle_, "INSERT INTO share_info VALUES" |
| 1116 "(?, " // id | 1117 "(?, " // id |
| 1117 "?, " // name | 1118 "?, " // name |
| 1118 "?, " // store_birthday | 1119 "?, " // store_birthday |
| 1119 "?, " // db_create_version | 1120 "?, " // db_create_version |
| 1120 "?, " // db_create_time | 1121 "?, " // db_create_time |
| 1121 "-2, " // next_id | 1122 "-2, " // next_id |
| 1122 "?, " // cache_guid | 1123 "?, " // cache_guid |
| 1123 "?);"); // notification_state | 1124 "?);"); // notification_state |
| 1124 statement.bind_string(0, dir_name_); // id | 1125 statement.bind_string(0, dir_name_); // id |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1136 result = CreateModelsTable(); | 1137 result = CreateModelsTable(); |
| 1137 if (result != SQLITE_DONE) | 1138 if (result != SQLITE_DONE) |
| 1138 return result; | 1139 return result; |
| 1139 // Create the big metas table. | 1140 // Create the big metas table. |
| 1140 result = CreateMetasTable(false); | 1141 result = CreateMetasTable(false); |
| 1141 if (result != SQLITE_DONE) | 1142 if (result != SQLITE_DONE) |
| 1142 return result; | 1143 return result; |
| 1143 { | 1144 { |
| 1144 // Insert the entry for the root into the metas table. | 1145 // Insert the entry for the root into the metas table. |
| 1145 const int64 now = Now(); | 1146 const int64 now = Now(); |
| 1146 SQLStatement statement; | 1147 sqlite_utils::SQLStatement statement; |
| 1147 statement.prepare(load_dbhandle_, | 1148 statement.prepare(load_dbhandle_, |
| 1148 "INSERT INTO metas " | 1149 "INSERT INTO metas " |
| 1149 "( id, metahandle, is_dir, ctime, mtime) " | 1150 "( id, metahandle, is_dir, ctime, mtime) " |
| 1150 "VALUES ( \"r\", 1, 1, ?, ?)"); | 1151 "VALUES ( \"r\", 1, 1, ?, ?)"); |
| 1151 statement.bind_int64(0, now); | 1152 statement.bind_int64(0, now); |
| 1152 statement.bind_int64(1, now); | 1153 statement.bind_int64(1, now); |
| 1153 result = statement.step(); | 1154 result = statement.step(); |
| 1154 } | 1155 } |
| 1155 return result; | 1156 return result; |
| 1156 } | 1157 } |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1227 "id TEXT primary key, " | 1228 "id TEXT primary key, " |
| 1228 "name TEXT, " | 1229 "name TEXT, " |
| 1229 "store_birthday TEXT, " | 1230 "store_birthday TEXT, " |
| 1230 "db_create_version TEXT, " | 1231 "db_create_version TEXT, " |
| 1231 "db_create_time INT, " | 1232 "db_create_time INT, " |
| 1232 "next_id INT default -2, " | 1233 "next_id INT default -2, " |
| 1233 "cache_guid TEXT )"); | 1234 "cache_guid TEXT )"); |
| 1234 return ExecQuery(load_dbhandle_, query.c_str()); | 1235 return ExecQuery(load_dbhandle_, query.c_str()); |
| 1235 } | 1236 } |
| 1236 } // namespace syncable | 1237 } // namespace syncable |
| OLD | NEW |