Skip to content

Commit b832cd6

Browse files
committed
Use including to more efficiently load products with associated values
Products and variations with attributes are 2x faster loaded when using included
1 parent 96c7d30 commit b832cd6

File tree

1 file changed

+28
-16
lines changed

1 file changed

+28
-16
lines changed

Modules/Sources/Yosemite/PointOfSale/Items/GRDBObservableDataSource.swift

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -118,18 +118,24 @@ public final class GRDBObservableDataSource: POSObservableDataSourceProtocol {
118118
.tracking { [weak self] database -> [POSProduct] in
119119
guard let self else { return [] }
120120

121-
let persistedProducts = try PersistedProduct
121+
struct ProductWithRelations: Decodable, FetchableRecord {
122+
let product: PersistedProduct
123+
let images: [PersistedImage]?
124+
let attributes: [PersistedProductAttribute]?
125+
}
126+
127+
let productsWithRelations = try PersistedProduct
122128
.posProductsRequest(siteID: siteID)
123129
.limit(pageSize * currentPage)
130+
.including(all: PersistedProduct.images)
131+
.including(all: PersistedProduct.attributes)
132+
.asRequest(of: ProductWithRelations.self)
124133
.fetchAll(database)
125134

126-
return try persistedProducts.map { persistedProduct in
127-
let images = try persistedProduct.request(for: PersistedProduct.images).fetchAll(database)
128-
let attributes = try persistedProduct.request(for: PersistedProduct.attributes).fetchAll(database)
129-
130-
return persistedProduct.toPOSProduct(
131-
images: images.map { $0.toProductImage() },
132-
attributes: attributes.map { $0.toProductAttribute(siteID: persistedProduct.siteID) }
135+
return productsWithRelations.map { record in
136+
record.product.toPOSProduct(
137+
images: (record.images ?? []).map { $0.toProductImage() },
138+
attributes: (record.attributes ?? []).map { $0.toProductAttribute(siteID: record.product.siteID) }
133139
)
134140
}
135141
}
@@ -160,18 +166,24 @@ public final class GRDBObservableDataSource: POSObservableDataSourceProtocol {
160166
.tracking { [weak self] database -> [POSProductVariation] in
161167
guard let self else { return [] }
162168

163-
let persistedVariations = try PersistedProductVariation
169+
struct VariationWithRelations: Decodable, FetchableRecord {
170+
let persistedProductVariation: PersistedProductVariation
171+
let attributes: [PersistedProductVariationAttribute]?
172+
let image: PersistedImage?
173+
}
174+
175+
let variationsWithRelations = try PersistedProductVariation
164176
.posVariationsRequest(siteID: self.siteID, parentProductID: parentProduct.productID)
165177
.limit(self.pageSize * currentPage)
178+
.including(all: PersistedProductVariation.attributes)
179+
.including(optional: PersistedProductVariation.image)
180+
.asRequest(of: VariationWithRelations.self)
166181
.fetchAll(database)
167182

168-
return try persistedVariations.map { persistedVariation in
169-
let attributes = try persistedVariation.request(for: PersistedProductVariation.attributes).fetchAll(database)
170-
let image = try persistedVariation.request(for: PersistedProductVariation.image).fetchOne(database)
171-
172-
return persistedVariation.toPOSProductVariation(
173-
attributes: attributes.map { $0.toProductVariationAttribute() },
174-
image: image?.toProductImage()
183+
return variationsWithRelations.map { record in
184+
record.persistedProductVariation.toPOSProductVariation(
185+
attributes: (record.attributes ?? []).map { $0.toProductVariationAttribute() },
186+
image: record.image?.toProductImage()
175187
)
176188
}
177189
}

0 commit comments

Comments
 (0)