Replace all symbols for a file atomically.
(
path: string,
language: string,
mtimeMs: number,
sizeBytes: number,
contentHash: string | null,
symbols: ExtractedSymbol[],
)
| 109 | |
| 110 | /** Replace all symbols for a file atomically. */ |
| 111 | replaceFileSymbols( |
| 112 | path: string, |
| 113 | language: string, |
| 114 | mtimeMs: number, |
| 115 | sizeBytes: number, |
| 116 | contentHash: string | null, |
| 117 | symbols: ExtractedSymbol[], |
| 118 | ): void { |
| 119 | const tx = this.db.transaction(() => { |
| 120 | this.upsertFile.run(path, language, mtimeMs, sizeBytes, contentHash); |
| 121 | const fileRow = this.findFileByPath.get(path) as FileRow; |
| 122 | this.deleteSymbolsForFile.run(fileRow.id); |
| 123 | // Two-pass: first insert all symbols, then resolve parent IDs by name within this file |
| 124 | const nameToId = new Map<string, number>(); |
| 125 | for (const s of symbols) { |
| 126 | const result = this.insertSymbol.run( |
| 127 | fileRow.id, |
| 128 | s.name, |
| 129 | s.kind, |
| 130 | s.startLine, |
| 131 | s.endLine, |
| 132 | s.startColumn, |
| 133 | null, // resolved below |
| 134 | s.signature ?? null, |
| 135 | ); |
| 136 | nameToId.set(`${s.kind}:${s.name}`, result.lastInsertRowid as number); |
| 137 | } |
| 138 | // Second pass: link parents |
| 139 | const updateParent = this.db.prepare(`UPDATE symbols SET parent_symbol_id = ? WHERE id = ?`); |
| 140 | for (const s of symbols) { |
| 141 | if (!s.parentName) continue; |
| 142 | const childId = nameToId.get(`${s.kind}:${s.name}`); |
| 143 | // Match parent by name (any kind) within the same file |
| 144 | const parentSym = this.db.prepare( |
| 145 | `SELECT id FROM symbols WHERE file_id = ? AND name = ? LIMIT 1`, |
| 146 | ).get(fileRow.id, s.parentName) as { id: number } | undefined; |
| 147 | if (childId !== undefined && parentSym) { |
| 148 | updateParent.run(parentSym.id, childId); |
| 149 | } |
| 150 | } |
| 151 | }); |
| 152 | tx(); |
| 153 | } |
| 154 | |
| 155 | removeFile(path: string): void { |
| 156 | this.deleteFileByPath.run(path); |