FatalError when fetching associated records using dedicated record type #1274
-
Hi 👋 I'm trying to join and prefetch associated records. What I'm trying to achieve is to fetch every Types declaration:struct MuscleGroup: Codable, Identifiable, TableRecord, FetchableRecord, MutablePersistableRecord {
var id: String
static let primaryMuscleGroups = hasMany(PrimaryMuscleGroup.self)
static let primaryExercises = hasMany(
Exercise.self,
through: primaryMuscleGroups,
using: PrimaryMuscleGroup.exercise
)
}
struct Exercise: Codable, Identifiable, TableRecord, FetchableRecord, MutablePersistableRecord {
var id: String
// Primary Muscle Groups
static let primaryMuscleGroups = hasMany(
MuscleGroup.self,
through: Exercise.hasMany(PrimaryMuscleGroup.self),
using: PrimaryMuscleGroup.muscleGroup
)
.forKey("primaryMuscleGroups")
}
struct PrimaryMuscleGroup: Codable, TableRecord, FetchableRecord, MutablePersistableRecord {
var muscleGroupId: String
var exerciseId: String
static let muscleGroup = belongsTo(MuscleGroup.self)
static let exercise = belongsTo(Exercise.self)
} Schema declaration:// 2. Define the database schema
try dbQueue.write { db in
try db.create(table: "muscleGroup") { table in
table.column("id", .text).notNull().unique()
table.primaryKey(["id"])
}
try db.create(table: "exercise") { table in
table.column("id", .text).notNull().unique()
table.primaryKey(["id"])
}
try db.create(table: "primaryMuscleGroup") { table in
table.column("muscleGroupId", .integer).notNull().indexed().references("muscleGroup", onDelete: .cascade)
table.column("exerciseId", .integer).notNull().indexed().references("exercise", onDelete: .cascade)
table.primaryKey(["muscleGroupId", "exerciseId"])
}
} Fetching resultstry dbQueue.read { db in
struct CompleteExercise: Decodable, FetchableRecord {
var exercise: Exercise
var primaryMuscleGroups: [MuscleGroup]
}
let results = try Exercise
.including(all: Exercise.primaryMuscleGroups)
.asRequest(of: CompleteExercise.self)
.fetchAll(db)
} When fetching results, I get a
What am I doing wrong? I've been looking at the documentation for hours now but I must be overlooking something. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
Hello @juliensagot, I don't know if this is a GRDB bug, or if your program behaves as expected - to answer this I'll have to think a little more 😅 The cause of the issue is there: struct Exercise: Codable, Identifiable, TableRecord, FetchableRecord, MutablePersistableRecord {
var id: String
// Primary Muscle Groups
static let primaryMuscleGroups = hasMany(
MuscleGroup.self,
through: Exercise.hasMany(PrimaryMuscleGroup.self), // <- 1
using: PrimaryMuscleGroup.muscleGroup
)
.forKey("primaryMuscleGroups") // <- 2
}
So "primaryMuscleGroups" is the key for two different things: the associated rows from the Are you confused? I surely am 😉 Right now, my suggestion is to lift the ambiguity and rename the intermediate association: struct Exercise: Codable, Identifiable, TableRecord, FetchableRecord, MutablePersistableRecord {
var id: String
// Primary Muscle Groups
static let primaryMuscleGroups = hasMany(
MuscleGroup.self,
through: Exercise
.hasMany(PrimaryMuscleGroup.self)
.forKey("ignored") // Avoid conflict with Exercise.primaryMuscleGroups
using: PrimaryMuscleGroup.muscleGroup
)
.forKey("primaryMuscleGroups")
} This change fixes your issue. You may also find another name for your inner table "primaryMuscleGroup", so that it not named like the Thank you very much for the report! 🙂 The workarounds will have your app run, and I'll have the time to look at this particular setup more closely! |
Beta Was this translation helpful? Give feedback.
-
Wow! Didn't expect such a prompt answer (especially on a Sunday afternoon)! |
Beta Was this translation helpful? Give feedback.
Hello @juliensagot,
I don't know if this is a GRDB bug, or if your program behaves as expected - to answer this I'll have to think a little more 😅
The cause of the issue is there:
Exercise.hasMany(PrimaryMuscleGroup.self)
defines an association with key "primaryMuscleGroups" (the defau…