1use rusqlite::Connection;
2
3#[path = "code_query.rs"]
4mod code_query;
5
6#[path = "code_query_prepare.rs"]
7mod code_query_prepare;
8
9#[path = "code_query_hits.rs"]
10mod code_query_hits;
11
12#[path = "code_feature_flags.rs"]
13mod code_feature_flags;
14
15#[path = "code_query_scope.rs"]
16mod code_query_scope;
17
18#[path = "code_impact.rs"]
19mod code_impact;
20
21#[path = "code_report.rs"]
22mod code_report;
23
24#[path = "code_schema.rs"]
25mod code_schema;
26
27#[path = "code_status.rs"]
28mod code_status;
29
30#[path = "code_batch.rs"]
31mod code_batch;
32
33#[path = "code_cleanup.rs"]
34mod code_cleanup;
35
36#[path = "code_tasks.rs"]
37mod code_tasks;
38
39#[path = "code_search.rs"]
40mod code_search;
41
42#[path = "code_snapshot.rs"]
43mod code_snapshot;
44
45#[path = "code_set.rs"]
46mod code_set;
47
48#[path = "code_set_tasks.rs"]
49mod code_set_tasks;
50
51#[cfg(test)]
52#[path = "code_tests.rs"]
53mod code_tests;
54
55#[cfg(test)]
56#[path = "code_snapshot_candidate_paths_tests.rs"]
57mod code_snapshot_candidate_paths_tests;
58
59#[cfg(test)]
60#[path = "code_incremental_search_tests.rs"]
61mod code_incremental_search_tests;
62
63#[cfg(test)]
64#[path = "code_batch_finalize_tests.rs"]
65mod code_batch_finalize_tests;
66
67#[cfg(test)]
68#[path = "code_batch_finalize_typescript_tests.rs"]
69mod code_batch_finalize_typescript_tests;
70
71#[cfg(test)]
72#[path = "code_cross_language_call_tests.rs"]
73mod code_cross_language_call_tests;
74
75#[cfg(test)]
76#[path = "code_batch_search_tests.rs"]
77mod code_batch_search_tests;
78
79#[cfg(test)]
80#[path = "code_snapshot_progress_tests.rs"]
81mod code_snapshot_progress_tests;
82
83#[cfg(test)]
84#[path = "code_query_accuracy_tests.rs"]
85mod code_query_accuracy_tests;
86
87#[cfg(test)]
88#[path = "code_query_import_target_tests.rs"]
89mod code_query_import_target_tests;
90
91#[cfg(test)]
92#[path = "code_query_import_ranking_tests.rs"]
93mod code_query_import_ranking_tests;
94
95#[cfg(test)]
96#[path = "code_query_sbom_tests.rs"]
97mod code_query_sbom_tests;
98
99#[cfg(test)]
100#[path = "code_query_line_context_tests.rs"]
101mod code_query_line_context_tests;
102
103#[cfg(test)]
104#[path = "code_metadata_tests.rs"]
105mod code_metadata_tests;
106
107#[cfg(test)]
108#[path = "code_tasks_tests.rs"]
109mod code_tasks_tests;
110
111#[cfg(test)]
112#[path = "code_set_tasks_tests.rs"]
113mod code_set_tasks_tests;
114
115#[cfg(test)]
116#[path = "code_set_tests.rs"]
117mod code_set_tests;
118
119use crate::{
120 domain::{
121 CodeFeatureFlagGraph, CodeFeatureFlagRequest, CodeFileFingerprint, CodeImpactRequest,
122 CodeIndexBatch, CodeIndexCheckpoint, CodeIndexSession, CodeIndexSnapshot, CodeIndexSummary,
123 CodeRepositoryRegistration, CodeRepositoryReport, CodeRepositoryStatus,
124 CodeRepositoryTotals, CodeRetrievalHit, CodeRetrievalRequest,
125 },
126 storage::{CodeImpactChanges, CodeRepositoryStore, StorageError, StorageFuture},
127};
128
129use super::SqliteGraphStore;
130pub(super) use code_search::SearchDocumentInserter;
131
132const MAX_SYMBOL_SIGNATURE_LOOKUP_IDS_PER_STATEMENT: usize = 500;
133
134pub(super) fn initialize_code_schema(connection: &Connection) -> Result<(), StorageError> {
135 code_schema::initialize_code_schema(connection)
136}
137
138impl CodeRepositoryStore for SqliteGraphStore {
139 fn upsert_code_repository(
140 &self,
141 registration: CodeRepositoryRegistration,
142 ) -> StorageFuture<'_, CodeRepositoryStatus> {
143 self.run(move |connection| code_status::upsert_repository(connection, registration))
144 }
145
146 fn code_repository_status(
147 &self,
148 repository: String,
149 ) -> StorageFuture<'_, Option<CodeRepositoryStatus>> {
150 self.run(move |connection| code_status::repository_status(connection, &repository))
151 }
152
153 fn code_repository_scope_status(
154 &self,
155 repository: String,
156 resolved_commit_sha: String,
157 path_filters: Vec<String>,
158 language_filters: Vec<String>,
159 ) -> StorageFuture<'_, Option<CodeRepositoryStatus>> {
160 self.run(move |connection| {
161 code_status::repository_scope_status(
162 connection,
163 &repository,
164 &resolved_commit_sha,
165 &path_filters,
166 &language_filters,
167 )
168 })
169 }
170
171 fn queue_code_index_task(
172 &self,
173 task: crate::storage::CodeIndexTaskSeed,
174 ) -> StorageFuture<'_, crate::domain::CodeIndexTaskRecord> {
175 self.run(move |connection| code_tasks::queue_task(connection, task))
176 }
177
178 fn claim_code_index_task(
179 &self,
180 request: crate::storage::CodeIndexTaskClaimRequest,
181 ) -> StorageFuture<'_, Option<crate::domain::CodeIndexTaskRecord>> {
182 self.run(move |connection| code_tasks::claim_task(connection, request))
183 }
184
185 fn recover_code_index_task_leases(
186 &self,
187 now_ms: u64,
188 max_attempts: u32,
189 ) -> StorageFuture<'_, ()> {
190 self.run(move |connection| {
191 code_tasks::recover_expired_task_leases(connection, now_ms, max_attempts)
192 })
193 }
194
195 fn renew_code_index_task_lease(
196 &self,
197 request: crate::storage::CodeIndexTaskLeaseRenewal,
198 ) -> StorageFuture<'_, crate::domain::CodeIndexTaskRecord> {
199 self.run(move |connection| code_tasks::renew_task_lease(connection, request))
200 }
201
202 fn complete_code_index_task(
203 &self,
204 request: crate::storage::CodeIndexTaskCompletion,
205 ) -> StorageFuture<'_, crate::domain::CodeIndexTaskRecord> {
206 self.run(move |connection| code_tasks::complete_task(connection, request))
207 }
208
209 fn fail_code_index_task(
210 &self,
211 request: crate::storage::CodeIndexTaskFailure,
212 ) -> StorageFuture<'_, crate::domain::CodeIndexTaskRecord> {
213 self.run(move |connection| code_tasks::fail_task(connection, request))
214 }
215
216 fn code_index_task(
217 &self,
218 task_id: String,
219 ) -> StorageFuture<'_, Option<crate::domain::CodeIndexTaskRecord>> {
220 self.run(move |connection| code_tasks::task_by_id(connection, &task_id))
221 }
222
223 fn active_code_index_task(
224 &self,
225 repository_id: String,
226 ) -> StorageFuture<'_, Option<crate::domain::CodeIndexTaskRecord>> {
227 self.run(move |connection| code_tasks::active_task(connection, &repository_id))
228 }
229
230 fn code_index_checkpoint(
231 &self,
232 source_scope: String,
233 ) -> StorageFuture<'_, Option<crate::domain::CodeIndexCheckpoint>> {
234 self.run(move |connection| code_tasks::checkpoint(connection, &source_scope))
235 }
236
237 fn code_scope_retention(
238 &self,
239 repository_id: String,
240 ) -> StorageFuture<'_, crate::domain::CodeScopeRetentionSummary> {
241 self.run(move |connection| code_tasks::retention_status(connection, &repository_id))
242 }
243
244 fn prune_code_repository_scopes(
245 &self,
246 request: crate::storage::CodeScopeRetentionRequest,
247 ) -> StorageFuture<'_, crate::domain::CodeScopeRetentionSummary> {
248 self.run(move |connection| code_tasks::prune_scopes(connection, request))
249 }
250
251 fn code_file_fingerprints(
252 &self,
253 repository_id: String,
254 ) -> StorageFuture<'_, Vec<CodeFileFingerprint>> {
255 self.run(move |connection| code_snapshot::file_fingerprints(connection, &repository_id))
256 }
257
258 fn code_file_fingerprints_for_scope(
259 &self,
260 source_scope: String,
261 ) -> StorageFuture<'_, Vec<CodeFileFingerprint>> {
262 self.run(move |connection| {
263 code_snapshot::file_fingerprints_for_scope(connection, &source_scope)
264 })
265 }
266
267 fn code_file_candidate_paths_for_scope(
268 &self,
269 source_scope: String,
270 path_filters: Vec<String>,
271 language_filters: Vec<String>,
272 limit: usize,
273 ) -> StorageFuture<'_, Vec<String>> {
274 self.run(move |connection| {
275 code_snapshot::file_candidate_paths_for_scope(
276 connection,
277 &source_scope,
278 &path_filters,
279 &language_filters,
280 limit,
281 )
282 })
283 }
284
285 fn code_file_candidate_paths_for_query_scope(
286 &self,
287 source_scope: String,
288 query: String,
289 path_filters: Vec<String>,
290 language_filters: Vec<String>,
291 limit: usize,
292 ) -> StorageFuture<'_, Vec<String>> {
293 self.run(move |connection| {
294 code_snapshot::file_candidate_paths_for_query_scope(
295 connection,
296 &source_scope,
297 &query,
298 &path_filters,
299 &language_filters,
300 limit,
301 )
302 })
303 }
304
305 fn apply_code_index_snapshot(
306 &self,
307 snapshot: CodeIndexSnapshot,
308 ) -> StorageFuture<'_, CodeIndexSummary> {
309 self.run(move |connection| code_snapshot::apply_snapshot(connection, snapshot))
310 }
311
312 fn begin_code_index_session(
313 &self,
314 session: CodeIndexSession,
315 ) -> StorageFuture<'_, CodeIndexCheckpoint> {
316 self.run(move |connection| code_batch::begin_session(connection, session))
317 }
318
319 fn apply_code_index_batch(
320 &self,
321 batch: CodeIndexBatch,
322 ) -> StorageFuture<'_, CodeIndexCheckpoint> {
323 self.run(move |connection| code_batch::apply_batch(connection, batch))
324 }
325
326 fn finalize_code_index_session(
327 &self,
328 session: CodeIndexSession,
329 ) -> StorageFuture<'_, CodeIndexSummary> {
330 self.run(move |connection| code_batch::finalize_session(connection, session))
331 }
332
333 fn search_code(
334 &self,
335 request: CodeRetrievalRequest,
336 ) -> StorageFuture<'_, Vec<CodeRetrievalHit>> {
337 self.run(move |connection| code_query::search_code(connection, request))
338 }
339
340 fn search_code_feature_flags(
341 &self,
342 request: CodeFeatureFlagRequest,
343 ) -> StorageFuture<'_, Vec<CodeFeatureFlagGraph>> {
344 self.run(move |connection| code_feature_flags::search(connection, request))
345 }
346
347 fn search_code_scope(
348 &self,
349 source_scope: String,
350 request: CodeRetrievalRequest,
351 ) -> StorageFuture<'_, Vec<CodeRetrievalHit>> {
352 self.run(move |connection| {
353 code_query::search_code_scope(connection, &source_scope, request)
354 })
355 }
356
357 fn analyze_code_impact(
358 &self,
359 request: CodeImpactRequest,
360 changes: CodeImpactChanges,
361 ) -> StorageFuture<'_, Vec<CodeRetrievalHit>> {
362 self.run(move |connection| code_impact::analyze_impact(connection, request, changes))
363 }
364
365 fn code_repository_totals(&self) -> StorageFuture<'_, CodeRepositoryTotals> {
366 self.run(code_report::repository_totals)
367 }
368
369 fn code_repository_report(
370 &self,
371 repository: String,
372 ) -> StorageFuture<'_, CodeRepositoryReport> {
373 self.run(move |connection| code_report::repository_report(connection, &repository))
374 }
375
376 fn create_code_repository_set(
377 &self,
378 seed: crate::storage::CodeRepositorySetSeed,
379 ) -> StorageFuture<'_, crate::domain::CodeRepositorySet> {
380 self.run(move |connection| code_set::create_set(connection, seed))
381 }
382
383 fn add_code_repository_set_member(
384 &self,
385 seed: crate::storage::CodeRepositorySetMemberSeed,
386 ) -> StorageFuture<'_, crate::domain::CodeRepositorySetMember> {
387 self.run(move |connection| code_set::add_member(connection, seed))
388 }
389
390 fn remove_code_repository_set_member(
391 &self,
392 set_alias: String,
393 repository_alias: String,
394 ) -> StorageFuture<'_, crate::domain::CodeRepositorySetMember> {
395 self.run(move |connection| {
396 code_set::remove_member(connection, &set_alias, &repository_alias)
397 })
398 }
399
400 fn code_repository_set(
401 &self,
402 set_alias: String,
403 ) -> StorageFuture<'_, Option<crate::domain::CodeRepositorySet>> {
404 self.run(move |connection| code_set::set_by_alias(connection, &set_alias))
405 }
406
407 fn code_repository_set_status(
408 &self,
409 set_alias: String,
410 ) -> StorageFuture<'_, Option<crate::domain::CodeRepositorySetStatus>> {
411 self.run(move |connection| code_set::set_status(connection, &set_alias))
412 }
413
414 fn refresh_code_repository_set_overlay(
415 &self,
416 set_alias: String,
417 now_ms: u64,
418 ) -> StorageFuture<'_, crate::domain::CodeRepositorySetRefreshSummary> {
419 self.run(move |connection| code_set::refresh_overlay(connection, &set_alias, now_ms))
420 }
421
422 fn code_repository_set_cross_edges(
423 &self,
424 set_id: String,
425 ) -> StorageFuture<'_, Vec<crate::domain::CodeRepositoryCrossEdge>> {
426 self.run(move |connection| code_set::cross_edges_for_set(connection, &set_id))
427 }
428
429 fn queue_code_repository_set_refresh_task(
430 &self,
431 task: crate::storage::CodeRepositorySetRefreshTaskSeed,
432 ) -> StorageFuture<'_, crate::domain::CodeRepositorySetRefreshTaskRecord> {
433 self.run(move |connection| code_set_tasks::queue_refresh_task(connection, task))
434 }
435
436 fn claim_code_repository_set_refresh_task(
437 &self,
438 request: crate::storage::CodeRepositorySetRefreshTaskClaimRequest,
439 ) -> StorageFuture<'_, Option<crate::domain::CodeRepositorySetRefreshTaskRecord>> {
440 self.run(move |connection| code_set_tasks::claim_refresh_task(connection, request))
441 }
442
443 fn complete_code_repository_set_refresh_task(
444 &self,
445 request: crate::storage::CodeRepositorySetRefreshTaskCompletion,
446 ) -> StorageFuture<'_, crate::domain::CodeRepositorySetRefreshTaskRecord> {
447 self.run(move |connection| code_set_tasks::complete_refresh_task(connection, request))
448 }
449
450 fn fail_code_repository_set_refresh_task(
451 &self,
452 request: crate::storage::CodeRepositorySetRefreshTaskFailure,
453 ) -> StorageFuture<'_, crate::domain::CodeRepositorySetRefreshTaskRecord> {
454 self.run(move |connection| code_set_tasks::fail_refresh_task(connection, request))
455 }
456}