I'm a little bit confused about what I might be doing wrong here when trying to setup my Postgres DB using Vapor 4. I'm trying to create tables a database using the Migration API.
This is just a simple dummy project, just for testing purposes. I have an empty database with no tables, running on the default port of 5432 & I'm using PostgresSQL 14 as well.
Below is my current model setup and their migrations.
// Category Model
final class Category: Model, Content, @unchecked Sendable {
static let schema = Schema.categories
@ID(key: .id)
var id: UUID?
@Field(key: "name")
var name: String
@Field(key: "description")
var description: String
@Field(key: "created_at")
var createdAt: Date
@Children(for: \.$category)
var questions: [Question]
init() {}
init(id: UUID? = nil,
name: String,
description: String,
createdAt: Date = .now) {
self.id = id
self.name = name
self.description = description
self.createdAt = createdAt
}
}
// Category Migration
extension Category {
struct CreateCategory: AsyncMigration {
func prepare(on database: any FluentKit.Database) async throws {
try await database.schema(Category.schema)
.id()
.field("name", .string, .required)
.create()
}
func revert(on database: any FluentKit.Database) async throws {
try await database.schema(Category.schema).delete()
}
}
}
// Questions Model
final class Question: Model, Content, @unchecked Sendable {
static let schema = Schema.questions
@ID(key: .id)
var id: UUID?
@Field(key: "text")
var text: String
@Parent(key: "category_id")
var category: Category
init(){ }
init(id: UUID,
text: String,
categoryID: Category.IDValue) {
self.id = id
self.text = text
self.category.id = categoryID
}
}
// Questions Migration
extension Question {
struct CreateQuestion: AsyncMigration {
func prepare(on database: any FluentKit.Database) async throws {
try await database.schema(Question.schema)
.id()
.field("text", .string, .required)
.field("category_id", .uuid, .references("category", "id"))
.create()
}
func revert(on database: any FluentKit.Database) async throws {
try await database.schema(Question.schema).delete()
}
}
}
I have verified and I'm able to successfully connect to my database within my configure function, and I have also added the migrations to create the tables and any relationships. Since a question can belong to one or more categories. This is the relationship between the two tables.
guard let host = Environment.get("DATABASE_HOST"),
let dbPort = Environment.get("DATABASE_PORT"),
let port = Int(dbPort),
let username = Environment.get("DATABASE_USERNAME"),
let password = Environment.get("DATABASE_PASSWORD"),
let database = Environment.get("DATABASE_NAME") else {
app.logger.error("Missing ENV configuration")
throw Abort(.internalServerError, reason: "Database configuration missing")
}
app.databases.use(
.postgres(
configuration: .init(
hostname: host,
port: port,
username: username,
password: password,
database: database,
tls: .disable
)
),
as: .psql)
app.logger.info("Creating database migration...")
app.migrations.add(Category.CreateCategory.init(), to: .psql)
app.migrations.add(Question.CreateQuestion.init(), to: .psql)
app.logger.info("Setting up routes...")
try routes(app)
When I execute the command to run the migration to create the tables
swift run App migrate
I'm getting the following error in the terminal
[ INFO ] [Migrator] Starting prepare [database-id: psql, migration: App.Category.CreateCategory]
[ INFO ] [Migrator] Finished prepare [database-id: psql, migration: App.Category.CreateCategory]
[ INFO ] [Migrator] Starting prepare [database-id: psql, migration: App.Question.CreateQuestion]
[ ERROR ] [Migrator] Failed prepare [database-id: psql, error: PSQLError(code: server, serverInfo: [sqlState: 42P01, file: namespace.c, line: 624, message: relation "category" does not exist, routine: RangeVarGetRelidExtended, localizedSeverity: ERROR, severity: ERROR], triggeredFromRequestInFile: PostgresKit/PostgresDatabase+SQL.swift, line: 57, query: PostgresQuery(sql: CREATE TABLE "questions" ("id" UUID PRIMARY KEY, "text" TEXT NOT NULL, "category_id" UUID REFERENCES "category" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION), binds: [])), migration: App.Question.CreateQuestion]
[ WARNING ] PSQLError(code: server, serverInfo: [sqlState: 42P01, file: namespace.c, line: 624, message: relation "category" does not exist, routine: RangeVarGetRelidExtended, localizedSeverity: ERROR, severity: ERROR], triggeredFromRequestInFile: PostgresKit/PostgresDatabase+SQL.swift, line: 57, query: PostgresQuery(sql: CREATE TABLE "questions" ("id" UUID PRIMARY KEY, "text" TEXT NOT NULL, "category_id" UUID REFERENCES "category" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION), binds: []))
[ ERROR ] Application.shutdown() was not called before Application deinitialized.
Vapor/ServeCommand.swift:131: Assertion failed: ServeCommand did not shutdown before deinit
zsh: trace trap swift run App migrate
Am I possibly misunderstanding the API? Since following the relation guide my models are super simple and I would of thought this would create two tables, where there is a one to many relationship.