Vapor注册ToDo数据库后PostgreSQL命令行无法查看及Turkey库报错问题
环境信息
- 环境:Vapor v4.77
- 数据库:通过Homebrew安装的PostgreSQL@15
环境变量配置
/Users/Ric> echo $DATABASE_NAME ToDo /Users/Ric> echo $DATABASE_HOST localhost /Users/Ric> echo $DATABASE_PORT 5432
应用配置代码
public func configure(_ app: Application) async throws { // uncomment to serve files from /Public folder // app.middleware.use(FileMiddleware(publicDirectory: app.directory.publicDirectory)) app.databases.use(DatabaseConfigurationFactory.postgres(configuration: .init( hostname: Environment.get("DATABASE_HOST") ?? "localhost", port: Environment.get("DATABASE_PORT").flatMap(Int.init(_:)) ?? SQLPostgresConfiguration.ianaPortNumber, username: Environment.get("DATABASE_USERNAME") ?? "vapor_username", password: Environment.get("DATABASE_PASSWORD") ?? "vapor_password", database: Environment.get("DATABASE_NAME") ?? "vapor_database", tls: .prefer(try .init(configuration: .clientDefault))) ), as: .psql) // Migrations: app.migrations.add(CreateTodo()) try await app.autoMigrate().get() // register routes try routes(app) }
迁移代码
(临时将'name'改为'first_name'等)
import Fluent struct CreateTodo: AsyncMigration { func prepare(on database: Database) async throws { try await database.schema("todos") .deleteField("title") .field("first_name", .string) .field("last_name", .string) .update() } func revert(on database: Database) async throws { try await database.schema("todos").delete() } }
问题描述
通过PostgreSQL命令行找不到名为ToDo的数据库,但应用能正常执行POST和GET请求,数据也能持久化。尝试切换到已存在的Turkey库并修改配置后,执行swift run出现报错,请求解释原因。
问题原因分析
找不到
ToDo数据库但应用正常运行
PostgreSQL默认区分大小写,你环境变量里的数据库名是ToDo(首字母大写),但PostgreSQL在未加双引号的查询场景下会自动将名称转为小写。实际Vapor创建的数据库是带大小写的ToDo,但你用命令行\l查看时,若未用双引号指定名称,只会显示小写的库名(如果存在的话)。而Vapor连接时会严格按照配置的大小写名称发送请求,所以能正常连接到ToDo库,你在命令行里需要用\l "ToDo"才能查到这个库。切换到
Turkey库后报错
你的迁移代码CreateTodo的prepare方法是对todos表执行删除字段、新增字段的修改操作,但Turkey库中可能不存在todos表,或者todos表原本就没有title字段,导致迁移执行时触发数据库报错。另外,Fluent会在每个数据库中创建_fluent_migrations表记录已执行的迁移,之前在ToDo库中已经执行过CreateTodo迁移,切换到Turkey库后,Fluent会尝试再次执行该迁移,但Turkey库的表结构和迁移逻辑不匹配,进而抛出错误。
解决建议
- 验证
ToDo数据库:用psql -d "ToDo"直接连接,或在命令行中执行\l "ToDo"查看该库。 - 修复
Turkey库迁移问题:- 如果
Turkey库中没有todos表,修改迁移的prepare方法为创建表的逻辑(比如用.create()替代.update(),先创建基础表结构); - 如果已有
todos表,先确认表中是否存在title字段,再调整迁移逻辑; - 也可以先清空
Turkey库中的_fluent_migrations表记录,重新执行适配该库的迁移。
- 如果
内容的提问来源于stack exchange,提问作者Frederick C. Lee
相关产品推荐
相关产品推荐

