import Foundation import GRDB extension Database { static var migrator: DatabaseMigrator = { var migrator = DatabaseMigrator() // flush db on schema change (only in DEV mode) #if DEBUG migrator.eraseDatabaseOnSchemaChange = true #endif // 1st migration - basic tables migrator.registerMigration("Add basic tables") { db in // credentials try db.create(table: "credentials", options: [.ifNotExists]) { table in table.column("bareJid", .text).notNull().primaryKey().unique(onConflict: .replace) table.column("pass", .text).notNull() table.column("isActive", .boolean).notNull().defaults(to: true) } // rosters try db.create(table: "rosterVersions", options: [.ifNotExists]) { table in table.column("bareJid", .text).notNull().primaryKey().unique(onConflict: .replace) table.column("version", .text).notNull() } try db.create(table: "rosters", options: [.ifNotExists]) { table in table.column("bareJid", .text).notNull() table.column("contactBareJid", .text).notNull() table.column("name", .text) table.column("subscription", .text).notNull() table.column("ask", .boolean).notNull().defaults(to: false) table.column("data", .text).notNull() table.primaryKey(["bareJid", "contactBareJid"], onConflict: .replace) table.column("locallyDeleted", .boolean).notNull().defaults(to: false) } // chats try db.create(table: "chats", options: [.ifNotExists]) { table in table.column("id", .text).notNull().primaryKey().unique(onConflict: .replace) table.column("account", .text).notNull() table.column("participant", .text).notNull() table.column("type", .integer).notNull() } // messages try db.create(table: "messages", options: [.ifNotExists]) { table in table.column("id", .text).notNull().primaryKey().unique(onConflict: .replace) table.column("type", .text).notNull() table.column("date", .datetime).notNull() table.column("contentType", .text).notNull() table.column("status", .integer).notNull() table.column("from", .text).notNull() table.column("to", .text) table.column("body", .text) table.column("subject", .text) table.column("thread", .text) table.column("oobUrl", .text) } } migrator.registerMigration("Add OMEMO tables") { db in try db.create(table: "omemo_sessions", options: [.ifNotExists]) { table in table.column("account", .text).notNull() table.column("name", .text).notNull() table.column("deviceId", .integer).notNull() table.column("key", .text).notNull() table.primaryKey(["account", "name", "deviceId"], onConflict: .replace) } try db.create(table: "omemo_identities", options: [.ifNotExists]) { table in table.column("account", .text).notNull() table.column("name", .text).notNull() table.column("deviceId", .integer).notNull() table.column("fingerprint", .text).notNull() table.column("key", .blob).notNull() table.column("own", .integer).notNull() table.column("status", .integer).notNull() table.primaryKey(["account", "name", "fingerprint"], onConflict: .ignore) } try db.create(table: "omemo_pre_keys", options: [.ifNotExists]) { table in table.column("account", .text).notNull() table.column("id", .integer).notNull() table.column("key", .blob).notNull() table.column("markForDeletion", .boolean).notNull().defaults(to: false) table.primaryKey(["account", "id"], onConflict: .replace) } try db.create(table: "omemo_signed_pre_keys", options: [.ifNotExists]) { table in table.column("account", .text).notNull() table.column("id", .integer).notNull() table.column("key", .blob).notNull() table.primaryKey(["account", "id"], onConflict: .replace) } do { try db.alter(table: "messages") { table in table.add(column: "secure", .boolean).notNull().defaults(to: false) } } catch { print("Error adding columns: \(error)\nProbably already added") } do { try db.alter(table: "chats") { table in table.add(column: "encrypted", .boolean).notNull().defaults(to: false) } } catch { print("Error adding columns: \(error)\nProbably already added") } } // return migrator return migrator }() }