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