Coverage Report

Created: 2026-07-31 00:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/home/runner/work/feoxdb/feoxdb/src/core/store/range.rs
Line
Count
Source
1
use crossbeam_epoch as epoch;
2
use std::ops::Bound;
3
4
use crate::constants::MAX_KEY_SIZE;
5
use crate::error::{FeoxError, Result};
6
7
use super::FeoxStore;
8
9
const RANGE_PREALLOC_LIMIT: usize = 1024;
10
const RANGE_REPIN_INTERVAL: usize = 256;
11
12
impl FeoxStore {
13
    /// Perform a range query on the store.
14
    ///
15
    /// Returns all key-value pairs where the key is >= `start_key` and <= `end_key`.
16
    /// Both bounds are inclusive.
17
    ///
18
    /// # Arguments
19
    ///
20
    /// * `start_key` - Inclusive lower bound
21
    /// * `end_key` - Inclusive upper bound
22
    /// * `limit` - Maximum number of results to return
23
    ///
24
    /// # Returns
25
    ///
26
    /// Returns a vector of (key, value) pairs in sorted order.
27
    ///
28
    /// # Example
29
    ///
30
    /// ```rust
31
    /// # use feoxdb::FeoxStore;
32
    /// # fn main() -> feoxdb::Result<()> {
33
    /// # let store = FeoxStore::new(None)?;
34
    /// store.insert(b"user:001", b"Alice")?;
35
    /// store.insert(b"user:002", b"Bob")?;
36
    /// store.insert(b"user:003", b"Charlie")?;
37
    /// store.insert(b"user:004", b"David")?;
38
    ///
39
    /// // Get users 001 through 003 (inclusive)
40
    /// let results = store.range_query(b"user:001", b"user:003", 10)?;
41
    /// assert_eq!(results.len(), 3);
42
    /// # Ok(())
43
    /// # }
44
    /// ```
45
105
    pub fn range_query(
46
105
        &self,
47
105
        start_key: &[u8],
48
105
        end_key: &[u8],
49
105
        limit: usize,
50
105
    ) -> Result<Vec<(Vec<u8>, Vec<u8>)>> {
51
105
        if start_key.len() > MAX_KEY_SIZE || end_key.len() > MAX_KEY_SIZE {
52
0
            return Err(FeoxError::InvalidKeySize);
53
105
        }
54
55
105
        if limit == 0 {
56
0
            return Ok(Vec::new());
57
105
        }
58
105
        let mut results = Vec::with_capacity(limit.min(self.tree.len()).min(RANGE_PREALLOC_LIMIT));
59
60
105
        let mut guard = epoch::pin();
61
105
        let mut entries_since_repin = 0;
62
105
        let mut cursor = self.tree.lower_bound(Bound::Included(start_key));
63
64
6.82k
        while let Some(
entry6.72k
) = cursor {
65
6.72k
            if results.len() >= limit || 
entry.key().as_slice() > end_key6.72k
{
66
4
                break;
67
6.71k
            }
68
69
6.71k
            let value = {
70
6.71k
                let record = entry.value().load(&guard);
71
6.71k
                self.resolve_value_ref(entry.key(), record)
72
            };
73
6.71k
            entries_since_repin += 1;
74
6.71k
            if entries_since_repin == RANGE_REPIN_INTERVAL {
75
1
                guard.repin();
76
1
                entries_since_repin = 0;
77
6.71k
            }
78
6.71k
            let value = match 
value0
{
79
6.71k
                Ok(value) => value.to_vec(),
80
                Err(FeoxError::StaleExtent) | Err(FeoxError::KeyNotFound) => {
81
0
                    cursor = entry.next();
82
0
                    continue;
83
                }
84
0
                Err(error) => return Err(error),
85
            };
86
87
6.71k
            results.push((entry.key().clone(), value));
88
6.71k
            cursor = entry.next();
89
        }
90
91
105
        Ok(results)
92
105
    }
93
}