     }
     
     private func runMigrations(_ db: Database, upTo targetIdentifier: String) throws {
+        try db.execute(sql: "CREATE TABLE IF NOT EXISTS grdb_migrations (identifier TEXT NOT NULL PRIMARY KEY)")
+        
         var prefixMigrations: [Migration] = []
         for migration in migrations {
             prefixMigrations.append(migration)

            !migrations.map({ $0.identifier }).contains(migration.identifier),
            "already registered migration: \(String(reflecting: migration.identifier))")
        migrations.append(migration)
    }
    
    private func setupMigrations(_ db: Database) throws {
        try db.execute(sql: "CREATE TABLE IF NOT EXISTS grdb_migrations (identifier TEXT NOT NULL PRIMARY KEY)")
    }
    
    private func appliedIdentifiers(_ db: Database) throws -> Set<String> {

    /// - targetIdentifier: The identifier of a registered migration.
    /// - throws: An eventual error thrown by the registered migration blocks.
    public func migrate(_ writer: DatabaseWriter, upTo targetIdentifier: String) throws {
        try writer.barrierWriteWithoutTransaction { db in
            if eraseDatabaseOnSchemaChange {
                // Fetch information about current database state
                var info: (lastAppliedIdentifier: String, schema: SchemaInfo)?
                try db.inTransaction(.deferred) {
                    let identifiers = try appliedIdentifiers(db)
                    if let lastAppliedIdentifier = migrations
                        .last(where: { identifiers.contains($0.identifier) })?
                        .identifier
                    {
                        info = try (lastAppliedIdentifier: lastAppliedIdentifier, schema: db.schema())
                    }
                    return .commit
                }
                
                if let info = info {
                    // Create a temporary witness database (on disk, just in case
                    // migrations would involve a lot of data).
                    let witness = try DatabaseQueue(path: "", configuration: writer.configuration)
                    
                    // Grab schema of migrated witness database
                    let witnessSchema: SchemaInfo = try witness.writeWithoutTransaction { db in
                        try runMigrations(db, upTo: info.lastAppliedIdentifier)
                        return try db.schema()
                    }
                    
                    // Erase database if we detect a schema change
                    if info.schema != witnessSchema {
                        try db.erase()
                    }
                }
            }
            
            // Migrate to target schema
            try runMigrations(db, upTo: targetIdentifier)
        }
    }
