From 9073bc08677f807680db95e1af418178c986d6af Mon Sep 17 00:00:00 2001 From: jiangyq9 Date: Sat, 27 Jun 2026 08:15:57 +0800 Subject: [PATCH] fix(db): chunk resolved reference deletes --- __tests__/db-perf.test.ts | 36 +++++++++++++++++++++++++++++++++++- src/db/queries.ts | 7 +++++-- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/__tests__/db-perf.test.ts b/__tests__/db-perf.test.ts index 1dc3f1eb6..64e7d208a 100644 --- a/__tests__/db-perf.test.ts +++ b/__tests__/db-perf.test.ts @@ -16,7 +16,7 @@ import * as path from 'path'; import * as os from 'os'; import { DatabaseConnection } from '../src/db'; import { QueryBuilder } from '../src/db/queries'; -import { Node } from '../src/types'; +import { Node, UnresolvedReference } from '../src/types'; function makeNode(id: string, name = id): Node { return { @@ -174,6 +174,40 @@ describe('insertEdges endpoint validation', () => { }); }); +describe('deleteResolvedReferences', () => { + let dir: string; + let db: DatabaseConnection; + let q: QueryBuilder; + + beforeEach(() => { + dir = fs.mkdtempSync(path.join(os.tmpdir(), 'db-perf-delete-refs-')); + db = DatabaseConnection.initialize(path.join(dir, 'test.db')); + q = new QueryBuilder(db.getDb()); + }); + + afterEach(() => { + db.close(); + if (fs.existsSync(dir)) fs.rmSync(dir, { recursive: true, force: true }); + }); + + it('handles batches over the SQLite parameter limit when deleting resolved refs', () => { + q.insertNodes(Array.from({ length: 1500 }, (_, i) => makeNode(`n${i}`))); + const refs: UnresolvedReference[] = Array.from({ length: 1500 }, (_, i) => ({ + fromNodeId: `n${i}`, + referenceName: `target${i}`, + referenceKind: 'calls', + line: 1, + column: 0, + filePath: 'a.ts', + language: 'typescript', + })); + q.insertUnresolvedRefsBatch(refs); + + expect(() => q.deleteResolvedReferences(refs.map((ref) => ref.fromNodeId))).not.toThrow(); + expect(q.getUnresolvedReferencesCount()).toBe(0); + }); +}); + describe('runMaintenance', () => { let dir: string; let db: DatabaseConnection; diff --git a/src/db/queries.ts b/src/db/queries.ts index e75b60436..34acd0ba8 100644 --- a/src/db/queries.ts +++ b/src/db/queries.ts @@ -1731,8 +1731,11 @@ export class QueryBuilder { */ deleteResolvedReferences(fromNodeIds: string[]): void { if (fromNodeIds.length === 0) return; - const placeholders = fromNodeIds.map(() => '?').join(','); - this.db.prepare(`DELETE FROM unresolved_refs WHERE from_node_id IN (${placeholders})`).run(...fromNodeIds); + for (let i = 0; i < fromNodeIds.length; i += SQLITE_PARAM_CHUNK_SIZE) { + const chunk = fromNodeIds.slice(i, i + SQLITE_PARAM_CHUNK_SIZE); + const placeholders = chunk.map(() => '?').join(','); + this.db.prepare(`DELETE FROM unresolved_refs WHERE from_node_id IN (${placeholders})`).run(...chunk); + } } /**