1use std::path::Path;
2
3use rusqlite::Connection;
4
5#[path = "code_query.rs"]
6mod code_query;
7
8#[path = "code_query_prepare.rs"]
9mod code_query_prepare;
10
11#[path = "code_query_hits.rs"]
12mod code_query_hits;
13
14#[path = "code_feature_flags.rs"]
15mod code_feature_flags;
16
17#[path = "code_query_scope.rs"]
18mod code_query_scope;
19
20#[path = "code_impact.rs"]
21mod code_impact;
22
23#[path = "code_report.rs"]
24pub(super) mod code_report;
25
26#[path = "code_schema.rs"]
27mod code_schema;
28
29#[path = "code_status.rs"]
30mod code_status;
31
32#[path = "code_remove.rs"]
33mod code_remove;
34
35#[path = "code_batch.rs"]
36mod code_batch;
37
38#[path = "code_cleanup.rs"]
39mod code_cleanup;
40
41#[path = "code_tasks.rs"]
42mod code_tasks;
43
44#[path = "code_search.rs"]
45mod code_search;
46
47#[path = "code_snapshot.rs"]
48mod code_snapshot;
49
50#[path = "code_set.rs"]
51mod code_set;
52
53#[path = "code_set_tasks.rs"]
54mod code_set_tasks;
55
56#[path = "software.rs"]
57mod software;
58
59#[cfg(test)]
60#[path = "code_tests.rs"]
61mod code_tests;
62
63#[cfg(test)]
64#[path = "code_scope_status_tests.rs"]
65mod code_scope_status_tests;
66
67#[cfg(test)]
68#[path = "code_snapshot_candidate_paths_tests.rs"]
69mod code_snapshot_candidate_paths_tests;
70
71#[cfg(test)]
72#[path = "code_incremental_search_tests.rs"]
73mod code_incremental_search_tests;
74
75#[cfg(test)]
76#[path = "code_batch_finalize_tests.rs"]
77mod code_batch_finalize_tests;
78
79#[cfg(test)]
80#[path = "code_batch_finalize_typescript_tests.rs"]
81mod code_batch_finalize_typescript_tests;
82
83#[cfg(test)]
84#[path = "code_cross_language_call_tests.rs"]
85mod code_cross_language_call_tests;
86
87#[cfg(test)]
88#[path = "code_batch_search_tests.rs"]
89mod code_batch_search_tests;
90
91#[cfg(test)]
92#[path = "code_snapshot_progress_tests.rs"]
93mod code_snapshot_progress_tests;
94
95#[cfg(test)]
96#[path = "code_query_accuracy_tests.rs"]
97mod code_query_accuracy_tests;
98
99#[cfg(test)]
100#[path = "code_query_import_target_tests.rs"]
101mod code_query_import_target_tests;
102
103#[cfg(test)]
104#[path = "code_query_import_ranking_tests.rs"]
105mod code_query_import_ranking_tests;
106
107#[cfg(test)]
108#[path = "code_query_import_foundational_ranking_tests.rs"]
109mod code_query_import_foundational_ranking_tests;
110
111#[cfg(test)]
112#[path = "code_query_sbom_tests.rs"]
113mod code_query_sbom_tests;
114
115#[cfg(test)]
116#[path = "code_query_line_context_tests.rs"]
117mod code_query_line_context_tests;
118
119#[cfg(test)]
120#[path = "code_metadata_tests.rs"]
121mod code_metadata_tests;
122
123#[cfg(test)]
124#[path = "code_tasks_tests.rs"]
125mod code_tasks_tests;
126
127#[cfg(test)]
128#[path = "code_tasks_status_tests.rs"]
129mod code_tasks_status_tests;
130
131#[cfg(test)]
132#[path = "code_tasks_lease_tests.rs"]
133mod code_tasks_lease_tests;
134
135#[cfg(test)]
136#[path = "code_tasks_reset_tests.rs"]
137mod code_tasks_reset_tests;
138
139#[cfg(test)]
140#[path = "code_set_tasks_tests.rs"]
141mod code_set_tasks_tests;
142
143#[cfg(test)]
144#[path = "code_set_tests.rs"]
145mod code_set_tests;
146
147use crate::{
148 domain::{
149 CodeFeatureFlagGraph, CodeFeatureFlagRequest, CodeFileFingerprint, CodeImpactRequest,
150 CodeIndexBatch, CodeIndexCheckpoint, CodeIndexSession, CodeIndexSnapshot, CodeIndexSummary,
151 CodeRepositoryRegistration, CodeRepositoryReport, CodeRepositoryStatus,
152 CodeRepositoryTotals, CodeRetrievalHit, CodeRetrievalRequest, SoftwareGlobalProjection,
153 SoftwareGlobalRequest,
154 },
155 storage::{CodeImpactChanges, CodeRepositoryStore, StorageError, StorageFuture},
156};
157
158use super::SqliteGraphStore;
159pub(super) use code_search::SearchDocumentInserter;
160
161const MAX_SYMBOL_SIGNATURE_LOOKUP_IDS_PER_STATEMENT: usize = 500;
162
163pub(super) fn initialize_code_schema(connection: &Connection) -> Result<(), StorageError> {
164 code_schema::initialize_code_schema(connection)?;
165 software::initialize_schema(connection)
166}
167
168pub(super) fn import_repository_from_database(
169 connection: &mut Connection,
170 source_path: &Path,
171 repository_id: &str,
172 source_scope: Option<&str>,
173) -> Result<(), StorageError> {
174 code_snapshot::import_repository_from_database(
175 connection,
176 source_path,
177 repository_id,
178 source_scope,
179 )
180}
181
182pub(super) fn repository_totals_excluding(
183 connection: &mut Connection,
184 excluded_repository_ids: &[String],
185) -> Result<CodeRepositoryTotals, StorageError> {
186 code_report::repository_totals_excluding(connection, excluded_repository_ids)
187}
188
189pub(super) fn prune_scopes_with_retained(
190 connection: &mut Connection,
191 request: crate::storage::CodeScopeRetentionRequest,
192 extra_retained_scopes: Vec<String>,
193) -> Result<crate::domain::CodeScopeRetentionSummary, StorageError> {
194 code_tasks::prune_scopes_with_retained(connection, request, extra_retained_scopes)
195}
196
197impl CodeRepositoryStore for SqliteGraphStore {
198 fn upsert_code_repository(
199 &self,
200 registration: CodeRepositoryRegistration,
201 ) -> StorageFuture<'_, CodeRepositoryStatus> {
202 self.run(move |connection| code_status::upsert_repository(connection, registration))
203 }
204
205 fn code_repository_status(
206 &self,
207 repository: String,
208 ) -> StorageFuture<'_, Option<CodeRepositoryStatus>> {
209 self.run_read(move |connection| code_status::repository_status(connection, &repository))
210 }
211
212 fn remove_code_repository(
213 &self,
214 repository: String,
215 now_ms: u64,
216 ) -> StorageFuture<'_, Option<crate::domain::CodeRepositoryRemovalSummary>> {
217 self.run(move |connection| code_remove::remove_repository(connection, &repository, now_ms))
218 }
219
220 fn code_repository_scope_status(
221 &self,
222 repository: String,
223 resolved_commit_sha: String,
224 path_filters: Vec<String>,
225 language_filters: Vec<String>,
226 ) -> StorageFuture<'_, Option<CodeRepositoryStatus>> {
227 self.run_read(move |connection| {
228 code_status::repository_scope_status(
229 connection,
230 &repository,
231 &resolved_commit_sha,
232 &path_filters,
233 &language_filters,
234 )
235 })
236 }
237
238 fn latest_code_repository_scope_status(
239 &self,
240 repository: String,
241 path_filters: Vec<String>,
242 language_filters: Vec<String>,
243 ) -> StorageFuture<'_, Option<CodeRepositoryStatus>> {
244 self.run_read(move |connection| {
245 code_status::latest_repository_scope_status(
246 connection,
247 &repository,
248 &path_filters,
249 &language_filters,
250 )
251 })
252 }
253
254 fn queue_code_index_task(
255 &self,
256 task: crate::storage::CodeIndexTaskSeed,
257 ) -> StorageFuture<'_, crate::domain::CodeIndexTaskRecord> {
258 self.run(move |connection| code_tasks::queue_task(connection, task))
259 }
260
261 fn claim_code_index_task(
262 &self,
263 request: crate::storage::CodeIndexTaskClaimRequest,
264 ) -> StorageFuture<'_, Option<crate::domain::CodeIndexTaskRecord>> {
265 self.run(move |connection| code_tasks::claim_task(connection, request))
266 }
267
268 fn recover_code_index_task_leases(
269 &self,
270 now_ms: u64,
271 max_attempts: u32,
272 ) -> StorageFuture<'_, ()> {
273 self.run(move |connection| {
274 code_tasks::recover_expired_task_leases(connection, now_ms, max_attempts)
275 })
276 }
277
278 fn running_code_index_task_leases(
279 &self,
280 ) -> StorageFuture<'_, Vec<crate::storage::CodeIndexTaskLeaseRecord>> {
281 self.run_read(code_tasks::running_task_leases)
282 }
283
284 fn recover_code_index_task_leases_by_task(
285 &self,
286 request: crate::storage::CodeIndexTaskLeaseRecovery,
287 ) -> StorageFuture<'_, usize> {
288 self.run(move |connection| code_tasks::recover_task_leases_by_task(connection, request))
289 }
290
291 fn reset_code_index_tasks(
292 &self,
293 repository_id: String,
294 now_ms: u64,
295 ) -> StorageFuture<'_, Vec<crate::domain::CodeIndexTaskRecord>> {
296 self.run(move |connection| code_tasks::reset_tasks(connection, &repository_id, now_ms))
297 }
298
299 fn renew_code_index_task_lease(
300 &self,
301 request: crate::storage::CodeIndexTaskLeaseRenewal,
302 ) -> StorageFuture<'_, crate::domain::CodeIndexTaskRecord> {
303 self.run(move |connection| code_tasks::renew_task_lease(connection, request))
304 }
305
306 fn complete_code_index_task(
307 &self,
308 request: crate::storage::CodeIndexTaskCompletion,
309 ) -> StorageFuture<'_, crate::domain::CodeIndexTaskRecord> {
310 self.run(move |connection| code_tasks::complete_task(connection, request))
311 }
312
313 fn fail_code_index_task(
314 &self,
315 request: crate::storage::CodeIndexTaskFailure,
316 ) -> StorageFuture<'_, crate::domain::CodeIndexTaskRecord> {
317 self.run(move |connection| code_tasks::fail_task(connection, request))
318 }
319
320 fn code_index_task(
321 &self,
322 task_id: String,
323 ) -> StorageFuture<'_, Option<crate::domain::CodeIndexTaskRecord>> {
324 self.run_read(move |connection| code_tasks::task_by_id(connection, &task_id))
325 }
326
327 fn active_code_index_task(
328 &self,
329 repository_id: String,
330 ) -> StorageFuture<'_, Option<crate::domain::CodeIndexTaskRecord>> {
331 self.run_read(move |connection| code_tasks::active_task(connection, &repository_id))
332 }
333
334 fn code_index_task_queue_status(
335 &self,
336 ) -> StorageFuture<'_, crate::domain::CodeIndexTaskQueueStatus> {
337 self.run_read(code_tasks::queue_status)
338 }
339
340 fn code_index_checkpoint(
341 &self,
342 source_scope: String,
343 ) -> StorageFuture<'_, Option<crate::domain::CodeIndexCheckpoint>> {
344 self.run_read(move |connection| code_tasks::checkpoint(connection, &source_scope))
345 }
346
347 fn latest_code_index_checkpoint(
348 &self,
349 repository_id: String,
350 ) -> StorageFuture<'_, Option<crate::domain::CodeIndexCheckpoint>> {
351 self.run_read(move |connection| {
352 code_tasks::latest_checkpoint_for_repository(connection, &repository_id)
353 })
354 }
355
356 fn code_scope_retention(
357 &self,
358 repository_id: String,
359 ) -> StorageFuture<'_, crate::domain::CodeScopeRetentionSummary> {
360 self.run_read(move |connection| code_tasks::retention_status(connection, &repository_id))
361 }
362
363 fn prune_code_repository_scopes(
364 &self,
365 request: crate::storage::CodeScopeRetentionRequest,
366 ) -> StorageFuture<'_, crate::domain::CodeScopeRetentionSummary> {
367 self.run(move |connection| code_tasks::prune_scopes(connection, request))
368 }
369
370 fn code_file_fingerprints(
371 &self,
372 repository_id: String,
373 ) -> StorageFuture<'_, Vec<CodeFileFingerprint>> {
374 self.run_read(move |connection| {
375 code_snapshot::file_fingerprints(connection, &repository_id)
376 })
377 }
378
379 fn code_file_fingerprints_for_scope(
380 &self,
381 source_scope: String,
382 ) -> StorageFuture<'_, Vec<CodeFileFingerprint>> {
383 self.run_read(move |connection| {
384 code_snapshot::file_fingerprints_for_scope(connection, &source_scope)
385 })
386 }
387
388 fn code_file_candidate_paths_for_scope(
389 &self,
390 source_scope: String,
391 path_filters: Vec<String>,
392 language_filters: Vec<String>,
393 limit: usize,
394 ) -> StorageFuture<'_, Vec<String>> {
395 self.run_read(move |connection| {
396 code_snapshot::file_candidate_paths_for_scope(
397 connection,
398 &source_scope,
399 &path_filters,
400 &language_filters,
401 limit,
402 )
403 })
404 }
405
406 fn code_file_candidate_paths_for_query_scope(
407 &self,
408 source_scope: String,
409 query: String,
410 path_filters: Vec<String>,
411 language_filters: Vec<String>,
412 limit: usize,
413 ) -> StorageFuture<'_, Vec<String>> {
414 self.run_read(move |connection| {
415 code_snapshot::file_candidate_paths_for_query_scope(
416 connection,
417 &source_scope,
418 &query,
419 &path_filters,
420 &language_filters,
421 limit,
422 )
423 })
424 }
425
426 fn apply_code_index_snapshot(
427 &self,
428 snapshot: CodeIndexSnapshot,
429 ) -> StorageFuture<'_, CodeIndexSummary> {
430 self.run(move |connection| code_snapshot::apply_snapshot(connection, snapshot))
431 }
432
433 fn begin_code_index_session(
434 &self,
435 session: CodeIndexSession,
436 ) -> StorageFuture<'_, CodeIndexCheckpoint> {
437 self.run(move |connection| code_batch::begin_session(connection, session))
438 }
439
440 fn apply_code_index_batch(
441 &self,
442 batch: CodeIndexBatch,
443 ) -> StorageFuture<'_, CodeIndexCheckpoint> {
444 self.run(move |connection| code_batch::apply_batch(connection, batch))
445 }
446
447 fn finalize_code_index_session(
448 &self,
449 session: CodeIndexSession,
450 ) -> StorageFuture<'_, CodeIndexSummary> {
451 self.run(move |connection| code_batch::finalize_session(connection, session))
452 }
453
454 fn search_code(
455 &self,
456 request: CodeRetrievalRequest,
457 ) -> StorageFuture<'_, Vec<CodeRetrievalHit>> {
458 self.run_read(move |connection| code_query::search_code(connection, request))
459 }
460
461 fn search_code_feature_flags(
462 &self,
463 request: CodeFeatureFlagRequest,
464 ) -> StorageFuture<'_, Vec<CodeFeatureFlagGraph>> {
465 self.run_read(move |connection| code_feature_flags::search(connection, request))
466 }
467
468 fn search_code_feature_flags_scope(
469 &self,
470 source_scope: String,
471 request: CodeFeatureFlagRequest,
472 ) -> StorageFuture<'_, Vec<CodeFeatureFlagGraph>> {
473 self.run_read(move |connection| {
474 code_feature_flags::search_scope(connection, &source_scope, request)
475 })
476 }
477
478 fn search_code_scope(
479 &self,
480 source_scope: String,
481 request: CodeRetrievalRequest,
482 ) -> StorageFuture<'_, Vec<CodeRetrievalHit>> {
483 self.run_read(move |connection| {
484 code_query::search_code_scope(connection, &source_scope, request)
485 })
486 }
487
488 fn analyze_code_impact(
489 &self,
490 request: CodeImpactRequest,
491 changes: CodeImpactChanges,
492 ) -> StorageFuture<'_, Vec<CodeRetrievalHit>> {
493 self.run_read(move |connection| code_impact::analyze_impact(connection, request, changes))
494 }
495
496 fn analyze_code_impact_scope(
497 &self,
498 source_scope: String,
499 request: CodeImpactRequest,
500 changes: CodeImpactChanges,
501 ) -> StorageFuture<'_, Vec<CodeRetrievalHit>> {
502 self.run_read(move |connection| {
503 code_impact::analyze_impact_scope(connection, &source_scope, request, changes)
504 })
505 }
506
507 fn code_repository_totals(&self) -> StorageFuture<'_, CodeRepositoryTotals> {
508 self.run_read(code_report::repository_totals)
509 }
510
511 fn code_repository_report(
512 &self,
513 repository: String,
514 ) -> StorageFuture<'_, CodeRepositoryReport> {
515 self.run_read(move |connection| code_report::repository_report(connection, &repository))
516 }
517
518 fn refresh_software_global_projection(
519 &self,
520 source_scope: String,
521 ) -> StorageFuture<'_, SoftwareGlobalProjection> {
522 self.run(move |connection| software::refresh_projection(connection, &source_scope))
523 }
524
525 fn software_global_projection(
526 &self,
527 request: SoftwareGlobalRequest,
528 ) -> StorageFuture<'_, SoftwareGlobalProjection> {
529 self.run_read(move |connection| software::projection(connection, request))
530 }
531
532 fn software_global_projection_for_scope(
533 &self,
534 source_scope: String,
535 request: SoftwareGlobalRequest,
536 ) -> StorageFuture<'_, SoftwareGlobalProjection> {
537 self.run_read(move |connection| {
538 software::projection_for_scope(connection, &source_scope, request)
539 })
540 }
541
542 fn create_code_repository_set(
543 &self,
544 seed: crate::storage::CodeRepositorySetSeed,
545 ) -> StorageFuture<'_, crate::domain::CodeRepositorySet> {
546 self.run(move |connection| code_set::create_set(connection, seed))
547 }
548
549 fn add_code_repository_set_member(
550 &self,
551 seed: crate::storage::CodeRepositorySetMemberSeed,
552 ) -> StorageFuture<'_, crate::domain::CodeRepositorySetMember> {
553 self.run(move |connection| code_set::add_member(connection, seed))
554 }
555
556 fn remove_code_repository_set_member(
557 &self,
558 set_alias: String,
559 repository_alias: String,
560 ) -> StorageFuture<'_, crate::domain::CodeRepositorySetMember> {
561 self.run(move |connection| {
562 code_set::remove_member(connection, &set_alias, &repository_alias)
563 })
564 }
565
566 fn code_repository_set(
567 &self,
568 set_alias: String,
569 ) -> StorageFuture<'_, Option<crate::domain::CodeRepositorySet>> {
570 self.run_read(move |connection| code_set::set_by_alias(connection, &set_alias))
571 }
572
573 fn code_repository_set_status(
574 &self,
575 set_alias: String,
576 ) -> StorageFuture<'_, Option<crate::domain::CodeRepositorySetStatus>> {
577 self.run_read(move |connection| code_set::set_status(connection, &set_alias))
578 }
579
580 fn refresh_code_repository_set_overlay(
581 &self,
582 set_alias: String,
583 now_ms: u64,
584 ) -> StorageFuture<'_, crate::domain::CodeRepositorySetRefreshSummary> {
585 self.run(move |connection| code_set::refresh_overlay(connection, &set_alias, now_ms))
586 }
587
588 fn code_repository_set_cross_edges(
589 &self,
590 set_id: String,
591 ) -> StorageFuture<'_, Vec<crate::domain::CodeRepositoryCrossEdge>> {
592 self.run_read(move |connection| code_set::cross_edges_for_set(connection, &set_id))
593 }
594
595 fn queue_code_repository_set_refresh_task(
596 &self,
597 task: crate::storage::CodeRepositorySetRefreshTaskSeed,
598 ) -> StorageFuture<'_, crate::domain::CodeRepositorySetRefreshTaskRecord> {
599 self.run(move |connection| code_set_tasks::queue_refresh_task(connection, task))
600 }
601
602 fn claim_code_repository_set_refresh_task(
603 &self,
604 request: crate::storage::CodeRepositorySetRefreshTaskClaimRequest,
605 ) -> StorageFuture<'_, Option<crate::domain::CodeRepositorySetRefreshTaskRecord>> {
606 self.run(move |connection| code_set_tasks::claim_refresh_task(connection, request))
607 }
608
609 fn complete_code_repository_set_refresh_task(
610 &self,
611 request: crate::storage::CodeRepositorySetRefreshTaskCompletion,
612 ) -> StorageFuture<'_, crate::domain::CodeRepositorySetRefreshTaskRecord> {
613 self.run(move |connection| code_set_tasks::complete_refresh_task(connection, request))
614 }
615
616 fn fail_code_repository_set_refresh_task(
617 &self,
618 request: crate::storage::CodeRepositorySetRefreshTaskFailure,
619 ) -> StorageFuture<'_, crate::domain::CodeRepositorySetRefreshTaskRecord> {
620 self.run(move |connection| code_set_tasks::fail_refresh_task(connection, request))
621 }
622}