Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions src/search/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,22 @@ async function withSnippets(
// Key by repo_id:file_path to avoid collisions across repos with identical relative paths
const entriesMap = new Map<string, string>();

if (filePaths.length > 0) {
if (filePaths.length > 0 && resultRepoIds.length > 0) {
if (config.store === "pg") {
// Avoid ANY($n) with array params — Bun.SQL misserialises nested
// arrays. Use IN-list for validated integer repo IDs, placeholders
// for file paths.
for (const id of resultRepoIds) {
if (typeof id !== "number" || !Number.isInteger(id))
throw new Error(`Invalid repo ID: ${String(id)}`);
}
const pathPh = filePaths.map((_, i) => `$${i + 1}`).join(",");
const rows = await withRepoScope(resultRepoIds, async (tx) => {
return (await tx.unsafe(
`SELECT repo_id, file_path, skeleton_entries FROM files
WHERE repo_id = ANY($1)
AND file_path = ANY($2)`,
[resultRepoIds, filePaths],
WHERE repo_id IN (${resultRepoIds.join(",")})
AND file_path IN (${pathPh})`,
filePaths as never[],
)) as { repo_id: string; file_path: string; skeleton_entries: string | null }[];
});
for (const row of rows) {
Expand Down
13 changes: 11 additions & 2 deletions src/search/search-pg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,19 @@ export async function searchPgInTransaction(
if (junctionRows.length > 0) {
const repoIdArr = [...new Set(junctionRows.map((r) => parseInt(r.repo_id)))];
const pathArr = [...new Set(junctionRows.map((r) => r.file_path))];
// Avoid ANY($n) with array params — Bun.SQL misserialises nested
// arrays, causing "number of array dimensions (N) exceeds maximum".
// Use IN-list interpolation for validated integer repo IDs and
// parameterised placeholders for file paths instead.
for (const id of repoIdArr) {
if (typeof id !== "number" || !Number.isInteger(id))
throw new Error(`Invalid repo ID: ${String(id)}`);
}
const pathPlaceholders = pathArr.map((_, i) => `$${i + 1}`).join(",");
const idRows = (await pg.unsafe(
`SELECT id, repo_id, file_path FROM files
WHERE repo_id = ANY($1) AND file_path = ANY($2)`,
[repoIdArr, pathArr] as never[],
WHERE repo_id IN (${repoIdArr.join(",")}) AND file_path IN (${pathPlaceholders})`,
pathArr as never[],
)) as { id: string; repo_id: string; file_path: string }[];
for (const r of idRows) {
idMap.set(`${r.repo_id}:${r.file_path}`, r.id);
Expand Down
Loading