use serde::Serialize;
use crate::{Database, Result};
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize)]
pub struct CleanSummary {
pub files: usize,
pub functions: usize,
}
const ORPHANS: &str = "
DROP TABLE IF EXISTS temp.orphan_file;
CREATE TEMP TABLE orphan_file AS
SELECT id FROM source_file
WHERE id NOT IN (SELECT source_file_id FROM version_file);
DROP TABLE IF EXISTS temp.orphan_function;
CREATE TEMP TABLE orphan_function AS
SELECT id FROM function WHERE source_file_id IN (SELECT id FROM orphan_file);
";
impl Database {
pub fn unreferenced(&self) -> Result<CleanSummary> {
let count = |sql: &str| -> Result<usize> {
let n: i64 = self.conn.query_row(sql, [], |r| r.get(0))?;
Ok(n as usize)
};
Ok(CleanSummary {
files: count(
"SELECT COUNT(*) FROM source_file
WHERE id NOT IN (SELECT source_file_id FROM version_file)",
)?,
functions: count(
"SELECT COUNT(*) FROM function WHERE source_file_id IN (
SELECT id FROM source_file
WHERE id NOT IN (SELECT source_file_id FROM version_file))",
)?,
})
}
pub fn clean(&mut self) -> Result<CleanSummary> {
let tx = self.conn.transaction()?;
tx.execute_batch(ORPHANS)?;
let count = |table: &str| -> Result<usize> {
let n: i64 = tx.query_row(&format!("SELECT COUNT(*) FROM temp.{table}"), [], |r| {
r.get(0)
})?;
Ok(n as usize)
};
let summary = CleanSummary {
files: count("orphan_file")?,
functions: count("orphan_function")?,
};
tx.execute_batch(
"DELETE FROM lsh_bucket WHERE function_id IN (SELECT id FROM temp.orphan_function);
DELETE FROM minhash WHERE function_id IN (SELECT id FROM temp.orphan_function);
DELETE FROM fingerprint WHERE function_id IN (SELECT id FROM temp.orphan_function);
DELETE FROM exact_hash WHERE function_id IN (SELECT id FROM temp.orphan_function);
DELETE FROM function WHERE id IN (SELECT id FROM temp.orphan_function);
DELETE FROM source_file WHERE id IN (SELECT id FROM temp.orphan_file);
DROP TABLE temp.orphan_function;
DROP TABLE temp.orphan_file;",
)?;
tx.commit()?;
Ok(summary)
}
pub fn vacuum(&self) -> Result<()> {
self.conn
.execute_batch(
"PRAGMA wal_checkpoint(TRUNCATE); VACUUM; PRAGMA wal_checkpoint(TRUNCATE);",
)?;
Ok(())
}
}