|
1 | 1 | import { Constructor, Context, DAL } from "@medusajs/framework/types" |
2 | 2 | import { MikroOrmBaseRepository, toMikroORMEntity } from "@medusajs/framework/utils" |
3 | | -import { LoadStrategy } from "@medusajs/framework/mikro-orm/core" |
| 3 | +import { LoadStrategy, raw } from "@medusajs/framework/mikro-orm/core" |
4 | 4 | import { Order, OrderClaim, OrderLineItemAdjustment } from "@models" |
5 | 5 |
|
6 | 6 | import { mapRepositoryToOrderModel } from "." |
@@ -116,7 +116,13 @@ export function setFindMethods<T>(klass: Constructor<T>, entity: any) { |
116 | 116 | const version = config.where?.version ?? defaultVersion |
117 | 117 | delete config.where?.version |
118 | 118 |
|
119 | | - configurePopulateWhere(config, isRelatedEntity, version) |
| 119 | + configurePopulateWhere( |
| 120 | + config, |
| 121 | + isRelatedEntity, |
| 122 | + version, |
| 123 | + strategy === LoadStrategy.SELECT_IN, |
| 124 | + manager |
| 125 | + ) |
120 | 126 |
|
121 | 127 | let loadAdjustments = false |
122 | 128 | if (config.options.populate.includes("items.item.adjustments")) { |
@@ -253,11 +259,16 @@ export function setFindMethods<T>(klass: Constructor<T>, entity: any) { |
253 | 259 | }) |
254 | 260 | } |
255 | 261 |
|
256 | | - const [result, count] = await manager.findAndCount( |
257 | | - this.entity, |
258 | | - config.where, |
259 | | - config.options |
260 | | - ) |
| 262 | + // The count query uses JOINED strategy internally (MikroORM 6.6+), but |
| 263 | + // populateWhere version subqueries reference SELECT_IN aliases (e.g. "o0") |
| 264 | + // that don't exist in the JOINED count context. Since version filters only |
| 265 | + // control which items to load (not which root entities to count), we run |
| 266 | + // find and count separately with different populateWhere options. |
| 267 | + const countOptions = { ...config.options, populateWhere: undefined } |
| 268 | + const [result, count] = await Promise.all([ |
| 269 | + manager.find(this.entity, config.where, config.options), |
| 270 | + manager.count(this.entity, config.where, countOptions), |
| 271 | + ]) |
261 | 272 |
|
262 | 273 | if (loadAdjustments) { |
263 | 274 | const orders = !isRelatedEntity |
@@ -339,36 +350,65 @@ function configurePopulateWhere( |
339 | 350 | config.options.populateWhere ??= {} |
340 | 351 | const popWhere = config.options.populateWhere |
341 | 352 |
|
342 | | - // isSelectIn && isRelatedEntity - Order is always the FROM clause (field o0.id) |
343 | 353 | if (isRelatedEntity) { |
344 | 354 | popWhere.order ??= {} |
345 | 355 |
|
346 | 356 | const popWhereOrder = popWhere.order |
347 | 357 |
|
348 | | - popWhereOrder.version = isSelectIn |
349 | | - ? getVersionSubQuery(manager, "o0", "id") |
350 | | - : version |
| 358 | + if (!isSelectIn) { |
| 359 | + // For JOINED strategy, version is a reference to the order alias (e.g. "o1"."version") |
| 360 | + // This is trivially true since Order has one row per id, but kept for consistency |
| 361 | + popWhereOrder.version = version |
| 362 | + } |
| 363 | + // For SELECT_IN strategy, the order.version condition is always trivially true |
| 364 | + // (Order has one row per id) so we skip it entirely |
351 | 365 |
|
352 | 366 | // related entity shipping method |
353 | 367 | if (hasRelation("shipping_methods")) { |
354 | 368 | popWhere.shipping_methods ??= {} |
355 | | - popWhere.shipping_methods.version = isSelectIn |
356 | | - ? getVersionSubQuery(manager, "s0") |
357 | | - : version |
| 369 | + if (isSelectIn) { |
| 370 | + // For MikroORM 6.6.x+, populateWhere conditions for force-joined relations are |
| 371 | + // embedded as inline JOIN conditions. Use alias callback so [::alias::] gets |
| 372 | + // replaced with the actual shipping_method alias at query-build time. |
| 373 | + const fragment = raw( |
| 374 | + (alias) => |
| 375 | + `"${alias}"."version" = (select "_sub0"."version" from "order" as "_sub0" where "_sub0"."id" = "${alias}"."order_id")` |
| 376 | + ) |
| 377 | + ;(popWhere.shipping_methods as any)[fragment.toString()] = [] |
| 378 | + } else { |
| 379 | + popWhere.shipping_methods.version = version |
| 380 | + } |
358 | 381 | } |
359 | 382 |
|
360 | 383 | if (hasRelation("items") || hasRelation("order.items")) { |
361 | 384 | popWhereOrder.items ??= {} |
362 | | - popWhereOrder.items.version = isSelectIn |
363 | | - ? getVersionSubQuery(manager, "o0", "id") |
364 | | - : version |
| 385 | + if (isSelectIn) { |
| 386 | + // In MikroORM 6.6.x+, the global alias counter changed (no longer per-entity-type), |
| 387 | + // so "o0" no longer exists in the query context for related entity queries. |
| 388 | + // Instead, use a self-referential raw fragment: the [::alias::] placeholder is |
| 389 | + // replaced with the order_item's own JOIN alias, and order_item.order_id is used |
| 390 | + // to look up the order's current version. |
| 391 | + const fragment = raw( |
| 392 | + (alias) => |
| 393 | + `"${alias}"."version" = (select "_sub0"."version" from "order" as "_sub0" where "_sub0"."id" = "${alias}"."order_id")` |
| 394 | + ) |
| 395 | + ;(popWhereOrder.items as any)[fragment.toString()] = [] |
| 396 | + } else { |
| 397 | + popWhereOrder.items.version = version |
| 398 | + } |
365 | 399 | } |
366 | 400 |
|
367 | 401 | if (hasRelation("shipping_methods")) { |
368 | 402 | popWhereOrder.shipping_methods ??= {} |
369 | | - popWhereOrder.shipping_methods.version = isSelectIn |
370 | | - ? getVersionSubQuery(manager, "o0", "id") |
371 | | - : version |
| 403 | + if (isSelectIn) { |
| 404 | + const fragment = raw( |
| 405 | + (alias) => |
| 406 | + `"${alias}"."version" = (select "_sub0"."version" from "order" as "_sub0" where "_sub0"."id" = "${alias}"."order_id")` |
| 407 | + ) |
| 408 | + ;(popWhereOrder.shipping_methods as any)[fragment.toString()] = [] |
| 409 | + } else { |
| 410 | + popWhereOrder.shipping_methods.version = version |
| 411 | + } |
372 | 412 | } |
373 | 413 |
|
374 | 414 | return |
|
0 commit comments