Skip to main content

linkrs_storage/edge/
property_schema.rs

1//! Property Schema and Statistics
2//!
3//! Contains schema definitions and compaction statistics for property storage.
4//! These types are separated from the table implementation for better modularity.
5
6use crate::encoding::EncodingType;
7use linkrs_core::{DataType, Value};
8use std::sync::Arc;
9
10/// Default version chain capacity for property storage
11pub const DEFAULT_VERSION_CHAIN_CAP: usize = 64;
12
13/// Property schema definition
14#[derive(Debug, Clone)]
15pub struct PropertySchema {
16    pub name: Arc<str>,
17    pub prop_id: i32,
18    pub data_type: DataType,
19    pub nullable: bool,
20    pub encoding_type: EncodingType,
21    pub default_value: Option<Value>,
22}
23
24impl PropertySchema {
25    pub fn new(name: impl Into<Arc<str>>, prop_id: i32, data_type: DataType) -> Self {
26        Self {
27            name: name.into(),
28            prop_id,
29            data_type,
30            nullable: false,
31            encoding_type: EncodingType::None,
32            default_value: None,
33        }
34    }
35
36    pub fn nullable(mut self, nullable: bool) -> Self {
37        self.nullable = nullable;
38        self
39    }
40
41    pub fn with_encoding(mut self, encoding_type: EncodingType) -> Self {
42        self.encoding_type = encoding_type;
43        self
44    }
45
46    pub fn with_default_value(mut self, default_value: Option<Value>) -> Self {
47        self.default_value = default_value;
48        self
49    }
50}
51
52/// Statistics about property table fragmentation and compaction.
53///
54/// Tracks fragmentation metrics to help decide when to perform compaction
55/// and measure the effectiveness of compaction operations.
56///
57/// Fragmentation is measured in two ways:
58/// 1. **Record-level**: tombstone_count / total_records
59///    - Quick check for excessive deleted records
60///    - Not size-aware (100 large records vs 100 tiny records look the same)
61///
62/// 2. **Byte-level**: reclaimable_bytes
63///    - Actual storage waste from deleted records
64///    - More accurate indicator of compaction benefit
65///
66/// Compaction decisions should primarily consider reclaimable_bytes
67/// rather than just fragmentation ratio.
68#[derive(Debug, Clone, Default)]
69pub struct PropertyCompactionStats {
70    /// Number of deleted/tombstoned records
71    pub tombstone_count: usize,
72    /// Total number of records including tombstones
73    pub total_records: usize,
74    /// Number of live (non-deleted) records
75    /// Equal to total_records - tombstone_count
76    pub live_records: usize,
77    /// Estimated bytes that could be recovered through compaction
78    pub reclaimable_bytes: usize,
79}
80
81impl PropertyCompactionStats {
82    /// Get fragmentation ratio as a decimal (0.0 to 1.0)
83    pub fn fragmentation_ratio(&self) -> f64 {
84        if self.total_records == 0 {
85            0.0
86        } else {
87            self.tombstone_count as f64 / self.total_records as f64
88        }
89    }
90}