Last active
April 28, 2018 22:09
-
-
Save acrookston/6dd5fad482a5ae74663d66213df18fe4 to your computer and use it in GitHub Desktop.
Simple SQLite migration for Swift with the SQLite.swift framework
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// MigrationCreateItems.swift | |
// Stash | |
// | |
// Created by Andrew C on 8/30/17. | |
// Copyright © 2017 Andrew Crookston. All rights reserved. | |
// License: MIT | |
// | |
import Foundation | |
import SQLite | |
final class MigrationCreateItems: SQLiteMigration { | |
static let name: String = "create_items" | |
static func migrate(connection: Connection) -> Bool { | |
do { | |
try connection.run(Table(Item.tableName).create { t in | |
t.column(Expression<Int64>("id"), primaryKey: .autoincrement) | |
t.column(Expression<String>("uid"), unique: true) | |
t.column(Expression<Int64>("type")) | |
t.column(Expression<String>("content")) | |
t.column(Expression<String?>("notes")) | |
t.column(Expression<String?>("metadata")) | |
}) | |
return true | |
} catch { | |
print("#DB MIGRATION ERROR: \(error)") | |
return false | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// SQLiteMigration.swift | |
// Stash | |
// | |
// Created by Andrew C on 8/30/17. | |
// Copyright © 2017 Andrew Crookston. All rights reserved. | |
// License: MIT | |
// | |
import Foundation | |
import SQLite | |
protocol SQLiteMigration { | |
static var name: String { get } | |
static func migrate(connection: Connection) -> Bool | |
} | |
final class SQLiteMigrator { | |
static func register(_ migration: SQLiteMigration.Type) { | |
sharedInstance.migrations.append(migration) | |
} | |
static func register(_ migrations: [SQLiteMigration.Type]) { | |
sharedInstance.migrations.append(contentsOf: migrations) | |
} | |
@discardableResult static func migrate(_ connection: Connection) -> Bool { | |
return sharedInstance.migrate(connection) | |
} | |
// MARK: - private | |
private static let schemaTable = Table("db_schema_migration") | |
private static let sharedInstance = SQLiteMigrator() | |
private var migrations = [SQLiteMigration.Type]() | |
private lazy var completed = [String]() | |
private init() {} | |
private func migrate(connection: Connection, migration: SQLiteMigration.Type) -> Bool { | |
print("#DB CHECKING MIGRATION: \(migration.name)") | |
if !hasMigrated(migration: migration) { | |
print("#DB MIGRATING: \(migration.name)") | |
if migration.migrate(connection: connection) { | |
completed(migration: migration, connection: connection) | |
return true | |
} | |
return true | |
} | |
return false | |
} | |
private func completed(migration: SQLiteMigration.Type, connection: Connection) { | |
completed.append(migration.name) | |
let name = Expression<String>("name") | |
do { | |
let insert = SQLiteMigrator.schemaTable.insert(name <- migration.self.name) | |
try connection.run(insert) | |
} catch { | |
print("#DB SAVE MIGRATED ERROR: \(error)") | |
} | |
} | |
private func hasMigrated(migration: SQLiteMigration.Type) -> Bool { | |
return completed.contains(migration.name) | |
} | |
private func setup(connection: Connection) { | |
createSchema(connection: connection) | |
completed = loadMigrations(connection: connection) | |
} | |
private func loadMigrations(connection: Connection) -> [String] { | |
var migrations = [String]() | |
let name = Expression<String>("name") | |
do { | |
for migration in try connection.prepare(SQLiteMigrator.schemaTable) { | |
migrations.append(migration[name]) | |
} | |
} catch { | |
print("#DB LOAD MIGRATIONS ERROR: \(error)") | |
} | |
return migrations | |
} | |
@discardableResult private func createSchema(connection: Connection) -> Bool { | |
do { | |
try connection.run(SQLiteMigrator.schemaTable.create(ifNotExists: true) { t in | |
t.column(Expression<String>("name"), unique: true) | |
}) | |
return true | |
} catch { | |
print("#DB MIGRATION ERROR: \(error)") | |
return false | |
} | |
} | |
private func migrate(_ connection: Connection) -> Bool { | |
setup(connection: connection) | |
for migration in migrations { | |
if !migrate(connection: connection, migration: migration) { | |
return false | |
} | |
} | |
return true | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// After creating a db connection: | |
SQLiteMigrator.register(MigrationCreateItems.self) | |
SQLiteMigrator.migrate(connection) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment