Skip to content

Commit 3bb85a0

Browse files
kevin-dpclaude
andcommitted
Add failing test for shared correlation key with orderBy + limit
Reproduces the bug where grouped ordering for limit uses the raw correlation key instead of the composite routing key, causing parents that share a correlation key but differ on parent-referenced filters to have their children merged before the limit is applied. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent fcb841d commit 3bb85a0

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed

packages/db/tests/query/includes.test.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,78 @@ describe(`includes subqueries`, () => {
11601160
])
11611161
})
11621162

1163+
it(`shared correlation key with parent filter + orderBy + limit`, async () => {
1164+
// Regression: grouped ordering for limit must use the composite routing
1165+
// key, not the raw correlation key. Otherwise two parents that share the
1166+
// same correlation key but differ on the parent-referenced filter get
1167+
// their children merged before the limit is applied.
1168+
type GroupParent = {
1169+
id: number
1170+
groupId: number
1171+
createdBy: string
1172+
}
1173+
1174+
type GroupChild = {
1175+
id: number
1176+
groupId: number
1177+
createdBy: string
1178+
}
1179+
1180+
const parents = createCollection(
1181+
mockSyncCollectionOptions<GroupParent>({
1182+
id: `limit-corr-parents`,
1183+
getKey: (p) => p.id,
1184+
initialData: [
1185+
{ id: 1, groupId: 1, createdBy: `alice` },
1186+
{ id: 2, groupId: 1, createdBy: `bob` },
1187+
],
1188+
}),
1189+
)
1190+
1191+
const children = createCollection(
1192+
mockSyncCollectionOptions<GroupChild>({
1193+
id: `limit-corr-children`,
1194+
getKey: (c) => c.id,
1195+
initialData: [
1196+
{ id: 10, groupId: 1, createdBy: `alice` },
1197+
{ id: 11, groupId: 1, createdBy: `bob` },
1198+
],
1199+
}),
1200+
)
1201+
1202+
const collection = createLiveQueryCollection((q) =>
1203+
q.from({ p: parents }).select(({ p }) => ({
1204+
id: p.id,
1205+
createdBy: p.createdBy,
1206+
items: q
1207+
.from({ c: children })
1208+
.where(({ c }) => eq(c.groupId, p.groupId))
1209+
.where(({ c }) => eq(c.createdBy, p.createdBy))
1210+
.orderBy(({ c }) => c.id, `asc`)
1211+
.limit(1)
1212+
.select(({ c }) => ({
1213+
id: c.id,
1214+
createdBy: c.createdBy,
1215+
})),
1216+
})),
1217+
)
1218+
1219+
await collection.preload()
1220+
1221+
expect(toTree(collection)).toEqual([
1222+
{
1223+
id: 1,
1224+
createdBy: `alice`,
1225+
items: [{ id: 10, createdBy: `alice` }],
1226+
},
1227+
{
1228+
id: 2,
1229+
createdBy: `bob`,
1230+
items: [{ id: 11, createdBy: `bob` }],
1231+
},
1232+
])
1233+
})
1234+
11631235
it(`extracts correlation from and() with more than 2 args`, async () => {
11641236
const collection = createLiveQueryCollection((q) =>
11651237
q.from({ p: projectsWC }).select(({ p }) => ({

0 commit comments

Comments
 (0)