add iOS
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
/// An internal struct that defines a migration.
|
||||
struct Migration {
|
||||
enum ForeignKeyChecks {
|
||||
case deferred
|
||||
case immediate
|
||||
case disabled
|
||||
}
|
||||
|
||||
let identifier: String
|
||||
var foreignKeyChecks: ForeignKeyChecks
|
||||
let migrate: (Database) throws -> Void
|
||||
|
||||
func run(_ db: Database) throws {
|
||||
if try Bool.fetchOne(db, sql: "PRAGMA foreign_keys") ?? false {
|
||||
switch foreignKeyChecks {
|
||||
case .deferred:
|
||||
try runWithDeferredForeignKeysChecks(db)
|
||||
case .immediate:
|
||||
try runWithImmediateForeignKeysChecks(db)
|
||||
case .disabled:
|
||||
try runWithDisabledForeignKeysChecks(db)
|
||||
}
|
||||
} else {
|
||||
try runWithImmediateForeignKeysChecks(db)
|
||||
}
|
||||
}
|
||||
|
||||
private func runWithImmediateForeignKeysChecks(_ db: Database) throws {
|
||||
try db.inTransaction(.immediate) {
|
||||
try migrate(db)
|
||||
try insertAppliedIdentifier(db)
|
||||
return .commit
|
||||
}
|
||||
}
|
||||
|
||||
private func runWithDisabledForeignKeysChecks(_ db: Database) throws {
|
||||
try db.execute(sql: "PRAGMA foreign_keys = OFF")
|
||||
try throwingFirstError(
|
||||
execute: {
|
||||
try db.inTransaction(.immediate) {
|
||||
try migrate(db)
|
||||
try insertAppliedIdentifier(db)
|
||||
return .commit
|
||||
}
|
||||
},
|
||||
finally: {
|
||||
try db.execute(sql: "PRAGMA foreign_keys = ON")
|
||||
})
|
||||
}
|
||||
|
||||
private func runWithDeferredForeignKeysChecks(_ db: Database) throws {
|
||||
// Support for database alterations described at
|
||||
// https://www.sqlite.org/lang_altertable.html#otheralter
|
||||
//
|
||||
// > 1. If foreign key constraints are enabled, disable them using
|
||||
// > PRAGMA foreign_keys=OFF.
|
||||
try db.execute(sql: "PRAGMA foreign_keys = OFF")
|
||||
|
||||
try throwingFirstError(
|
||||
execute: {
|
||||
// > 2. Start a transaction.
|
||||
try db.inTransaction(.immediate) {
|
||||
try migrate(db)
|
||||
try insertAppliedIdentifier(db)
|
||||
|
||||
// > 10. If foreign key constraints were originally enabled
|
||||
// > then run PRAGMA foreign_key_check to verify that the
|
||||
// > schema change did not break any foreign
|
||||
// > key constraints.
|
||||
try db.checkForeignKeys()
|
||||
|
||||
// > 11. Commit the transaction started in step 2.
|
||||
return .commit
|
||||
}
|
||||
},
|
||||
finally: {
|
||||
// > 12. If foreign keys constraints were originally enabled,
|
||||
// > reenable them now.
|
||||
try db.execute(sql: "PRAGMA foreign_keys = ON")
|
||||
})
|
||||
}
|
||||
|
||||
private func insertAppliedIdentifier(_ db: Database) throws {
|
||||
try db.execute(sql: "INSERT INTO grdb_migrations (identifier) VALUES (?)", arguments: [identifier])
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user