agentroot_core/db/
stats.rs

1//! Database statistics
2
3use super::Database;
4use crate::error::Result;
5
6/// Database stats
7#[derive(Debug, Clone, serde::Serialize)]
8pub struct DatabaseStats {
9    pub collection_count: usize,
10    pub document_count: usize,
11    pub embedded_count: usize,
12    pub pending_embedding: usize,
13    pub metadata_count: usize,
14    pub pending_metadata: usize,
15}
16
17impl Database {
18    /// Get database statistics
19    pub fn get_stats(&self) -> Result<DatabaseStats> {
20        let collection_count: i64 =
21            self.conn
22                .query_row("SELECT COUNT(*) FROM collections", [], |row| row.get(0))?;
23
24        let document_count: i64 = self.conn.query_row(
25            "SELECT COUNT(*) FROM documents WHERE active = 1",
26            [],
27            |row| row.get(0),
28        )?;
29
30        let embedded_count: i64 = self
31            .conn
32            .query_row(
33                "SELECT COUNT(DISTINCT hash) FROM content_vectors",
34                [],
35                |row| row.get(0),
36            )
37            .unwrap_or(0);
38
39        let pending_embedding: i64 = self
40            .conn
41            .query_row(
42                "SELECT COUNT(DISTINCT c.hash) FROM content c
43             JOIN documents d ON d.hash = c.hash AND d.active = 1
44             WHERE c.hash NOT IN (SELECT DISTINCT hash FROM content_vectors)",
45                [],
46                |row| row.get(0),
47            )
48            .unwrap_or(0);
49
50        let metadata_count: i64 = self
51            .conn
52            .query_row(
53                "SELECT COUNT(*) FROM documents WHERE active = 1 AND llm_summary IS NOT NULL",
54                [],
55                |row| row.get(0),
56            )
57            .unwrap_or(0);
58
59        let pending_metadata: i64 = self
60            .conn
61            .query_row(
62                "SELECT COUNT(*) FROM documents WHERE active = 1 AND llm_summary IS NULL",
63                [],
64                |row| row.get(0),
65            )
66            .unwrap_or(0);
67
68        Ok(DatabaseStats {
69            collection_count: collection_count as usize,
70            document_count: document_count as usize,
71            embedded_count: embedded_count as usize,
72            pending_embedding: pending_embedding as usize,
73            metadata_count: metadata_count as usize,
74            pending_metadata: pending_metadata as usize,
75        })
76    }
77
78    /// Vacuum the database
79    pub fn vacuum(&self) -> Result<()> {
80        self.conn.execute("VACUUM", [])?;
81        Ok(())
82    }
83
84    /// Cleanup orphaned vectors
85    pub fn cleanup_orphaned_vectors(&self) -> Result<usize> {
86        let rows = self.conn.execute(
87            "DELETE FROM content_vectors WHERE hash NOT IN
88             (SELECT DISTINCT hash FROM documents WHERE active = 1)",
89            [],
90        )?;
91        Ok(rows)
92    }
93}