Skip to content

Commit 6a62a2c

Browse files
authored
fix: issue with in memory distinct when distinct fields are not selected (#144)
* fix: issue with in memory distinct when distinct fields are not selected * addressing PR comments
1 parent 192cc01 commit 6a62a2c

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

packages/runtime/src/client/crud/operations/base.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,21 @@ export abstract class BaseOperationHandler<Schema extends SchemaDef> {
177177
// distinct
178178
let inMemoryDistinct: string[] | undefined = undefined;
179179
if (args?.distinct) {
180-
const distinct = ensureArray(args.distinct);
180+
const distinct = ensureArray(args.distinct) as string[];
181181
if (this.dialect.supportsDistinctOn) {
182-
query = query.distinctOn(distinct.map((f: any) => sql.ref(`${model}.${f}`)));
182+
query = query.distinctOn(distinct.map((f) => sql.ref(`${model}.${f}`)));
183183
} else {
184184
// in-memory distinct after fetching all results
185185
inMemoryDistinct = distinct;
186+
187+
// make sure distinct fields are selected
188+
query = distinct.reduce(
189+
(acc, field) =>
190+
acc.select((eb) =>
191+
buildFieldRef(this.schema, model, field, this.options, eb).as(`$distinct$${field}`),
192+
),
193+
query,
194+
);
186195
}
187196
}
188197

@@ -225,13 +234,20 @@ export abstract class BaseOperationHandler<Schema extends SchemaDef> {
225234
const distinctResult: Record<string, unknown>[] = [];
226235
const seen = new Set<string>();
227236
for (const r of result as any[]) {
228-
const key = safeJSONStringify(inMemoryDistinct.map((f) => r[f]))!;
237+
const key = safeJSONStringify(inMemoryDistinct.map((f) => r[`$distinct$${f}`]))!;
229238
if (!seen.has(key)) {
230239
distinctResult.push(r);
231240
seen.add(key);
232241
}
233242
}
234243
result = distinctResult;
244+
245+
// clean up distinct utility fields
246+
for (const r of result) {
247+
Object.keys(r)
248+
.filter((k) => k.startsWith('$distinct$'))
249+
.forEach((k) => delete r[k]);
250+
}
235251
}
236252

237253
return result;

packages/runtime/test/client-api/find.test.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ describe.each(createClientSpecs(PG_DB_NAME))('Client find tests for $provider',
244244
await createUser(client, '[email protected]', {
245245
name: 'Admin1',
246246
role: 'ADMIN',
247+
profile: { create: { bio: 'Bio1' } },
247248
});
248249
await createUser(client, '[email protected]', {
249250
name: 'User',
@@ -252,14 +253,15 @@ describe.each(createClientSpecs(PG_DB_NAME))('Client find tests for $provider',
252253
await createUser(client, '[email protected]', {
253254
name: 'Admin2',
254255
role: 'ADMIN',
256+
profile: { create: { bio: 'Bio1' } },
255257
});
256258
await createUser(client, '[email protected]', {
257259
name: 'User',
258260
role: 'USER',
259261
});
260262

261263
// single field distinct
262-
let r = await client.user.findMany({ distinct: ['role'] });
264+
let r: any = await client.user.findMany({ distinct: ['role'] });
263265
expect(r).toHaveLength(2);
264266
expect(r).toEqual(
265267
expect.arrayContaining([
@@ -268,6 +270,21 @@ describe.each(createClientSpecs(PG_DB_NAME))('Client find tests for $provider',
268270
]),
269271
);
270272

273+
// distinct with include
274+
r = await client.user.findMany({ distinct: ['role'], include: { profile: true } });
275+
expect(r).toHaveLength(2);
276+
expect(r).toEqual(
277+
expect.arrayContaining([
278+
expect.objectContaining({ role: 'ADMIN', profile: expect.any(Object) }),
279+
expect.objectContaining({ role: 'USER', profile: null }),
280+
]),
281+
);
282+
283+
// distinct with select
284+
r = await client.user.findMany({ distinct: ['role'], select: { email: true } });
285+
expect(r).toHaveLength(2);
286+
expect(r).toEqual(expect.arrayContaining([{ email: expect.any(String) }, { email: expect.any(String) }]));
287+
271288
// multiple fields distinct
272289
r = await client.user.findMany({
273290
distinct: ['role', 'name'],

0 commit comments

Comments
 (0)