12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/directory_backing_store.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base64.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/connection.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/statement.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/transaction.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/base/node_ordinal.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/protocol/bookmark_specifics.pb.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/protocol/sync.pb.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/syncable-inl.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/syncable_columns.h" 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "sync/syncable/syncable_util.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/util/time.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::string; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncer { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncable { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This just has to be big enough to hold an UPDATE or INSERT statement that 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modifies all the columns in the entry table. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const string::size_type kUpdateStatementBufferSize = 2048; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Increment this version whenever updating DB tables. 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int32 kCurrentDBVersion = 86; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Iterate over the fields of |entry| and bind each to |statement| for 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// updating. Returns the number of args bound. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BindFields(const EntryKernel& entry, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement* statement) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = 0; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i = 0; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement->BindInt64(index++, entry.ref(static_cast<Int64Field>(i))); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for ( ; i < TIME_FIELDS_END; ++i) { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement->BindInt64(index++, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeToProtoTime( 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry.ref(static_cast<TimeField>(i)))); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for ( ; i < ID_FIELDS_END; ++i) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement->BindString(index++, entry.ref(static_cast<IdField>(i)).s_); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for ( ; i < BIT_FIELDS_END; ++i) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement->BindInt(index++, entry.ref(static_cast<BitField>(i))); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for ( ; i < STRING_FIELDS_END; ++i) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement->BindString(index++, entry.ref(static_cast<StringField>(i))); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for ( ; i < PROTO_FIELDS_END; ++i) { 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string temp; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry.ref(static_cast<ProtoField>(i)).SerializeToString(&temp); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement->BindBlob(index++, temp.data(), temp.length()); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for ( ; i < UNIQUE_POSITION_FIELDS_END; ++i) { 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string temp; 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) entry.ref(static_cast<UniquePositionField>(i)).SerializeToString(&temp); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement->BindBlob(index++, temp.data(), temp.length()); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The caller owns the returned EntryKernel*. Assumes the statement currently 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// points to a valid row in the metas table. Returns NULL to indicate that 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it detected a corruption in the data on unpacking. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<EntryKernel> UnpackEntry(sql::Statement* statement) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<EntryKernel> kernel(new EntryKernel()); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(statement->ColumnCount(), static_cast<int>(FIELD_COUNT)); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i = 0; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel->put(static_cast<Int64Field>(i), statement->ColumnInt64(i)); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for ( ; i < TIME_FIELDS_END; ++i) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel->put(static_cast<TimeField>(i), 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProtoTimeToTime(statement->ColumnInt64(i))); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for ( ; i < ID_FIELDS_END; ++i) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel->mutable_ref(static_cast<IdField>(i)).s_ = 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement->ColumnString(i); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for ( ; i < BIT_FIELDS_END; ++i) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel->put(static_cast<BitField>(i), (0 != statement->ColumnInt(i))); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for ( ; i < STRING_FIELDS_END; ++i) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel->put(static_cast<StringField>(i), 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement->ColumnString(i)); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for ( ; i < PROTO_FIELDS_END; ++i) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel->mutable_ref(static_cast<ProtoField>(i)).ParseFromArray( 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement->ColumnBlob(i), statement->ColumnByteLength(i)); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for ( ; i < UNIQUE_POSITION_FIELDS_END; ++i) { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string temp; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement->ColumnBlobAsString(i, &temp); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sync_pb::UniquePosition proto; 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!proto.ParseFromString(temp)) { 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DVLOG(1) << "Unpacked invalid position. Assuming the DB is corrupt"; 1117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return scoped_ptr<EntryKernel>(); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kernel->mutable_ref(static_cast<UniquePositionField>(i)) = 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UniquePosition::FromProto(proto); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kernel.Pass(); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string ComposeCreateTableColumnSpecs() { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ColumnSpec* begin = g_metas_columns; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ColumnSpec* end = g_metas_columns + arraysize(g_metas_columns); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string query; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query.reserve(kUpdateStatementBufferSize); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char separator = '('; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (const ColumnSpec* column = begin; column != end; ++column) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query.push_back(separator); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) separator = ','; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query.append(column->name); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query.push_back(' '); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query.append(column->spec); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query.push_back(')'); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return query; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppendColumnList(std::string* output) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* joiner = " "; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Be explicit in SELECT order to match up with UnpackEntry. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = BEGIN_FIELDS; i < FIELD_COUNT; ++i) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->append(joiner); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->append(ColumnName(i)); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) joiner = ", "; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DirectoryBackingStore implementation. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DirectoryBackingStore::DirectoryBackingStore(const string& dir_name) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : db_(new sql::Connection()), 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dir_name_(dir_name), 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) needs_column_refresh_(false) { 1587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) db_->set_histogram_tag("SyncDirectory"); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DirectoryBackingStore::DirectoryBackingStore(const string& dir_name, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Connection* db) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : db_(db), 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dir_name_(dir_name), 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) needs_column_refresh_(false) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DirectoryBackingStore::~DirectoryBackingStore() { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DirectoryBackingStore::DeleteEntries(EntryTable from, 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const MetahandleSet& handles) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (handles.empty()) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sql::Statement statement; 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Call GetCachedStatement() separately to get different statements for 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // different tables. 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (from) { 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case METAS_TABLE: 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement.Assign(db_->GetCachedStatement( 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SQL_FROM_HERE, "DELETE FROM metas WHERE metahandle = ?")); 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case DELETE_JOURNAL_TABLE: 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) statement.Assign(db_->GetCachedStatement( 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SQL_FROM_HERE, "DELETE FROM deleted_metas WHERE metahandle = ?")); 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (MetahandleSet::const_iterator i = handles.begin(); i != handles.end(); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i) { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.BindInt64(0, *i); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!statement.Run()) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) statement.Reset(true); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::SaveChanges( 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Directory::SaveChangesSnapshot& snapshot) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(CalledOnValidThread()); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(db_->is_open()); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Back out early if there is nothing to write. 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool save_info = 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (Directory::KERNEL_SHARE_INFO_DIRTY == snapshot.kernel_info_status); 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (snapshot.dirty_metas.empty() && snapshot.metahandles_to_purge.empty() && 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) snapshot.delete_journals.empty() && 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) snapshot.delete_journals_to_purge.empty() && !save_info) { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Transaction transaction(db_.get()); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!transaction.Begin()) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PrepareSaveEntryStatement(METAS_TABLE, &save_meta_statment_); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (EntryKernelSet::const_iterator i = snapshot.dirty_metas.begin(); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != snapshot.dirty_metas.end(); ++i) { 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK((*i)->is_dirty()); 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!SaveEntryToDB(&save_meta_statment_, **i)) 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!DeleteEntries(METAS_TABLE, snapshot.metahandles_to_purge)) 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PrepareSaveEntryStatement(DELETE_JOURNAL_TABLE, 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &save_delete_journal_statment_); 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (EntryKernelSet::const_iterator i = snapshot.delete_journals.begin(); 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i != snapshot.delete_journals.end(); ++i) { 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!SaveEntryToDB(&save_delete_journal_statment_, **i)) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!DeleteEntries(DELETE_JOURNAL_TABLE, snapshot.delete_journals_to_purge)) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (save_info) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Directory::PersistedKernelInfo& info = snapshot.kernel_info; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s1(db_->GetCachedStatement( 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SQL_FROM_HERE, 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "UPDATE share_info " 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SET store_birthday = ?, " 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "next_id = ?, " 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "bag_of_chips = ?")); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s1.BindString(0, info.store_birthday); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s1.BindInt64(1, info.next_id); 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) s1.BindBlob(2, info.bag_of_chips.data(), info.bag_of_chips.size()); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!s1.Run()) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(db_->GetLastChangeCount(), 1); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s2(db_->GetCachedStatement( 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SQL_FROM_HERE, 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "INSERT OR REPLACE " 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "INTO models (model_id, progress_marker, transaction_version) " 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "VALUES (?, ?, ?)")); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ModelTypeSet protocol_types = ProtocolTypes(); 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good(); 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter.Inc()) { 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ModelType type = iter.Get(); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We persist not ModelType but rather a protobuf-derived ID. 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) string model_id = ModelTypeEnumToModelId(type); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string progress_marker; 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info.download_progress[type].SerializeToString(&progress_marker); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s2.BindBlob(0, model_id.data(), model_id.length()); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s2.BindBlob(1, progress_marker.data(), progress_marker.length()); 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) s2.BindInt64(2, info.transaction_version[type]); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!s2.Run()) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(db_->GetLastChangeCount(), 1); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s2.Reset(true); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transaction.Commit(); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::InitializeTables() { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Transaction transaction(db_.get()); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!transaction.Begin()) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int version_on_disk = GetVersion(); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Upgrade from version 67. Version 67 was widely distributed as the original 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Bookmark Sync release. Version 68 removed unique naming. 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk == 67) { 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MigrateVersion67To68()) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_on_disk = 68; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 69 introduced additional datatypes. 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk == 68) { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MigrateVersion68To69()) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_on_disk = 69; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk == 69) { 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MigrateVersion69To70()) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_on_disk = 70; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 71 changed the sync progress information to be per-datatype. 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk == 70) { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MigrateVersion70To71()) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_on_disk = 71; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 72 removed extended attributes, a legacy way to do extensible 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // key/value information, stored in their own table. 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk == 71) { 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MigrateVersion71To72()) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_on_disk = 72; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 73 added a field for notification state. 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk == 72) { 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MigrateVersion72To73()) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_on_disk = 73; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 74 added state for the autofill migration. 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk == 73) { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MigrateVersion73To74()) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_on_disk = 74; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 75 migrated from int64-based timestamps to per-datatype tokens. 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk == 74) { 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MigrateVersion74To75()) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_on_disk = 75; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 76 removed all (5) autofill migration related columns. 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk == 75) { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MigrateVersion75To76()) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_on_disk = 76; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 77 standardized all time fields to ms since the Unix 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // epoch. 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk == 76) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MigrateVersion76To77()) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_on_disk = 77; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 78 added the column base_server_specifics to the metas table. 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk == 77) { 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MigrateVersion77To78()) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_on_disk = 78; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 79 migration is a one-time fix for some users in a bad state. 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk == 78) { 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MigrateVersion78To79()) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_on_disk = 79; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 80 migration is adding the bag_of_chips column. 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk == 79) { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MigrateVersion79To80()) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_on_disk = 80; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 81 replaces the int64 server_position_in_parent_field 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with a blob server_ordinal_in_parent field. 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk == 80) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MigrateVersion80To81()) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_on_disk = 81; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 82 migration added transaction_version column per data type. 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk == 81) { 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MigrateVersion81To82()) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_on_disk = 82; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 83 migration added transaction_version column per sync entry. 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk == 82) { 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MigrateVersion82To83()) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_on_disk = 83; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Version 84 migration added deleted_metas table. 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (version_on_disk == 83) { 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (MigrateVersion83To84()) 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) version_on_disk = 84; 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Version 85 migration removes the initial_sync_ended bits. 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (version_on_disk == 84) { 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (MigrateVersion84To85()) 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) version_on_disk = 85; 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Version 86 migration converts bookmarks to the unique positioning system. 401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // It also introduces a new field to store a unique ID for each bookmark. 402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (version_on_disk == 85) { 403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (MigrateVersion85To86()) 404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) version_on_disk = 86; 405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If one of the migrations requested it, drop columns that aren't current. 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It's only safe to do this after migrating all the way to the current 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // version. 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk == kCurrentDBVersion && needs_column_refresh_) { 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RefreshColumns()) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_on_disk = 0; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A final, alternative catch-all migration to simply re-sync everything. 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk != kCurrentDBVersion) { 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_on_disk > kCurrentDBVersion) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fallback (re-sync everything) migration path. 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Old/null sync database, version " << version_on_disk; 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete the existing database (if any), and create a fresh one. 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DropAllTables(); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreateTables()) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db_->GetUniqueStatement( 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT db_create_version, db_create_time FROM share_info")); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!s.Step()) 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string db_create_version = s.ColumnString(0); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int db_create_time = s.ColumnInt(1); 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "DB created at " << db_create_time << " by version " << 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_create_version; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transaction.Commit(); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function drops unused columns by creating a new table that contains only 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the currently used columns then copying all rows from the old tables into 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this new one. The tables are then rearranged so the new replaces the old. 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::RefreshColumns() { 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(needs_column_refresh_); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a new table named temp_metas. 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SafeDropTable("temp_metas"); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreateMetasTable(true)) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Populate temp_metas from metas. 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // At this point, the metas table may contain columns belonging to obsolete 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // schema versions. This statement explicitly lists only the columns that 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // belong to the current schema version, so the obsolete columns will be 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // effectively dropped once we rename temp_metas over top of metas. 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string query = "INSERT INTO temp_metas ("; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AppendColumnList(&query); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query.append(") SELECT "); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AppendColumnList(&query); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query.append(" FROM metas"); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute(query.c_str())) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Drop metas. 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SafeDropTable("metas"); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Rename temp_metas -> metas. 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute("ALTER TABLE temp_metas RENAME TO metas")) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Repeat the process for share_info. 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SafeDropTable("temp_share_info"); 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreateShareInfoTable(true)) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(rlarocque, 124140): Remove notification_state. 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "INSERT INTO temp_share_info (id, name, store_birthday, " 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "db_create_version, db_create_time, next_id, cache_guid," 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "notification_state, bag_of_chips) " 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT id, name, store_birthday, db_create_version, " 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "db_create_time, next_id, cache_guid, notification_state, " 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "bag_of_chips " 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "FROM share_info")) 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SafeDropTable("share_info"); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute("ALTER TABLE temp_share_info RENAME TO share_info")) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) needs_column_refresh_ = false; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool DirectoryBackingStore::LoadEntries( 497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Directory::MetahandlesMap* handles_map) { 498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) string select; 499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) select.reserve(kUpdateStatementBufferSize); 500868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) select.append("SELECT "); 501868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AppendColumnList(&select); 502868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) select.append(" FROM metas"); 503868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 504868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) sql::Statement s(db_->GetUniqueStatement(select.c_str())); 505868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) while (s.Step()) { 507868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<EntryKernel> kernel = UnpackEntry(&s); 508868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // A null kernel is evidence of external data corruption. 509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!kernel) 510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int64 handle = kernel->ref(META_HANDLE); 513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) (*handles_map)[handle] = kernel.release(); 514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return s.Succeeded(); 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DirectoryBackingStore::LoadDeleteJournals( 5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) JournalIndex* delete_journals) { 520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) string select; 521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) select.reserve(kUpdateStatementBufferSize); 522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) select.append("SELECT "); 523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AppendColumnList(&select); 524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) select.append(" FROM deleted_metas"); 525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) sql::Statement s(db_->GetUniqueStatement(select.c_str())); 527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) while (s.Step()) { 529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<EntryKernel> kernel = UnpackEntry(&s); 530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // A null kernel is evidence of external data corruption. 531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!kernel) 532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) delete_journals->insert(kernel.release()); 534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return s.Succeeded(); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::LoadInfo(Directory::KernelLoadInfo* info) { 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s( 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetUniqueStatement( 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "SELECT store_birthday, next_id, cache_guid, bag_of_chips " 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "FROM share_info")); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!s.Step()) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->kernel_info.store_birthday = s.ColumnString(0); 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->kernel_info.next_id = s.ColumnInt64(1); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->cache_guid = s.ColumnString(2); 5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) s.ColumnBlobAsString(3, &(info->kernel_info.bag_of_chips)); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify there was only one row returned. 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!s.Step()); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(s.Succeeded()); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s( 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetUniqueStatement( 5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "SELECT model_id, progress_marker, " 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "transaction_version FROM models")); 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (s.Step()) { 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelType type = ModelIdToModelTypeEnum(s.ColumnBlob(0), 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.ColumnByteLength(0)); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type != UNSPECIFIED && type != TOP_LEVEL_FOLDER) { 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->kernel_info.download_progress[type].ParseFromArray( 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.ColumnBlob(1), s.ColumnByteLength(1)); 5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info->kernel_info.transaction_version[type] = s.ColumnInt64(2); 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!s.Succeeded()) 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s( 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_->GetUniqueStatement( 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT MAX(metahandle) FROM metas")); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!s.Step()) 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->max_metahandle = s.ColumnInt64(0); 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify only one row was returned. 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!s.Step()); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(s.Succeeded()); 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* static */ 5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DirectoryBackingStore::SaveEntryToDB(sql::Statement* save_statement, 5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const EntryKernel& entry) { 5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) save_statement->Reset(true); 5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BindFields(entry, save_statement); 5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return save_statement->Run(); 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::DropDeletedEntries() { 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute("DELETE FROM metas " 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE is_del > 0 " 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND is_unsynced < 1 " 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND is_unapplied_update < 1")) { 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute("DELETE FROM metas " 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE is_del > 0 " 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AND id LIKE 'c%'")) { 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::SafeDropTable(const char* table_name) { 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string query = "DROP TABLE IF EXISTS "; 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query.append(table_name); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->Execute(query.c_str()); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DirectoryBackingStore::DropAllTables() { 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SafeDropTable("metas"); 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SafeDropTable("temp_metas"); 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SafeDropTable("share_info"); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SafeDropTable("temp_share_info"); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SafeDropTable("share_version"); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SafeDropTable("extended_attributes"); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SafeDropTable("models"); 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SafeDropTable("temp_models"); 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) needs_column_refresh_ = false; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ModelType DirectoryBackingStore::ModelIdToModelTypeEnum( 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* data, int size) { 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_pb::EntitySpecifics specifics; 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!specifics.ParseFromArray(data, size)) 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return UNSPECIFIED; 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetModelTypeFromSpecifics(specifics); 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string DirectoryBackingStore::ModelTypeEnumToModelId(ModelType model_type) { 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_pb::EntitySpecifics specifics; 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddDefaultFieldValue(model_type, &specifics); 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return specifics.SerializeAsString(); 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string DirectoryBackingStore::GenerateCacheGUID() { 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Generate a GUID with 128 bits of randomness. 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kGuidBytes = 128 / 8; 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string guid; 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Base64Encode(base::RandBytesAsString(kGuidBytes), &guid); 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return guid; 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::MigrateToSpecifics( 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* old_columns, 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* specifics_column, 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void (*handler_function)(sql::Statement* old_value_query, 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int old_value_column, 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_pb::EntitySpecifics* mutable_new_value)) { 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string query_sql = base::StringPrintf( 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT metahandle, %s, %s FROM metas", specifics_column, old_columns); 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string update_sql = base::StringPrintf( 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "UPDATE metas SET %s = ? WHERE metahandle = ?", specifics_column); 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement query(db_->GetUniqueStatement(query_sql.c_str())); 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement update(db_->GetUniqueStatement(update_sql.c_str())); 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (query.Step()) { 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 metahandle = query.ColumnInt64(0); 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string new_value_bytes; 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query.ColumnBlobAsString(1, &new_value_bytes); 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_pb::EntitySpecifics new_value; 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_value.ParseFromString(new_value_bytes); 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handler_function(&query, 2, &new_value); 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_value.SerializeToString(&new_value_bytes); 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update.BindBlob(0, new_value_bytes.data(), new_value_bytes.length()); 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update.BindInt64(1, metahandle); 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!update.Run()) 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update.Reset(true); 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return query.Succeeded(); 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::SetVersion(int version) { 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db_->GetCachedStatement( 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SQL_FROM_HERE, "UPDATE share_version SET data = ?")); 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindInt(0, version); 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return s.Run(); 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int DirectoryBackingStore::GetVersion() { 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->DoesTableExist("share_version")) 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement statement(db_->GetUniqueStatement( 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT data FROM share_version")); 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (statement.Step()) { 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return statement.ColumnInt(0); 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::MigrateVersion67To68() { 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This change simply removed three columns: 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // string NAME 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // string UNSANITIZED_NAME 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // string SERVER_NAME 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No data migration is necessary, but we should do a column refresh. 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVersion(68); 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) needs_column_refresh_ = true; 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::MigrateVersion69To70() { 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Added "unique_client_tag", renamed "singleton_tag" to unique_server_tag 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVersion(70); 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ALTER TABLE metas ADD COLUMN unique_server_tag varchar")) 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ALTER TABLE metas ADD COLUMN unique_client_tag varchar")) 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) needs_column_refresh_ = true; 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "UPDATE metas SET unique_server_tag = singleton_tag")) 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Callback passed to MigrateToSpecifics for the v68->v69 migration. See 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MigrateVersion68To69(). 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EncodeBookmarkURLAndFavicon(sql::Statement* old_value_query, 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int old_value_column, 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_pb::EntitySpecifics* mutable_new_value) { 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Extract data from the column trio we expect. 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool old_is_bookmark_object = old_value_query->ColumnBool(old_value_column); 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string old_url = old_value_query->ColumnString(old_value_column + 1); 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string old_favicon; 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_value_query->ColumnBlobAsString(old_value_column + 2, &old_favicon); 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool old_is_dir = old_value_query->ColumnBool(old_value_column + 3); 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_is_bookmark_object) { 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_pb::BookmarkSpecifics* bookmark_data = 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable_new_value->mutable_bookmark(); 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!old_is_dir) { 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_data->set_url(old_url); 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bookmark_data->set_favicon(old_favicon); 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::MigrateVersion68To69() { 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In Version 68, there were columns on table 'metas': 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // string BOOKMARK_URL 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // string SERVER_BOOKMARK_URL 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // blob BOOKMARK_FAVICON 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // blob SERVER_BOOKMARK_FAVICON 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In version 69, these columns went away in favor of storing 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a serialized EntrySpecifics protobuf in the columns: 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // protobuf blob SPECIFICS 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // protobuf blob SERVER_SPECIFICS 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For bookmarks, EntrySpecifics is extended as per 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bookmark_specifics.proto. This migration converts bookmarks from the 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // former scheme to the latter scheme. 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First, add the two new columns to the schema. 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ALTER TABLE metas ADD COLUMN specifics blob")) 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ALTER TABLE metas ADD COLUMN server_specifics blob")) 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Next, fold data from the old columns into the new protobuf columns. 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!MigrateToSpecifics(("is_bookmark_object, bookmark_url, " 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "bookmark_favicon, is_dir"), 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "specifics", 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &EncodeBookmarkURLAndFavicon)) { 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!MigrateToSpecifics(("server_is_bookmark_object, " 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "server_bookmark_url, " 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "server_bookmark_favicon, " 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "server_is_dir"), 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "server_specifics", 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &EncodeBookmarkURLAndFavicon)) { 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Lastly, fix up the "Google Chrome" folder, which is of the TOP_LEVEL_FOLDER 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ModelType: it shouldn't have BookmarkSpecifics. 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "UPDATE metas SET specifics = NULL, server_specifics = NULL WHERE " 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "singleton_tag IN ('google_chrome')")) 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVersion(69); 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) needs_column_refresh_ = true; // Trigger deletion of old columns. 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Version 71, the columns 'initial_sync_ended' and 'last_sync_timestamp' 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// were removed from the share_info table. They were replaced by 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the 'models' table, which has these values on a per-datatype basis. 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::MigrateVersion70To71() { 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreateV71ModelsTable()) 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Move data from the old share_info columns to the new models table. 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement fetch(db_->GetUniqueStatement( 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT last_sync_timestamp, initial_sync_ended FROM share_info")); 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!fetch.Step()) 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 last_sync_timestamp = fetch.ColumnInt64(0); 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool initial_sync_ended = fetch.ColumnBool(1); 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify there were no additional rows returned. 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!fetch.Step()); 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(fetch.Succeeded()); 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement update(db_->GetUniqueStatement( 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "INSERT INTO models (model_id, " 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "last_download_timestamp, initial_sync_ended) VALUES (?, ?, ?)")); 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string bookmark_model_id = ModelTypeEnumToModelId(BOOKMARKS); 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update.BindBlob(0, bookmark_model_id.data(), bookmark_model_id.size()); 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update.BindInt64(1, last_sync_timestamp); 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update.BindBool(2, initial_sync_ended); 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!update.Run()) 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Drop the columns from the old share_info table via a temp table. 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool kCreateAsTempShareInfo = true; 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreateShareInfoTableVersion71(kCreateAsTempShareInfo)) 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "INSERT INTO temp_share_info (id, name, store_birthday, " 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "db_create_version, db_create_time, next_id, cache_guid) " 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT id, name, store_birthday, db_create_version, " 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "db_create_time, next_id, cache_guid FROM share_info")) 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SafeDropTable("share_info"); 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ALTER TABLE temp_share_info RENAME TO share_info")) 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVersion(71); 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::MigrateVersion71To72() { 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 72 removed a table 'extended_attributes', whose 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // contents didn't matter. 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SafeDropTable("extended_attributes"); 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVersion(72); 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::MigrateVersion72To73() { 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 73 added one column to the table 'share_info': notification_state 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ALTER TABLE share_info ADD COLUMN notification_state BLOB")) 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVersion(73); 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::MigrateVersion73To74() { 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 74 added the following columns to the table 'share_info': 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // autofill_migration_state 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bookmarks_added_during_autofill_migration 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // autofill_migration_time 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // autofill_entries_added_during_migration 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // autofill_profiles_added_during_migration 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ALTER TABLE share_info ADD COLUMN " 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "autofill_migration_state INT default 0")) 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ALTER TABLE share_info ADD COLUMN " 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "bookmarks_added_during_autofill_migration " 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "INT default 0")) 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ALTER TABLE share_info ADD COLUMN autofill_migration_time " 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "INT default 0")) 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ALTER TABLE share_info ADD COLUMN " 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "autofill_entries_added_during_migration " 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "INT default 0")) 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ALTER TABLE share_info ADD COLUMN " 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "autofill_profiles_added_during_migration " 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "INT default 0")) 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVersion(74); 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::MigrateVersion74To75() { 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In version 74, there was a table 'models': 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // blob model_id (entity specifics, primary key) 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // int last_download_timestamp 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // boolean initial_sync_ended 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In version 75, we deprecated the integer-valued last_download_timestamp, 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // using insted a protobuf-valued progress_marker field: 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // blob progress_marker 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The progress_marker values are initialized from the value of 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // last_download_timestamp, thereby preserving the download state. 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Move aside the old table and create a new empty one at the current schema. 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute("ALTER TABLE models RENAME TO temp_models")) 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!CreateV75ModelsTable()) 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement query(db_->GetUniqueStatement( 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT model_id, last_download_timestamp, initial_sync_ended " 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "FROM temp_models")); 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement update(db_->GetUniqueStatement( 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "INSERT INTO models (model_id, " 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "progress_marker, initial_sync_ended) VALUES (?, ?, ?)")); 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (query.Step()) { 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelType type = ModelIdToModelTypeEnum(query.ColumnBlob(0), 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query.ColumnByteLength(0)); 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type != UNSPECIFIED) { 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the |timestamp_token_for_migration| on a new 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DataTypeProgressMarker, using the old value of last_download_timestamp. 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The server will turn this into a real token on our behalf the next 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time we check for updates. 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_pb::DataTypeProgressMarker progress_marker; 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) progress_marker.set_data_type_id( 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSpecificsFieldNumberFromModelType(type)); 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) progress_marker.set_timestamp_token_for_migration(query.ColumnInt64(1)); 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string progress_blob; 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) progress_marker.SerializeToString(&progress_blob); 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update.BindBlob(0, query.ColumnBlob(0), query.ColumnByteLength(0)); 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update.BindBlob(1, progress_blob.data(), progress_blob.length()); 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update.BindBool(2, query.ColumnBool(2)); 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!update.Run()) 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update.Reset(true); 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!query.Succeeded()) 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Drop the old table. 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SafeDropTable("temp_models"); 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVersion(75); 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::MigrateVersion75To76() { 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This change removed five columns: 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // autofill_migration_state 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bookmarks_added_during_autofill_migration 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // autofill_migration_time 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // autofill_entries_added_during_migration 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // autofill_profiles_added_during_migration 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No data migration is necessary, but we should do a column refresh. 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVersion(76); 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) needs_column_refresh_ = true; 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::MigrateVersion76To77() { 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This change changes the format of stored timestamps to ms since 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the Unix epoch. 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On Windows, we used to store timestamps in FILETIME format (100s of 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ns since Jan 1, 1601). Magic numbers taken from 1001c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// http://stackoverflow.com/questions/5398557/ 1002c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// java-library-for-dealing-with-win32-filetime 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// . 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TO_UNIX_TIME_MS(x) #x " = " #x " / 10000 - 11644473600000" 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On other platforms, we used to store timestamps in time_t format (s 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// since the Unix epoch). 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TO_UNIX_TIME_MS(x) #x " = " #x " * 1000" 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement update_timestamps(db_->GetUniqueStatement( 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "UPDATE metas SET " 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TO_UNIX_TIME_MS(mtime) ", " 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TO_UNIX_TIME_MS(server_mtime) ", " 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TO_UNIX_TIME_MS(ctime) ", " 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TO_UNIX_TIME_MS(server_ctime))); 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef TO_UNIX_TIME_MS 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!update_timestamps.Run()) 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVersion(77); 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::MigrateVersion77To78() { 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 78 added one column to table 'metas': base_server_specifics. 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ALTER TABLE metas ADD COLUMN base_server_specifics BLOB")) { 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVersion(78); 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::MigrateVersion78To79() { 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some users are stuck with a DB that causes them to reuse existing IDs. We 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // perform this one-time fixup on all users to help the few that are stuck. 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See crbug.com/142987 for details. 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "UPDATE share_info SET next_id = next_id - 65536")) { 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVersion(79); 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::MigrateVersion79To80() { 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ALTER TABLE share_info ADD COLUMN bag_of_chips BLOB")) 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement update(db_->GetUniqueStatement( 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "UPDATE share_info SET bag_of_chips = ?")); 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An empty message is serialized to an empty string. 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) update.BindBlob(0, NULL, 0); 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!update.Run()) 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVersion(80); 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::MigrateVersion80To81() { 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if(!db_->Execute( 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ALTER TABLE metas ADD COLUMN server_ordinal_in_parent BLOB")) 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement get_positions(db_->GetUniqueStatement( 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT metahandle, server_position_in_parent FROM metas")); 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement put_ordinals(db_->GetUniqueStatement( 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "UPDATE metas SET server_ordinal_in_parent = ?" 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WHERE metahandle = ?")); 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while(get_positions.Step()) { 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 metahandle = get_positions.ColumnInt64(0); 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 position = get_positions.ColumnInt64(1); 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& ordinal = Int64ToNodeOrdinal(position).ToInternalValue(); 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) put_ordinals.BindBlob(0, ordinal.data(), ordinal.length()); 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) put_ordinals.BindInt64(1, metahandle); 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if(!put_ordinals.Run()) 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) put_ordinals.Reset(true); 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVersion(81); 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) needs_column_refresh_ = true; 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::MigrateVersion81To82() { 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ALTER TABLE models ADD COLUMN transaction_version BIGINT default 0")) 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement update(db_->GetUniqueStatement( 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "UPDATE models SET transaction_version = 0")); 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!update.Run()) 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVersion(82); 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::MigrateVersion82To83() { 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Version 83 added transaction_version on sync node. 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ALTER TABLE metas ADD COLUMN transaction_version BIGINT default 0")) 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement update(db_->GetUniqueStatement( 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "UPDATE metas SET transaction_version = 0")); 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!update.Run()) 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVersion(83); 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DirectoryBackingStore::MigrateVersion83To84() { 11152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Version 84 added deleted_metas table to store deleted metas until we know 11162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // for sure that the deletions are persisted in native models. 11172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) string query = "CREATE TABLE deleted_metas "; 11182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) query.append(ComposeCreateTableColumnSpecs()); 11192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!db_->Execute(query.c_str())) 11202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 11212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetVersion(84); 11222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 11232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 11242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DirectoryBackingStore::MigrateVersion84To85() { 1126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Version 85 removes the initial_sync_ended flag. 11272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!db_->Execute("ALTER TABLE models RENAME TO temp_models")) 11282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 11292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!CreateModelsTable()) 11302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 11312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!db_->Execute("INSERT INTO models SELECT " 11322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "model_id, progress_marker, transaction_version " 11332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "FROM temp_models")) { 11342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 11352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 11362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeDropTable("temp_models"); 11372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetVersion(85); 11392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 11402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 11412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool DirectoryBackingStore::MigrateVersion85To86() { 1143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Version 86 removes both server ordinals and local NEXT_ID, PREV_ID and 1144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // SERVER_{POSITION,ORDINAL}_IN_PARENT and replaces them with UNIQUE_POSITION 1145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // and SERVER_UNIQUE_POSITION. 1146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!db_->Execute("ALTER TABLE metas ADD COLUMN " 1147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "server_unique_position BLOB")) { 1148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 1149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!db_->Execute("ALTER TABLE metas ADD COLUMN " 1151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "unique_position BLOB")) { 1152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 1153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!db_->Execute("ALTER TABLE metas ADD COLUMN " 1155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "unique_bookmark_tag VARCHAR")) { 1156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 1157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Fetch the cache_guid from the DB, because we don't otherwise have access to 1160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // it from here. 1161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sql::Statement get_cache_guid(db_->GetUniqueStatement( 1162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "SELECT cache_guid FROM share_info")); 1163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!get_cache_guid.Step()) { 1164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 1165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string cache_guid = get_cache_guid.ColumnString(0); 1167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!get_cache_guid.Step()); 1168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(get_cache_guid.Succeeded()); 1169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sql::Statement get(db_->GetUniqueStatement( 1171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "SELECT " 1172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) " metahandle, " 1173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) " id, " 1174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) " specifics, " 1175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) " is_dir, " 1176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) " unique_server_tag, " 1177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) " server_ordinal_in_parent " 1178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "FROM metas")); 1179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Note that we set both the local and server position based on the server 1181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // position. We wll lose any unsynced local position changes. Unfortunately, 1182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // there's nothing we can do to avoid that. The NEXT_ID / PREV_ID values 1183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // can't be translated into a UNIQUE_POSTION in a reliable way. 1184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sql::Statement put(db_->GetCachedStatement( 1185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SQL_FROM_HERE, 1186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "UPDATE metas SET" 1187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) " server_unique_position = ?," 1188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) " unique_position = ?," 1189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) " unique_bookmark_tag = ?" 1190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "WHERE metahandle = ?")); 1191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) while (get.Step()) { 1193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int64 metahandle = get.ColumnInt64(0); 1194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string id_string; 1196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) get.ColumnBlobAsString(1, &id_string); 1197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sync_pb::EntitySpecifics specifics; 1199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) specifics.ParseFromArray( 1200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) get.ColumnBlob(2), get.ColumnByteLength(2)); 1201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool is_dir = get.ColumnBool(3); 1203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string server_unique_tag = get.ColumnString(4); 1205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string ordinal_string; 1207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) get.ColumnBlobAsString(5, &ordinal_string); 1208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NodeOrdinal ordinal(ordinal_string); 1209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string unique_bookmark_tag; 1212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We only maintain positions for bookmarks that are not server-defined 1214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // top-level folders. 1215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UniquePosition position; 1216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (GetModelTypeFromSpecifics(specifics) == BOOKMARKS 1217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) && !(is_dir && !server_unique_tag.empty())) { 1218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (id_string.at(0) == 'c') { 1219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We found an uncommitted item. This is rare, but fortunate. This 1220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // means we can set the bookmark tag according to the originator client 1221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // item ID and originator cache guid, because (unlike the other case) we 1222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // know that this client is the originator. 1223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) unique_bookmark_tag = syncable::GenerateSyncableBookmarkHash( 1224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cache_guid, 1225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) id_string.substr(1)); 1226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 1227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If we've already committed the item, then we don't know who the 1228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // originator was. We do not have access to the originator client item 1229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // ID and originator cache guid at this point. 1230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // 1231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We will base our hash entirely on the server ID instead. This is 1232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // incorrect, but at least all clients that undergo this migration step 1233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // will be incorrect in the same way. 1234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // 1235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // To get everyone back into a synced state, we will update the bookmark 1236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // tag according to the originator_cache_guid and originator_item_id 1237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // when we see updates for this item. That should ensure that commonly 1238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // modified items will end up with the proper tag values eventually. 1239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) unique_bookmark_tag = syncable::GenerateSyncableBookmarkHash( 1240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string(), // cache_guid left intentionally blank. 1241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) id_string.substr(1)); 1242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int64 int_position = NodeOrdinalToInt64(ordinal); 1245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) position = UniquePosition::FromInt64(int_position, unique_bookmark_tag); 1246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 1247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Leave bookmark_tag and position at their default (invalid) values. 1248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string position_blob; 1251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) position.SerializeToString(&position_blob); 1252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) put.BindBlob(0, position_blob.data(), position_blob.length()); 1253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) put.BindBlob(1, position_blob.data(), position_blob.length()); 1254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) put.BindBlob(2, unique_bookmark_tag.data(), unique_bookmark_tag.length()); 1255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) put.BindInt64(3, metahandle); 1256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!put.Run()) 1258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 1259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) put.Reset(true); 1260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SetVersion(86); 1263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) needs_column_refresh_ = true; 1264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 1265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 1266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::CreateTables() { 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "First run, creating tables"; 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create two little tables share_version and share_info 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!db_->Execute( 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "CREATE TABLE share_version (" 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "id VARCHAR(128) primary key, data INT)")) { 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db_->GetUniqueStatement( 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "INSERT INTO share_version VALUES(?, ?)")); 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindString(0, dir_name_); 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindInt(1, kCurrentDBVersion); 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!s.Run()) 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool kCreateAsTempShareInfo = false; 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreateShareInfoTable(kCreateAsTempShareInfo)) { 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db_->GetUniqueStatement( 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "INSERT INTO share_info VALUES" 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "(?, " // id 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "?, " // name 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "?, " // store_birthday 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "?, " // db_create_version 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "?, " // db_create_time 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "-2, " // next_id 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "?, " // cache_guid 13012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(rlarocque, 124140): Remove notification_state field. 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "?, " // notification_state 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "?);")); // bag_of_chips 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindString(0, dir_name_); // id 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindString(1, dir_name_); // name 1306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) s.BindString(2, std::string()); // store_birthday 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(akalin): Remove this unused db_create_version field. (Or 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // actually use it for something.) http://crbug.com/118356 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindString(3, "Unknown"); // db_create_version 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindInt(4, static_cast<int32>(time(0))); // db_create_time 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindString(5, GenerateCacheGUID()); // cache_guid 13122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(rlarocque, 124140): Remove this unused notification-state field. 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindBlob(6, NULL, 0); // notification_state 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindBlob(7, NULL, 0); // bag_of_chips 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!s.Run()) 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreateModelsTable()) 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the big metas table. 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreateMetasTable(false)) 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Insert the entry for the root into the metas table. 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int64 now = TimeToProtoTime(base::Time::Now()); 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db_->GetUniqueStatement( 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "INSERT INTO metas " 1331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "( id, metahandle, is_dir, ctime, mtime ) " 1332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "VALUES ( \"r\", 1, 1, ?, ? )")); 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindInt64(0, now); 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindInt64(1, now); 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!s.Run()) 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::CreateMetasTable(bool is_temporary) { 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string query = "CREATE TABLE "; 13452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) query.append(is_temporary ? "temp_metas" : "metas"); 13462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) query.append(ComposeCreateTableColumnSpecs()); 13472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!db_->Execute(query.c_str())) 13482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 13492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create a deleted_metas table to save copies of deleted metas until the 13512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // deletions are persisted. For simplicity, don't try to migrate existing 13522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // data because it's rarely used. 13532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SafeDropTable("deleted_metas"); 13542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) query = "CREATE TABLE deleted_metas "; 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query.append(ComposeCreateTableColumnSpecs()); 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->Execute(query.c_str()); 13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::CreateV71ModelsTable() { 13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is an old schema for the Models table, used from versions 71 to 74. 13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->Execute( 13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "CREATE TABLE models (" 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "model_id BLOB primary key, " 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "last_download_timestamp INT, " 13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Gets set if the syncer ever gets updates from the 13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // server and the server returns 0. Lets us detect the 13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // end of the initial sync. 13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "initial_sync_ended BOOLEAN default 0)"); 13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DirectoryBackingStore::CreateV75ModelsTable() { 13722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is an old schema for the Models table, used from versions 75 to 80. 13732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return db_->Execute( 13742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "CREATE TABLE models (" 13752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "model_id BLOB primary key, " 13762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "progress_marker BLOB, " 13772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Gets set if the syncer ever gets updates from the 13782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // server and the server returns 0. Lets us detect the 13792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // end of the initial sync. 13802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "initial_sync_ended BOOLEAN default 0)"); 13812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 13822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::CreateModelsTable() { 13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is the current schema for the Models table, from version 81 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // onward. If you change the schema, you'll probably want to double-check 13862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the use of this function in the v84-v85 migration. 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->Execute( 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "CREATE TABLE models (" 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "model_id BLOB primary key, " 13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "progress_marker BLOB, " 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Gets set if the syncer ever gets updates from the 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // server and the server returns 0. Lets us detect the 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // end of the initial sync. 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "transaction_version BIGINT default 0)"); 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::CreateShareInfoTable(bool is_temporary) { 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* name = is_temporary ? "temp_share_info" : "share_info"; 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string query = "CREATE TABLE "; 14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query.append(name); 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is the current schema for the ShareInfo table, from version 76 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // onward. 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query.append(" (" 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "id TEXT primary key, " 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "name TEXT, " 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "store_birthday TEXT, " 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "db_create_version TEXT, " 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "db_create_time INT, " 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "next_id INT default -2, " 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "cache_guid TEXT, " 14112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(rlarocque, 124140): Remove notification_state field. 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "notification_state BLOB, " 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "bag_of_chips BLOB" 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ")"); 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->Execute(query.c_str()); 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::CreateShareInfoTableVersion71( 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_temporary) { 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* name = is_temporary ? "temp_share_info" : "share_info"; 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string query = "CREATE TABLE "; 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query.append(name); 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is the schema for the ShareInfo table used from versions 71 to 72. 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query.append(" (" 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "id TEXT primary key, " 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "name TEXT, " 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "store_birthday TEXT, " 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "db_create_version TEXT, " 14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "db_create_time INT, " 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "next_id INT default -2, " 14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "cache_guid TEXT )"); 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return db_->Execute(query.c_str()); 14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function checks to see if the given list of Metahandles has any nodes 1436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// whose PARENT_ID values refer to ID values that do not actually exist. 1437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Returns true on success. 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DirectoryBackingStore::VerifyReferenceIntegrity( 1439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const Directory::MetahandlesMap* handles_map) { 14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACE_EVENT0("sync", "SyncDatabaseIntegrityCheck"); 14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using namespace syncable; 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef base::hash_set<std::string> IdsSet; 14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IdsSet ids_set; 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_ok = true; 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1447868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (Directory::MetahandlesMap::const_iterator it = handles_map->begin(); 1448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it != handles_map->end(); ++it) { 1449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EntryKernel* entry = it->second; 14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_duplicate_id = !(ids_set.insert(entry->ref(ID).value()).second); 14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_ok = is_ok && !is_duplicate_id; 14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IdsSet::iterator end = ids_set.end(); 1455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (Directory::MetahandlesMap::const_iterator it = handles_map->begin(); 1456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it != handles_map->end(); ++it) { 1457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EntryKernel* entry = it->second; 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool parent_exists = (ids_set.find(entry->ref(PARENT_ID).value()) != end); 1459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!parent_exists) { 1460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 1461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return is_ok; 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DirectoryBackingStore::PrepareSaveEntryStatement( 14672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EntryTable table, sql::Statement* save_statement) { 14682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (save_statement->is_valid()) 14692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 14702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) string query; 14722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) query.reserve(kUpdateStatementBufferSize); 14732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (table) { 14742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case METAS_TABLE: 14752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) query.append("INSERT OR REPLACE INTO metas "); 14762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 14772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case DELETE_JOURNAL_TABLE: 14782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) query.append("INSERT OR REPLACE INTO deleted_metas "); 14792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 14802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) string values; 14832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) values.reserve(kUpdateStatementBufferSize); 14842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) values.append(" VALUES "); 14852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* separator = "( "; 14862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int i = 0; 14872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (i = BEGIN_FIELDS; i < FIELD_COUNT; ++i) { 14882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) query.append(separator); 14892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) values.append(separator); 14902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) separator = ", "; 14912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) query.append(ColumnName(i)); 14922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) values.append("?"); 14932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) query.append(" ) "); 14952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) values.append(" )"); 14962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) query.append(values); 14972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) save_statement->Assign(db_->GetUniqueStatement( 14982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::StringPrintf(query.c_str(), "metas").c_str())); 14992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 15002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace syncable 15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace syncer 1503