fix(db): accumulate many-includes and nest relations in prisma facade
Co-authored-by: Cursor <[email protected]>
This commit is contained in:
+46
-10
@@ -270,24 +270,36 @@ async function queryRelationRows(
|
||||
rel: any,
|
||||
opts: any,
|
||||
keyValues: unknown[],
|
||||
mode: "one" | "many",
|
||||
): Promise<Map<string, any>> {
|
||||
const join = resolveJoin(table, rel);
|
||||
const byCol = join.fkCols[0];
|
||||
const condition = inArray(byCol, coerceArray(byCol, keyValues));
|
||||
const parts = [
|
||||
inArray(byCol, coerceArray(byCol, keyValues)),
|
||||
buildCondition(rel.referencedTable, opts.where),
|
||||
].filter(Boolean);
|
||||
const condition = parts.length === 1 ? parts[0] : and(...parts);
|
||||
const sel = projection(rel.referencedTable, opts.select);
|
||||
const orderBy = buildOrderBy(rel.referencedTable, opts.orderBy);
|
||||
|
||||
let stmt: any = sel
|
||||
? client.select({ ...sel, __fk: byCol }).from(rel.referencedTable)
|
||||
: client.select().from(rel.referencedTable);
|
||||
stmt = stmt.where(condition);
|
||||
if (condition) stmt = stmt.where(condition);
|
||||
if (orderBy.length) stmt = stmt.orderBy(...orderBy);
|
||||
|
||||
const rows = (await stmt) as any[];
|
||||
const map = new Map<string, any>();
|
||||
for (const row of rows) {
|
||||
const key = row.__fk ?? row[colKey(byCol)];
|
||||
map.set(String(key), sel ? pickRow(row, opts.select) : row);
|
||||
const key = String(row.__fk ?? row[colKey(byCol)]);
|
||||
const cleaned = sel ? pickRow(row, opts.select) : row;
|
||||
if (mode === "many") {
|
||||
const list = map.get(key);
|
||||
if (Array.isArray(list)) list.push(cleaned);
|
||||
else map.set(key, [cleaned]);
|
||||
} else if (!map.has(key)) {
|
||||
map.set(key, cleaned);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
@@ -386,13 +398,25 @@ async function attachIncludes(
|
||||
for (const row of rows) row[rel.fieldName] = null;
|
||||
continue;
|
||||
}
|
||||
const map = await queryRelationRows(client, table, rel, opts, values);
|
||||
const map = await queryRelationRows(
|
||||
client,
|
||||
table,
|
||||
rel,
|
||||
opts,
|
||||
values,
|
||||
"one",
|
||||
);
|
||||
const join = resolveJoin(table, rel);
|
||||
const refCol = join.refCols[0];
|
||||
const related: any[] = [];
|
||||
for (const row of rows) {
|
||||
const refValue = row[colKey(refCol)];
|
||||
row[rel.fieldName] =
|
||||
refValue == null ? null : (map.get(String(refValue)) ?? null);
|
||||
const hit = refValue == null ? null : (map.get(String(refValue)) ?? null);
|
||||
row[rel.fieldName] = hit;
|
||||
if (hit) related.push(hit);
|
||||
}
|
||||
if (opts.include && related.length > 0) {
|
||||
await attachIncludes(client, rel.referencedTable, related, opts.include);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,13 +426,25 @@ async function attachIncludes(
|
||||
for (const row of rows) row[rel.fieldName] = [];
|
||||
continue;
|
||||
}
|
||||
const map = await queryRelationRows(client, table, rel, opts, values);
|
||||
const map = await queryRelationRows(
|
||||
client,
|
||||
table,
|
||||
rel,
|
||||
opts,
|
||||
values,
|
||||
"many",
|
||||
);
|
||||
const join = resolveJoin(table, rel);
|
||||
const refCol = join.refCols[0];
|
||||
const related: any[] = [];
|
||||
for (const row of rows) {
|
||||
const refValue = row[colKey(refCol)];
|
||||
row[rel.fieldName] =
|
||||
refValue == null ? [] : (map.get(String(refValue)) ?? []);
|
||||
const list = refValue == null ? [] : (map.get(String(refValue)) ?? []);
|
||||
row[rel.fieldName] = list;
|
||||
for (const item of list) related.push(item);
|
||||
}
|
||||
if (opts.include && related.length > 0) {
|
||||
await attachIncludes(client, rel.referencedTable, related, opts.include);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user