首页 > 解决方案 > Avoiding Vapor migrations on a new database

问题描述

I've created migration for adding a field to the Postgres table, it works as expected on the existing database. But when I want to run the same vapor server with a new database it crashes on the migration with the "field already exists" message, which is, of course, understandable. But how to maintain the server code so it could work both with existing and new databases?

Fatal error: Error raised at top level: PostgreSQL Error: column "the_coloumn" of relation "User" already exists
- id: PostgreSQLError.server.error.check_for_column_name_collision
: file /BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-1100.8.280/swift/stdlib/public/core/ErrorType.swift, line 200

标签: swiftvaporvapor-fluent

解决方案


假设您已经部署了应用程序并进行了多次安装,那么您将需要保留表的两个版本。如果你没有,那么你总是可以删除第二个迁移,如果它只是添加字段。正如您所发现的,该字段是在新安装的第一次迁移中创建的。

但是,如果您必须同时拥有两者,那么您将需要替换您AddProperties在原始迁移中的使用,该迁移使用明确的字段列表构建表,而不是您在第二次迁移中添加的那个。单个字段创建的示例如下:

extension User:Migration
{
    static func prepare(on connection:MySQLConnection) -> Future<Void>
    {
        return Database.create(self, on:connection)
        {
            builder in
            builder.field(for:\.id, isIdentifier:true)
            builder.field(for:\.surname, type:.varchar(30, characterSet:nil, collate:nil))
            builder.field(for:\.firstName, type:.varchar(30, characterSet:nil, collate:nil))
        }
    }
}

这将像您之前在原始数据库中创建表时那样构建表。然后您的第二次迁移将像以前一样工作。有关更多信息,请参阅https://docs.vapor.codes/3.0/fluent/migrations/


推荐阅读