From 3cbdbf2652202a3473271ed298ff50e5797cce68 Mon Sep 17 00:00:00 2001 From: Greg Soltis Date: Tue, 30 Jan 2018 14:36:22 -0800 Subject: Schema migrations for LevelDB (#728) * Implement schema versions * Style fixes * newlines, copyrights, assumptions * Fix nullability * Raw ptr -> shared_ptr * kVersionTableGlobal -> kVersionGlobalTable * Drop utils, move into static methods * Drop extra include * Add a few more comments * Move version constant into migrations file * formatting? * Fix comment --- Firestore/Source/Local/FSTLevelDBMigrations.mm | 95 ++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 Firestore/Source/Local/FSTLevelDBMigrations.mm (limited to 'Firestore/Source/Local/FSTLevelDBMigrations.mm') diff --git a/Firestore/Source/Local/FSTLevelDBMigrations.mm b/Firestore/Source/Local/FSTLevelDBMigrations.mm new file mode 100644 index 0000000..49af893 --- /dev/null +++ b/Firestore/Source/Local/FSTLevelDBMigrations.mm @@ -0,0 +1,95 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Firestore/Source/Local/FSTLevelDBMigrations.h" + +#include +#include + +#import "Firestore/Protos/objc/firestore/local/Target.pbobjc.h" +#import "Firestore/Source/Local/FSTLevelDB.h" +#import "Firestore/Source/Local/FSTLevelDBKey.h" +#import "Firestore/Source/Local/FSTLevelDBQueryCache.h" +#import "Firestore/Source/Local/FSTWriteGroup.h" + +NS_ASSUME_NONNULL_BEGIN + +// Current version of the schema defined in this file. +static FSTLevelDBSchemaVersion kSchemaVersion = 1; + +using leveldb::DB; +using leveldb::Status; +using leveldb::Slice; +using leveldb::WriteOptions; + +/** + * Ensures that the global singleton target metadata row exists in LevelDB. + * @param db The db in which to require the row. + */ +static void EnsureTargetGlobal(std::shared_ptr db, FSTWriteGroup *group) { + FSTPBTargetGlobal *targetGlobal = [FSTLevelDBQueryCache readTargetMetadataFromDB:db]; + if (!targetGlobal) { + [group setMessage:[FSTPBTargetGlobal message] forKey:[FSTLevelDBTargetGlobalKey key]]; + } +} + +/** + * Save the given version number as the current version of the schema of the database. + * @param version The version to save + * @param group The transaction in which to save the new version number + */ +static void SaveVersion(FSTLevelDBSchemaVersion version, FSTWriteGroup *group) { + std::string key = [FSTLevelDBVersionKey key]; + std::string version_string = std::to_string(version); + [group setData:version_string forKey:key]; +} + +@implementation FSTLevelDBMigrations + ++ (FSTLevelDBSchemaVersion)schemaVersionForDB:(std::shared_ptr)db { + std::string key = [FSTLevelDBVersionKey key]; + std::string version_string; + Status status = db->Get([FSTLevelDB standardReadOptions], key, &version_string); + if (status.IsNotFound()) { + return 0; + } else { + return stoi(version_string); + } +} + ++ (void)runMigrationsOnDB:(std::shared_ptr)db { + FSTWriteGroup *group = [FSTWriteGroup groupWithAction:@"Migrations"]; + FSTLevelDBSchemaVersion currentVersion = [self schemaVersionForDB:db]; + // Each case in this switch statement intentionally falls through. This lets us + // start at the current schema version and apply any migrations that have not yet + // been applied, to bring us up to current, as defined by the kSchemaVersion constant. + switch (currentVersion) { + case 0: + EnsureTargetGlobal(db, group); + // Fallthrough + default: + if (currentVersion < kSchemaVersion) { + SaveVersion(kSchemaVersion, group); + } + } + if (!group.isEmpty) { + [group writeToDB:db]; + } +} + +@end + +NS_ASSUME_NONNULL_END -- cgit v1.2.3