#![cfg_attr(coverage_nightly, coverage(off))]
use super::insert::{
insert_call_graph, insert_coverage_off_files, insert_functions, insert_graph_metrics,
insert_metadata,
};
use super::schema::{create_schema, open_db};
use super::types::*;
use std::collections::{HashMap, HashSet};
use std::path::Path;
pub(crate) fn save_to_sqlite(
db_path: &Path,
functions: &[FunctionEntry],
calls: &HashMap<usize, Vec<usize>>,
graph_metrics: &[GraphMetrics],
manifest: &IndexManifest,
coverage_off_files: &HashSet<String>,
) -> Result<(), String> {
let tmp_path = db_path.with_extension("db.tmp");
let _ = std::fs::remove_file(&tmp_path);
let conn = open_db(&tmp_path)?;
create_schema(&conn)?;
insert_functions(&conn, functions)?;
insert_call_graph(&conn, calls)?;
insert_graph_metrics(&conn, graph_metrics)?;
insert_metadata(&conn, manifest)?;
insert_coverage_off_files(&conn, coverage_off_files)?;
drop(conn);
std::fs::rename(&tmp_path, db_path)
.map_err(|e| format!("Failed to rename temp DB into place: {e}"))?;
let _ = std::fs::remove_file(db_path.with_extension("db-wal"));
let _ = std::fs::remove_file(db_path.with_extension("db-shm"));
eprintln!(
" SQLite index saved: {} functions, {} call edges, {}",
functions.len(),
calls.values().map(|v| v.len()).sum::<usize>(),
humanize_bytes(db_path.metadata().map(|m| m.len()).unwrap_or(0)),
);
Ok(())
}
pub(crate) fn humanize_bytes(bytes: u64) -> String {
if bytes < 1024 {
format!("{bytes} B")
} else if bytes < 1024 * 1024 {
format!("{:.1} KB", bytes as f64 / 1024.0)
} else {
format!("{:.1} MB", bytes as f64 / (1024.0 * 1024.0))
}
}