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

vortex-data / vortex / 16728097825

04 Aug 2025 04:00PM UTC coverage: 48.355% (-35.1%) from 83.429%
16728097825

Pull #4108

github

web-flow
Merge 1b2d27fd8 into 649ba9576
Pull Request #4108: perf[vortex-array]: use all_valid instead of `invalid_count() == 0`

1 of 1 new or added line in 1 file covered. (100.0%)

11596 existing lines in 378 files now uncovered.

18635 of 38538 relevant lines covered (48.35%)

151786.4 hits per line

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

65.31
/vortex-expr/src/exprs/get_item.rs
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3

4
use std::fmt::{Debug, Display, Formatter};
5
use std::hash::Hash;
6

7
use vortex_array::stats::Stat;
8
use vortex_array::{ArrayRef, DeserializeMetadata, ProstMetadata, ToCanonical};
9
use vortex_dtype::{DType, FieldName, FieldPath};
10
use vortex_error::{VortexResult, vortex_bail, vortex_err};
11
use vortex_proto::expr as pb;
12

13
use crate::{
14
    AnalysisExpr, ExprEncodingRef, ExprId, ExprRef, IntoExpr, Scope, StatsCatalog, VTable, root,
15
    vtable,
16
};
17

18
vtable!(GetItem);
19

20
#[allow(clippy::derived_hash_with_manual_eq)]
21
#[derive(Debug, Clone, Hash, Eq)]
22
pub struct GetItemExpr {
23
    field: FieldName,
24
    child: ExprRef,
25
}
26

27
impl PartialEq for GetItemExpr {
28
    fn eq(&self, other: &Self) -> bool {
31,050✔
29
        self.field == other.field && self.child.eq(&other.child)
31,050✔
30
    }
31,050✔
31
}
32

33
pub struct GetItemExprEncoding;
34

35
impl VTable for GetItemVTable {
36
    type Expr = GetItemExpr;
37
    type Encoding = GetItemExprEncoding;
38
    type Metadata = ProstMetadata<pb::GetItemOpts>;
39

40
    fn id(_encoding: &Self::Encoding) -> ExprId {
22✔
41
        ExprId::new_ref("get_item")
22✔
42
    }
22✔
43

UNCOV
44
    fn encoding(_expr: &Self::Expr) -> ExprEncodingRef {
×
UNCOV
45
        ExprEncodingRef::new_ref(GetItemExprEncoding.as_ref())
×
UNCOV
46
    }
×
47

UNCOV
48
    fn metadata(expr: &Self::Expr) -> Option<Self::Metadata> {
×
UNCOV
49
        Some(ProstMetadata(pb::GetItemOpts {
×
UNCOV
50
            path: expr.field.to_string(),
×
UNCOV
51
        }))
×
UNCOV
52
    }
×
53

54
    fn children(expr: &Self::Expr) -> Vec<&ExprRef> {
150,844✔
55
        vec![&expr.child]
150,844✔
56
    }
150,844✔
57

58
    fn with_children(expr: &Self::Expr, children: Vec<ExprRef>) -> VortexResult<Self::Expr> {
2,406✔
59
        Ok(GetItemExpr {
2,406✔
60
            field: expr.field.clone(),
2,406✔
61
            child: children[0].clone(),
2,406✔
62
        })
2,406✔
63
    }
2,406✔
64

UNCOV
65
    fn build(
×
UNCOV
66
        _encoding: &Self::Encoding,
×
UNCOV
67
        metadata: &<Self::Metadata as DeserializeMetadata>::Output,
×
UNCOV
68
        children: Vec<ExprRef>,
×
UNCOV
69
    ) -> VortexResult<Self::Expr> {
×
UNCOV
70
        if children.len() != 1 {
×
71
            vortex_bail!(
×
72
                "GetItem expression must have exactly 1 child, got {}",
×
73
                children.len()
×
74
            );
UNCOV
75
        }
×
76

UNCOV
77
        let field = FieldName::from(metadata.path.clone());
×
UNCOV
78
        Ok(GetItemExpr {
×
UNCOV
79
            field,
×
UNCOV
80
            child: children[0].clone(),
×
UNCOV
81
        })
×
UNCOV
82
    }
×
83

84
    fn evaluate(expr: &Self::Expr, scope: &Scope) -> VortexResult<ArrayRef> {
11,978✔
85
        expr.child
11,978✔
86
            .unchecked_evaluate(scope)?
11,978✔
87
            .to_struct()?
11,978✔
88
            .field_by_name(expr.field())
11,978✔
89
            .cloned()
11,978✔
90
    }
11,978✔
91

92
    fn return_dtype(expr: &Self::Expr, scope: &DType) -> VortexResult<DType> {
17,174✔
93
        let input = expr.child.return_dtype(scope)?;
17,174✔
94
        input
17,174✔
95
            .as_struct()
17,174✔
96
            .and_then(|st| st.field(expr.field()))
17,174✔
97
            .ok_or_else(|| {
17,174✔
98
                vortex_err!(
×
99
                    "Couldn't find the {} field in the input scope",
×
100
                    expr.field()
×
101
                )
102
            })
×
103
    }
17,174✔
104
}
105

106
impl GetItemExpr {
107
    pub fn new(field: impl Into<FieldName>, child: ExprRef) -> Self {
16,562✔
108
        Self {
16,562✔
109
            field: field.into(),
16,562✔
110
            child,
16,562✔
111
        }
16,562✔
112
    }
16,562✔
113

114
    pub fn new_expr(field: impl Into<FieldName>, child: ExprRef) -> ExprRef {
×
115
        Self::new(field, child).into_expr()
×
116
    }
×
117

118
    pub fn field(&self) -> &FieldName {
36,534✔
119
        &self.field
36,534✔
120
    }
36,534✔
121

122
    pub fn child(&self) -> &ExprRef {
70,128✔
123
        &self.child
70,128✔
124
    }
70,128✔
125

126
    pub fn is(expr: &ExprRef) -> bool {
1,288✔
127
        expr.is::<GetItemVTable>()
1,288✔
128
    }
1,288✔
129
}
130

131
pub fn col(field: impl Into<FieldName>) -> ExprRef {
5,992✔
132
    GetItemExpr::new(field, root()).into_expr()
5,992✔
133
}
5,992✔
134

135
pub fn get_item(field: impl Into<FieldName>, child: ExprRef) -> ExprRef {
10,570✔
136
    GetItemExpr::new(field, child).into_expr()
10,570✔
137
}
10,570✔
138

139
impl Display for GetItemExpr {
UNCOV
140
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
×
UNCOV
141
        write!(f, "{}.{}", self.child, &self.field)
×
UNCOV
142
    }
×
143
}
144

145
impl AnalysisExpr for GetItemExpr {
146
    fn max(&self, catalog: &mut dyn StatsCatalog) -> Option<ExprRef> {
198✔
147
        catalog.stats_ref(&self.field_path()?, Stat::Max)
198✔
148
    }
198✔
149

150
    fn min(&self, catalog: &mut dyn StatsCatalog) -> Option<ExprRef> {
204✔
151
        catalog.stats_ref(&self.field_path()?, Stat::Min)
204✔
152
    }
204✔
153

154
    fn nan_count(&self, catalog: &mut dyn StatsCatalog) -> Option<ExprRef> {
292✔
155
        catalog.stats_ref(&self.field_path()?, Stat::NaNCount)
292✔
156
    }
292✔
157

158
    fn field_path(&self) -> Option<FieldPath> {
694✔
159
        self.child()
694✔
160
            .field_path()
694✔
161
            .map(|fp| fp.push(self.field.clone()))
694✔
162
    }
694✔
163
}
164

165
#[cfg(test)]
166
mod tests {
167
    use vortex_array::IntoArray;
168
    use vortex_array::arrays::StructArray;
169
    use vortex_buffer::buffer;
170
    use vortex_dtype::DType;
171
    use vortex_dtype::PType::I32;
172

173
    use crate::get_item::get_item;
174
    use crate::{Scope, root};
175

176
    fn test_array() -> StructArray {
177
        StructArray::from_fields(&[
178
            ("a", buffer![0i32, 1, 2].into_array()),
179
            ("b", buffer![4i64, 5, 6].into_array()),
180
        ])
181
        .unwrap()
182
    }
183

184
    #[test]
185
    pub fn get_item_by_name() {
186
        let st = test_array();
187
        let get_item = get_item("a", root());
188
        let item = get_item.evaluate(&Scope::new(st.to_array())).unwrap();
189
        assert_eq!(item.dtype(), &DType::from(I32))
190
    }
191

192
    #[test]
193
    pub fn get_item_by_name_none() {
194
        let st = test_array();
195
        let get_item = get_item("c", root());
196
        assert!(get_item.evaluate(&Scope::new(st.to_array())).is_err());
197
    }
198
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc