Hello @remcopoelstra,
This becomes a frequently asked question, it's high time the documentation addresses it as clearly as possible.
My answer is in two steps:
- Why ElementWithApertureData does not fit the request.
- How to rewrite the request so that it can feed ElementWithApertureData.
The request, as written, can decode a struct like this:
struct ElementWithApertureData: Decodable, FetchableRecord {
struct RestrictedAperture: Decodable {
var polygonData: Data
}
let element: Element
let aperture: RestrictedAperture?
}
let request = Element
.including(optional: Element.aperture.select(Column("polygonData")))
To understand why, consider that the select
method in including(association.select(...))
accepts several columns: those are naturally gathered in their own struct. The one-column case is no different.
And that's why you don't see the polygonData
column in the row in the debugger. You only see it in the "unadapted" (all columns) and "aperture" scope, hidden from the row exposed to ElementWithApertureData.
But you want a single column from the association, and avoid this nested struct.
The solution is to flatten joined columns with annotated(with:)
:
struct ElementWithApertureData: Decodable, FetchableRecord {
let element: Element
let polygonData: Data?
}
let apertureAlias = TableAlias()
let request = Element
.annotated(with: apertureAlias[Column("polygonData")])
.joining(optional: Element.aperture.aliased(apertureAlias))
By using annotated(with:)
, the extra columns are made available for your top-level record.
By using a TableAlias, you can refer to tables used elsewhere in the request, and pick their columns.
By replacing including
by joining
, you do not append the default selected columns of Aperture to your request. The columns are selected by annotated(with:)
.