use crate::row_header::XMAX_ALIVE;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct VacuumReport {
pub rows_reclaimed: u64,
pub rows_examined: u64,
pub per_table: alloc::vec::Vec<(alloc::string::String, u64)>,
}
impl VacuumReport {
pub fn merge(&mut self, other: VacuumReport) {
self.rows_reclaimed += other.rows_reclaimed;
self.rows_examined += other.rows_examined;
self.per_table.extend(other.per_table);
}
}
#[inline]
#[must_use]
pub fn is_reclaimable(xmax: u64, oldest_active: u64) -> bool {
xmax != XMAX_ALIVE && xmax < oldest_active
}
#[cfg(test)]
mod tests {
use super::*;
use crate::row_header::XMAX_ALIVE;
#[test]
fn alive_row_is_not_reclaimable() {
assert!(!is_reclaimable(XMAX_ALIVE, 100));
}
#[test]
fn deleted_row_is_reclaimable_when_xmax_older_than_oldest_active() {
assert!(is_reclaimable(10, 100));
}
#[test]
fn deleted_row_is_not_reclaimable_while_snapshot_could_still_see_it() {
assert!(!is_reclaimable(100, 5));
}
#[test]
fn report_merge_aggregates_counters() {
let mut a = VacuumReport {
rows_reclaimed: 5,
rows_examined: 100,
per_table: alloc::vec![("t".into(), 5)],
};
let b = VacuumReport {
rows_reclaimed: 3,
rows_examined: 40,
per_table: alloc::vec![("u".into(), 3)],
};
a.merge(b);
assert_eq!(a.rows_reclaimed, 8);
assert_eq!(a.rows_examined, 140);
assert_eq!(a.per_table.len(), 2);
}
}