• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

getdozer / dozer / 4371276901

pending completion
4371276901

push

github

GitHub
fix: Add sources names used in the query (#1190)

28 of 28 new or added lines in 3 files covered. (100.0%)

27837 of 39159 relevant lines covered (71.09%)

73963.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.05
/dozer-cache/src/cache/index/mod.rs
1
use std::cmp::Ordering;
2

3
use dozer_types::types::{FieldBorrow, IndexDefinition, Record};
4

5
pub trait CacheIndex {
6
    // Builds one index based on index definition and record
7
    fn build(index: &IndexDefinition, rec: &Record) -> Vec<Vec<u8>>;
8

9
    fn get_key(schema_id: u32, field_idx: &usize, field_val: &[u8]) -> Vec<u8>;
10
}
11

12
use dozer_types::types::Field;
13

14
use crate::errors::CompareError;
15

16
pub fn get_primary_key(primary_index: &[usize], values: &[Field]) -> Vec<u8> {
21,626✔
17
    debug_assert!(
18
        !primary_index.is_empty(),
21,659✔
19
        "Primary key indexes cannot be empty"
×
20
    );
21

22
    let key: Vec<Vec<u8>> = primary_index
21,626✔
23
        .iter()
21,626✔
24
        .map(|idx| values[*idx].encode())
21,780✔
25
        .collect();
21,626✔
26

21,626✔
27
    key.join("#".as_bytes())
21,626✔
28
}
21,626✔
29

30
/// Returns the secondary index key for a given set of fields.
31
///
32
/// We allow computing the secondary index key of "prefix" fields, so the user can filter the "prefix" fields using `Eq` filters,
33
/// and sort the filtering result using other fields.
34
///
35
/// In the meantime, we compute the key differently for single field indexes and compound indexes.
36
/// We'are not able to tell if certain `fields` belong to a single field index or compound index if its length is 1, hence the second parameter.
37
///
38
/// # Parameters
39
/// - `fields`: The fields to index.
40
/// - `is_single_field_index`: Whether the `fields` belong to a single field index. If `true`, `fields` must have length 1.
41
pub fn get_secondary_index(fields: &[&Field], is_single_field_index: bool) -> Vec<u8> {
152,787✔
42
    debug_assert!(!is_single_field_index || fields.len() == 1);
153,315✔
43
    if is_single_field_index {
152,754✔
44
        fields[0].encode()
102,289✔
45
    } else {
46
        get_composite_secondary_index(fields)
50,465✔
47
    }
48
}
152,754✔
49

50
pub fn compare_composite_secondary_index(a: &[u8], b: &[u8]) -> Result<Ordering, CompareError> {
2,552,470✔
51
    let mut a = CompositeSecondaryIndexKey::new(a);
2,552,470✔
52
    let mut b = CompositeSecondaryIndexKey::new(b);
2,552,470✔
53
    Ok(loop {
54
        match (a.next(), b.next()) {
5,414,609✔
55
            (Some(a), Some(b)) => {
4,857,439✔
56
                let a = a?;
4,857,439✔
57
                let b = b?;
4,857,439✔
58
                match a.cmp(&b) {
4,857,439✔
59
                    Ordering::Equal => continue,
2,862,139✔
60
                    ordering => break ordering,
1,995,300✔
61
                }
62
            }
63
            (Some(_), None) => break Ordering::Greater,
547,060✔
64
            (None, Some(_)) => break Ordering::Less,
9,162✔
65
            (None, None) => break Ordering::Equal,
948✔
66
        }
67
    })
68
}
2,552,470✔
69

70
pub fn get_full_text_secondary_index(token: &str) -> Vec<u8> {
40,754✔
71
    token.as_bytes().to_vec()
40,754✔
72
}
40,754✔
73

74
fn get_composite_secondary_index(fields: &[&Field]) -> Vec<u8> {
53,199✔
75
    fn get_field_encoding_len(field: &Field) -> usize {
234,068✔
76
        8 + field.encoding_len()
234,068✔
77
    }
234,068✔
78

53,199✔
79
    let total_len = fields
53,199✔
80
        .iter()
53,199✔
81
        .map(|field| get_field_encoding_len(field))
117,110✔
82
        .sum::<usize>();
53,199✔
83
    let mut buf = vec![0; total_len];
53,199✔
84
    let mut offset = 0;
53,199✔
85
    for field in fields {
170,295✔
86
        let field_len = get_field_encoding_len(field);
117,096✔
87
        buf[offset..offset + 8].copy_from_slice(&(field_len as u64).to_be_bytes());
117,096✔
88
        field.encode_buf(&mut buf[offset + 8..offset + field_len]);
117,096✔
89
        offset += field_len;
117,096✔
90
    }
117,096✔
91
    buf
53,199✔
92
}
53,199✔
93

94
struct CompositeSecondaryIndexKey<'a> {
95
    buf: &'a [u8],
96
    offset: usize,
97
}
98

99
impl<'a> CompositeSecondaryIndexKey<'a> {
100
    fn new(buf: &'a [u8]) -> Self {
5,105,446✔
101
        Self { buf, offset: 0 }
5,105,446✔
102
    }
5,105,446✔
103

104
    fn decode_one(&mut self) -> Result<FieldBorrow<'a>, CompareError> {
10,272,091✔
105
        if self.offset + 8 > self.buf.len() {
10,272,091✔
106
            return Err(CompareError::CannotReadFieldLength);
×
107
        }
10,272,091✔
108

10,272,091✔
109
        let field_len = u64::from_be_bytes(
10,272,091✔
110
            self.buf[self.offset..self.offset + 8]
10,272,091✔
111
                .try_into()
10,272,091✔
112
                .expect("We have checked `buf` is long enough"),
10,272,091✔
113
        ) as usize;
10,272,091✔
114
        if self.offset + field_len > self.buf.len() {
10,272,091✔
115
            return Err(CompareError::CannotReadField);
×
116
        }
10,272,091✔
117

118
        let field = Field::decode_borrow(&self.buf[self.offset + 8..self.offset + field_len])?;
10,272,091✔
119
        self.offset += field_len;
10,272,090✔
120
        Ok(field)
10,272,090✔
121
    }
10,272,090✔
122
}
123

124
impl<'a> Iterator for CompositeSecondaryIndexKey<'a> {
125
    type Item = Result<FieldBorrow<'a>, CompareError>;
126

127
    fn next(&mut self) -> Option<Self::Item> {
10,830,714✔
128
        if self.offset >= self.buf.len() {
10,830,714✔
129
            return None;
558,624✔
130
        }
10,272,090✔
131

10,272,090✔
132
        let result = self.decode_one();
10,272,090✔
133
        if result.is_err() {
10,272,090✔
134
            // Once an error happens, we stop decoding the rest of the buffer.
×
135
            self.offset = self.buf.len();
×
136
        }
10,272,091✔
137
        Some(result)
10,272,091✔
138
    }
10,830,715✔
139
}
140

141
#[cfg(test)]
142
mod tests;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc