OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 26 matching lines...) Expand all Loading... |
37 using std::string; | 37 using std::string; |
38 | 38 |
39 namespace syncable { | 39 namespace syncable { |
40 | 40 |
41 // This just has to be big enough to hold an UPDATE or INSERT statement that | 41 // This just has to be big enough to hold an UPDATE or INSERT statement that |
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 = 73; | 47 const int32 kCurrentDBVersion = 74; |
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 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(); |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 | 372 |
373 if (!DeleteEntries(snapshot.metahandles_to_purge)) | 373 if (!DeleteEntries(snapshot.metahandles_to_purge)) |
374 return false; | 374 return false; |
375 | 375 |
376 if (save_info) { | 376 if (save_info) { |
377 const Directory::PersistedKernelInfo& info = snapshot.kernel_info; | 377 const Directory::PersistedKernelInfo& info = snapshot.kernel_info; |
378 SQLStatement update; | 378 SQLStatement update; |
379 update.prepare(dbhandle, "UPDATE share_info " | 379 update.prepare(dbhandle, "UPDATE share_info " |
380 "SET store_birthday = ?, " | 380 "SET store_birthday = ?, " |
381 "next_id = ?, " | 381 "next_id = ?, " |
382 "notification_state = ?"); | 382 "notification_state = ?, " |
| 383 "autofill_migration_state = ?, " |
| 384 "bookmarks_added_during_autofill_migration = ?, " |
| 385 "autofill_migration_time = ?, " |
| 386 "autofill_entries_added_during_migration = ?, " |
| 387 "autofill_profiles_added_during_migration = ? "); |
| 388 |
| 389 const syncable::AutofillMigrationDebugInfo& debug_info = |
| 390 info.autofill_migration_debug_info; |
383 update.bind_string(0, info.store_birthday); | 391 update.bind_string(0, info.store_birthday); |
384 update.bind_int64(1, info.next_id); | 392 update.bind_int64(1, info.next_id); |
385 update.bind_blob(2, info.notification_state.data(), | 393 update.bind_blob(2, info.notification_state.data(), |
386 info.notification_state.size()); | 394 info.notification_state.size()); |
| 395 update.bind_int(3, info.autofill_migration_state); |
| 396 update.bind_int(4, |
| 397 debug_info.bookmarks_added_during_migration); |
| 398 update.bind_int64(5, |
| 399 debug_info.autofill_migration_time); |
| 400 update.bind_int(6, |
| 401 debug_info.autofill_entries_added_during_migration); |
| 402 update.bind_int(7, |
| 403 debug_info.autofill_profile_added_during_migration); |
387 | 404 |
388 if (!(SQLITE_DONE == update.step() && | 405 if (!(SQLITE_DONE == update.step() && |
389 SQLITE_OK == update.reset() && | 406 SQLITE_OK == update.reset() && |
390 1 == update.changes())) { | 407 1 == update.changes())) { |
391 return false; | 408 return false; |
392 } | 409 } |
393 | 410 |
394 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { | 411 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { |
395 SQLStatement op; | 412 SQLStatement op; |
396 op.prepare(dbhandle, "INSERT OR REPLACE INTO models (model_id, " | 413 op.prepare(dbhandle, "INSERT OR REPLACE INTO models (model_id, " |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 if (MigrateVersion71To72()) | 466 if (MigrateVersion71To72()) |
450 version_on_disk = 72; | 467 version_on_disk = 72; |
451 } | 468 } |
452 | 469 |
453 // Version 73 added a field for notification state. | 470 // Version 73 added a field for notification state. |
454 if (version_on_disk == 72) { | 471 if (version_on_disk == 72) { |
455 if (MigrateVersion72To73()) | 472 if (MigrateVersion72To73()) |
456 version_on_disk = 73; | 473 version_on_disk = 73; |
457 } | 474 } |
458 | 475 |
| 476 if (version_on_disk == 73) { |
| 477 if (MigrateVersion73To74()) |
| 478 version_on_disk = 74; |
| 479 } |
| 480 |
459 // If one of the migrations requested it, drop columns that aren't current. | 481 // If one of the migrations requested it, drop columns that aren't current. |
460 // It's only safe to do this after migrating all the way to the current | 482 // It's only safe to do this after migrating all the way to the current |
461 // version. | 483 // version. |
462 if (version_on_disk == kCurrentDBVersion && needs_column_refresh_) { | 484 if (version_on_disk == kCurrentDBVersion && needs_column_refresh_) { |
463 if (!RefreshColumns()) | 485 if (!RefreshColumns()) |
464 version_on_disk = 0; | 486 version_on_disk = 0; |
465 } | 487 } |
466 | 488 |
467 // A final, alternative catch-all migration to simply re-sync everything. | 489 // A final, alternative catch-all migration to simply re-sync everything. |
468 if (version_on_disk != kCurrentDBVersion) { | 490 if (version_on_disk != kCurrentDBVersion) { |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 entry_bucket->insert(kernel); | 571 entry_bucket->insert(kernel); |
550 } | 572 } |
551 return SQLITE_DONE == query_result; | 573 return SQLITE_DONE == query_result; |
552 } | 574 } |
553 | 575 |
554 bool DirectoryBackingStore::LoadInfo(Directory::KernelLoadInfo* info) { | 576 bool DirectoryBackingStore::LoadInfo(Directory::KernelLoadInfo* info) { |
555 { | 577 { |
556 SQLStatement query; | 578 SQLStatement query; |
557 query.prepare(load_dbhandle_, | 579 query.prepare(load_dbhandle_, |
558 "SELECT store_birthday, next_id, cache_guid, " | 580 "SELECT store_birthday, next_id, cache_guid, " |
559 "notification_state FROM share_info"); | 581 "notification_state, autofill_migration_state, " |
| 582 "bookmarks_added_during_autofill_migration, " |
| 583 "autofill_migration_time, " |
| 584 "autofill_entries_added_during_migration, " |
| 585 "autofill_profiles_added_during_migration " |
| 586 "FROM share_info"); |
560 if (SQLITE_ROW != query.step()) | 587 if (SQLITE_ROW != query.step()) |
561 return false; | 588 return false; |
562 info->kernel_info.store_birthday = query.column_string(0); | 589 info->kernel_info.store_birthday = query.column_string(0); |
563 info->kernel_info.next_id = query.column_int64(1); | 590 info->kernel_info.next_id = query.column_int64(1); |
564 info->cache_guid = query.column_string(2); | 591 info->cache_guid = query.column_string(2); |
565 query.column_blob_as_string(3, &info->kernel_info.notification_state); | 592 query.column_blob_as_string(3, &info->kernel_info.notification_state); |
| 593 info->kernel_info.autofill_migration_state = |
| 594 static_cast<AutofillMigrationState> (query.column_int(4)); |
| 595 syncable::AutofillMigrationDebugInfo& debug_info = |
| 596 info->kernel_info.autofill_migration_debug_info; |
| 597 debug_info.bookmarks_added_during_migration = |
| 598 query.column_int(5); |
| 599 debug_info.autofill_migration_time = |
| 600 query.column_int64(6); |
| 601 debug_info.autofill_entries_added_during_migration = |
| 602 query.column_int(7); |
| 603 debug_info.autofill_profile_added_during_migration = |
| 604 query.column_int(8); |
566 } | 605 } |
567 { | 606 { |
568 SQLStatement query; | 607 SQLStatement query; |
569 query.prepare(load_dbhandle_, | 608 query.prepare(load_dbhandle_, |
570 "SELECT model_id, last_download_timestamp, initial_sync_ended " | 609 "SELECT model_id, last_download_timestamp, initial_sync_ended " |
571 "FROM models"); | 610 "FROM models"); |
572 while (SQLITE_ROW == query.step()) { | 611 while (SQLITE_ROW == query.step()) { |
573 string model_id; | 612 string model_id; |
574 query.column_blob_as_string(0, &model_id); | 613 query.column_blob_as_string(0, &model_id); |
575 ModelType type = ModelIdToModelTypeEnum(model_id); | 614 ModelType type = ModelIdToModelTypeEnum(model_id); |
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
882 string bookmark_model_id = ModelTypeEnumToModelId(BOOKMARKS); | 921 string bookmark_model_id = ModelTypeEnumToModelId(BOOKMARKS); |
883 update.bind_blob(0, bookmark_model_id.data(), bookmark_model_id.size()); | 922 update.bind_blob(0, bookmark_model_id.data(), bookmark_model_id.size()); |
884 update.bind_int64(1, last_sync_timestamp); | 923 update.bind_int64(1, last_sync_timestamp); |
885 update.bind_bool(2, initial_sync_ended); | 924 update.bind_bool(2, initial_sync_ended); |
886 if (SQLITE_DONE != update.step()) | 925 if (SQLITE_DONE != update.step()) |
887 return false; | 926 return false; |
888 } | 927 } |
889 | 928 |
890 // Drop the columns from the old share_info table via a temp table. | 929 // Drop the columns from the old share_info table via a temp table. |
891 const bool kCreateAsTempShareInfo = true; | 930 const bool kCreateAsTempShareInfo = true; |
892 const bool kWithNotificationState = false; | 931 |
893 int result = | 932 int result = |
894 CreateShareInfoTable(kCreateAsTempShareInfo, kWithNotificationState); | 933 CreateShareInfoTableVersion71(kCreateAsTempShareInfo); |
895 if (result != SQLITE_DONE) | 934 if (result != SQLITE_DONE) |
896 return false; | 935 return false; |
897 ExecQuery(load_dbhandle_, | 936 ExecQuery(load_dbhandle_, |
898 "INSERT INTO temp_share_info (id, name, store_birthday, " | 937 "INSERT INTO temp_share_info (id, name, store_birthday, " |
899 "db_create_version, db_create_time, next_id, cache_guid) " | 938 "db_create_version, db_create_time, next_id, cache_guid) " |
900 "SELECT id, name, store_birthday, db_create_version, " | 939 "SELECT id, name, store_birthday, db_create_version, " |
901 "db_create_time, next_id, cache_guid FROM share_info"); | 940 "db_create_time, next_id, cache_guid FROM share_info"); |
902 if (result != SQLITE_DONE) | 941 if (result != SQLITE_DONE) |
903 return false; | 942 return false; |
904 SafeDropTable("share_info"); | 943 SafeDropTable("share_info"); |
(...skipping 14 matching lines...) Expand all Loading... |
919 bool DirectoryBackingStore::MigrateVersion72To73() { | 958 bool DirectoryBackingStore::MigrateVersion72To73() { |
920 int result = | 959 int result = |
921 ExecQuery(load_dbhandle_, | 960 ExecQuery(load_dbhandle_, |
922 "ALTER TABLE share_info ADD COLUMN notification_state BLOB"); | 961 "ALTER TABLE share_info ADD COLUMN notification_state BLOB"); |
923 if (result != SQLITE_DONE) | 962 if (result != SQLITE_DONE) |
924 return false; | 963 return false; |
925 SetVersion(73); | 964 SetVersion(73); |
926 return true; | 965 return true; |
927 } | 966 } |
928 | 967 |
| 968 bool DirectoryBackingStore::MigrateVersion73To74() { |
| 969 int result = |
| 970 ExecQuery(load_dbhandle_, |
| 971 "ALTER TABLE share_info ADD COLUMN autofill_migration_state " |
| 972 "INT default 0"); |
| 973 if (result != SQLITE_DONE) |
| 974 return false; |
| 975 |
| 976 result = ExecQuery(load_dbhandle_, |
| 977 "ALTER TABLE share_info ADD COLUMN " |
| 978 "bookmarks_added_during_autofill_migration " |
| 979 "INT default 0"); |
| 980 |
| 981 if (result != SQLITE_DONE) |
| 982 return false; |
| 983 |
| 984 result = ExecQuery(load_dbhandle_, |
| 985 "ALTER TABLE share_info ADD COLUMN autofill_migration_time " |
| 986 "INT default 0"); |
| 987 |
| 988 if (result != SQLITE_DONE) |
| 989 return false; |
| 990 |
| 991 result = ExecQuery(load_dbhandle_, |
| 992 "ALTER TABLE share_info ADD COLUMN " |
| 993 "autofill_entries_added_during_migration " |
| 994 "INT default 0"); |
| 995 |
| 996 if (result != SQLITE_DONE) |
| 997 return false; |
| 998 |
| 999 result = ExecQuery(load_dbhandle_, |
| 1000 "ALTER TABLE share_info ADD COLUMN " |
| 1001 "autofill_profiles_added_during_migration " |
| 1002 "INT default 0"); |
| 1003 |
| 1004 if (result != SQLITE_DONE) |
| 1005 return false; |
| 1006 |
| 1007 SetVersion(74); |
| 1008 return true; |
| 1009 } |
| 1010 |
| 1011 |
929 int DirectoryBackingStore::CreateTables() { | 1012 int DirectoryBackingStore::CreateTables() { |
930 VLOG(1) << "First run, creating tables"; | 1013 VLOG(1) << "First run, creating tables"; |
931 // Create two little tables share_version and share_info | 1014 // Create two little tables share_version and share_info |
932 int result = ExecQuery(load_dbhandle_, | 1015 int result = ExecQuery(load_dbhandle_, |
933 "CREATE TABLE share_version (" | 1016 "CREATE TABLE share_version (" |
934 "id VARCHAR(128) primary key, data INT)"); | 1017 "id VARCHAR(128) primary key, data INT)"); |
935 if (result != SQLITE_DONE) | 1018 if (result != SQLITE_DONE) |
936 return result; | 1019 return result; |
937 { | 1020 { |
938 SQLStatement statement; | 1021 SQLStatement statement; |
939 statement.prepare(load_dbhandle_, "INSERT INTO share_version VALUES(?, ?)"); | 1022 statement.prepare(load_dbhandle_, "INSERT INTO share_version VALUES(?, ?)"); |
940 statement.bind_string(0, dir_name_); | 1023 statement.bind_string(0, dir_name_); |
941 statement.bind_int(1, kCurrentDBVersion); | 1024 statement.bind_int(1, kCurrentDBVersion); |
942 result = statement.step(); | 1025 result = statement.step(); |
943 } | 1026 } |
944 if (result != SQLITE_DONE) | 1027 if (result != SQLITE_DONE) |
945 return result; | 1028 return result; |
946 | 1029 |
947 const bool kCreateAsTempShareInfo = false; | 1030 const bool kCreateAsTempShareInfo = false; |
948 const bool kWithNotificationState = true; | |
949 result = | 1031 result = |
950 CreateShareInfoTable(kCreateAsTempShareInfo, kWithNotificationState); | 1032 CreateShareInfoTable(kCreateAsTempShareInfo); |
951 if (result != SQLITE_DONE) | 1033 if (result != SQLITE_DONE) |
952 return result; | 1034 return result; |
953 { | 1035 { |
954 SQLStatement statement; | 1036 SQLStatement statement; |
955 statement.prepare(load_dbhandle_, "INSERT INTO share_info VALUES" | 1037 statement.prepare(load_dbhandle_, "INSERT INTO share_info VALUES" |
956 "(?, " // id | 1038 "(?, " // id |
957 "?, " // name | 1039 "?, " // name |
958 "?, " // store_birthday | 1040 "?, " // store_birthday |
959 "?, " // db_create_version | 1041 "?, " // db_create_version |
960 "?, " // db_create_time | 1042 "?, " // db_create_time |
961 "-2, " // next_id | 1043 "-2, " // next_id |
962 "?, " // cache_guid | 1044 "?, " // cache_guid |
| 1045 "?, " // autofill_migration_state |
| 1046 "?, " // bookmarks_added |
| 1047 // _during_autofill_migration |
| 1048 "?, " // autofill_migration_time |
| 1049 "?, " // autofill_entries |
| 1050 // _added_during_migration |
| 1051 "?, " // autofill_profiles_added |
| 1052 // _during_migration |
963 "?);"); // notification_state | 1053 "?);"); // notification_state |
964 statement.bind_string(0, dir_name_); // id | 1054 statement.bind_string(0, dir_name_); // id |
965 statement.bind_string(1, dir_name_); // name | 1055 statement.bind_string(1, dir_name_); // name |
966 statement.bind_string(2, ""); // store_birthday | 1056 statement.bind_string(2, ""); // store_birthday |
967 statement.bind_string(3, SYNC_ENGINE_VERSION_STRING); // db_create_version | 1057 statement.bind_string(3, SYNC_ENGINE_VERSION_STRING); // db_create_version |
968 statement.bind_int(4, static_cast<int32>(time(0))); // db_create_time | 1058 statement.bind_int(4, static_cast<int32>(time(0))); // db_create_time |
969 statement.bind_string(5, GenerateCacheGUID()); // cache_guid | 1059 statement.bind_string(5, GenerateCacheGUID()); // cache_guid |
970 statement.bind_blob(6, NULL, 0); // notification_state | 1060 statement.bind_int(6, 0); // autofill_migration_state |
| 1061 statement.bind_int(7, 0); // autofill_migration_time |
| 1062 statement.bind_int(8, 0); // bookmarks_added_during_autofill_migration |
| 1063 statement.bind_int(9, 0); // autofill_entries_added_during_migration |
| 1064 statement.bind_int(10, 0); // autofill_profiles_added_during_migration |
| 1065 statement.bind_blob(11, NULL, 0); // notification_state |
971 result = statement.step(); | 1066 result = statement.step(); |
972 } | 1067 } |
973 if (result != SQLITE_DONE) | 1068 if (result != SQLITE_DONE) |
974 return result; | 1069 return result; |
975 | 1070 |
976 result = CreateModelsTable(); | 1071 result = CreateModelsTable(); |
977 if (result != SQLITE_DONE) | 1072 if (result != SQLITE_DONE) |
978 return result; | 1073 return result; |
979 // Create the big metas table. | 1074 // Create the big metas table. |
980 result = CreateMetasTable(false); | 1075 result = CreateMetasTable(false); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1018 return ExecQuery(load_dbhandle_, | 1113 return ExecQuery(load_dbhandle_, |
1019 "CREATE TABLE models (" | 1114 "CREATE TABLE models (" |
1020 "model_id BLOB primary key, " | 1115 "model_id BLOB primary key, " |
1021 "last_download_timestamp INT, " | 1116 "last_download_timestamp INT, " |
1022 // Gets set if the syncer ever gets updates from the | 1117 // Gets set if the syncer ever gets updates from the |
1023 // server and the server returns 0. Lets us detect the | 1118 // server and the server returns 0. Lets us detect the |
1024 // end of the initial sync. | 1119 // end of the initial sync. |
1025 "initial_sync_ended BOOLEAN default 0)"); | 1120 "initial_sync_ended BOOLEAN default 0)"); |
1026 } | 1121 } |
1027 | 1122 |
1028 int DirectoryBackingStore::CreateShareInfoTable( | 1123 int DirectoryBackingStore::CreateShareInfoTable(bool is_temporary) { |
1029 bool is_temporary, bool with_notification_state) { | |
1030 const char* name = is_temporary ? "temp_share_info" : "share_info"; | 1124 const char* name = is_temporary ? "temp_share_info" : "share_info"; |
1031 string query = "CREATE TABLE "; | 1125 string query = "CREATE TABLE "; |
1032 query.append(name); | 1126 query.append(name); |
1033 // This is the current schema for the ShareInfo table, from version 71 | 1127 // This is the current schema for the ShareInfo table, from version 71 |
1034 // onward. If you change the schema, you'll probably want to double-check | 1128 // onward. If you change the schema, you'll probably want to double-check |
1035 // the use of this function in the v70-v71 migration. | 1129 // the use of this function in the v70-v71 migration. |
1036 query.append(" (" | 1130 query.append(" (" |
1037 "id TEXT primary key, " | 1131 "id TEXT primary key, " |
1038 "name TEXT, " | 1132 "name TEXT, " |
1039 "store_birthday TEXT, " | 1133 "store_birthday TEXT, " |
1040 "db_create_version TEXT, " | 1134 "db_create_version TEXT, " |
1041 "db_create_time INT, " | 1135 "db_create_time INT, " |
1042 "next_id INT default -2, " | 1136 "next_id INT default -2, " |
1043 "cache_guid TEXT"); | 1137 "cache_guid TEXT, " |
1044 if (with_notification_state) { | 1138 "autofill_migration_state INT default 0, " |
1045 query.append(", notification_state BLOB"); | 1139 "bookmarks_added_during_autofill_migration INT default 0, " |
1046 } | 1140 "autofill_migration_time INT default 0, " |
| 1141 "autofill_entries_added_during_migration INT default 0, " |
| 1142 "autofill_profiles_added_during_migration INT default 0 "); |
| 1143 |
| 1144 query.append(", notification_state BLOB"); |
1047 query.append(")"); | 1145 query.append(")"); |
1048 return ExecQuery(load_dbhandle_, query.c_str()); | 1146 return ExecQuery(load_dbhandle_, query.c_str()); |
1049 } | 1147 } |
1050 | 1148 |
| 1149 int DirectoryBackingStore::CreateShareInfoTableVersion71( |
| 1150 bool is_temporary) { |
| 1151 const char* name = is_temporary ? "temp_share_info" : "share_info"; |
| 1152 string query = "CREATE TABLE "; |
| 1153 query.append(name); |
| 1154 // This is the current schema for the ShareInfo table, from version 71 |
| 1155 // onward. If you change the schema, you'll probably want to double-check |
| 1156 // the use of this function in the v70-v71 migration. |
| 1157 query.append(" (" |
| 1158 "id TEXT primary key, " |
| 1159 "name TEXT, " |
| 1160 "store_birthday TEXT, " |
| 1161 "db_create_version TEXT, " |
| 1162 "db_create_time INT, " |
| 1163 "next_id INT default -2, " |
| 1164 "cache_guid TEXT )"); |
| 1165 return ExecQuery(load_dbhandle_, query.c_str()); |
| 1166 } |
1051 } // namespace syncable | 1167 } // namespace syncable |
OLD | NEW |