Skip to main content

akar_storage/
stats.rs

1//! Column statistics for cardinality estimation in the optimizer.
2
3use std::collections::HashMap;
4
5/// Statistics for a single column.
6#[derive(Debug, Clone)]
7pub struct ColumnStats {
8    pub table_id: u64,
9    pub column_id: u32,
10    pub num_distinct_values: u64,
11    pub num_null_values: u64,
12    pub min_value: Option<Vec<u8>>,
13    pub max_value: Option<Vec<u8>>,
14}
15
16/// Per-table statistics.
17#[derive(Debug, Default)]
18pub struct TableStats {
19    pub num_rows: u64,
20    pub columns: HashMap<u32, ColumnStats>,
21}
22
23/// Global statistics manager.
24#[derive(Debug, Default)]
25pub struct StatsStore {
26    tables: HashMap<u64, TableStats>,
27}
28
29impl StatsStore {
30    pub fn new() -> Self {
31        Self::default()
32    }
33
34    pub fn get_table_stats(&self, table_id: u64) -> Option<&TableStats> {
35        self.tables.get(&table_id)
36    }
37
38    pub fn get_column_stats(&self, table_id: u64, column_id: u32) -> Option<&ColumnStats> {
39        self.tables.get(&table_id).and_then(|t| t.columns.get(&column_id))
40    }
41
42    pub fn update_table_stats(&mut self, table_id: u64, stats: TableStats) {
43        self.tables.insert(table_id, stats);
44    }
45
46    /// Get row count and estimated storage size for a table by ID.
47    /// Returns (row_count: u64, storage_size_bytes: u64).
48    pub fn table_stats_by_id(&self, table_id: u64) -> (u64, u64) {
49        if let Some(stats) = self.tables.get(&table_id) {
50            // Rough estimate: num_rows * 256 bytes per row average
51            let estimated_size = stats.num_rows * 256;
52            (stats.num_rows, estimated_size)
53        } else {
54            (0, 0)
55        }
56    }
57}