You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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出现报错,请求解释原因。


问题原因分析

  1. 找不到ToDo数据库但应用正常运行
    PostgreSQL默认区分大小写,你环境变量里的数据库名是ToDo(首字母大写),但PostgreSQL在未加双引号的查询场景下会自动将名称转为小写。实际Vapor创建的数据库是带大小写的ToDo,但你用命令行\l查看时,若未用双引号指定名称,只会显示小写的库名(如果存在的话)。而Vapor连接时会严格按照配置的大小写名称发送请求,所以能正常连接到ToDo库,你在命令行里需要用\l "ToDo"才能查到这个库。

  2. 切换到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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 04:17:04