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

vortex-data / vortex / 16970635821

14 Aug 2025 04:13PM UTC coverage: 85.882% (-1.8%) from 87.693%
16970635821

Pull #4215

github

web-flow
Merge 5182504a6 into f547cbca5
Pull Request #4215: Ji/vectors

80 of 1729 new or added lines in 38 files covered. (4.63%)

117 existing lines in 25 files now uncovered.

56994 of 66363 relevant lines covered (85.88%)

609331.7 hits per line

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

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

4
use std::fmt::Display;
5

6
use vortex_array::arrays::ConstantArray;
7
use vortex_array::{ArrayRef, DeserializeMetadata, IntoArray, ProstMetadata};
8
use vortex_dtype::{DType, match_each_float_ptype};
9
use vortex_error::{VortexResult, vortex_bail, vortex_err};
10
use vortex_proto::expr as pb;
11
use vortex_scalar::Scalar;
12

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

17
vtable!(Literal);
18

19
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
20
pub struct LiteralExpr {
21
    value: Scalar,
22
}
23

24
pub struct LiteralExprEncoding;
25

26
impl VTable for LiteralVTable {
27
    type Expr = LiteralExpr;
28
    type Encoding = LiteralExprEncoding;
29
    type Metadata = ProstMetadata<pb::LiteralOpts>;
30

31
    fn id(_encoding: &Self::Encoding) -> ExprId {
189✔
32
        ExprId::new_ref("literal")
189✔
33
    }
189✔
34

35
    fn encoding(_expr: &Self::Expr) -> ExprEncodingRef {
22✔
36
        ExprEncodingRef::new_ref(LiteralExprEncoding.as_ref())
22✔
37
    }
22✔
38

39
    fn metadata(expr: &Self::Expr) -> Option<Self::Metadata> {
22✔
40
        Some(ProstMetadata(pb::LiteralOpts {
22✔
41
            value: Some((&expr.value).into()),
22✔
42
        }))
22✔
43
    }
22✔
44

45
    fn children(_expr: &Self::Expr) -> Vec<&ExprRef> {
76,678✔
46
        vec![]
76,678✔
47
    }
76,678✔
48

UNCOV
49
    fn with_children(expr: &Self::Expr, _children: Vec<ExprRef>) -> VortexResult<Self::Expr> {
×
UNCOV
50
        Ok(expr.clone())
×
51
    }
52

53
    fn build(
22✔
54
        _encoding: &Self::Encoding,
22✔
55
        metadata: &<Self::Metadata as DeserializeMetadata>::Output,
22✔
56
        children: Vec<ExprRef>,
22✔
57
    ) -> VortexResult<Self::Expr> {
22✔
58
        if !children.is_empty() {
22✔
UNCOV
59
            vortex_bail!(
×
UNCOV
60
                "Literal expression does not have children, got: {:?}",
×
61
                children
62
            );
63
        }
22✔
64
        let value: Scalar = metadata
22✔
65
            .value
22✔
66
            .as_ref()
22✔
67
            .ok_or_else(|| vortex_err!("Literal metadata missing value"))?
22✔
68
            .try_into()?;
22✔
69
        Ok(LiteralExpr::new(value))
22✔
70
    }
22✔
71

72
    fn evaluate(expr: &Self::Expr, scope: &Scope) -> VortexResult<ArrayRef> {
8,291✔
73
        Ok(ConstantArray::new(expr.value.clone(), scope.len()).into_array())
8,291✔
74
    }
8,291✔
75

76
    fn return_dtype(expr: &Self::Expr, _scope: &DType) -> VortexResult<DType> {
11,532✔
77
        Ok(expr.value.dtype().clone())
11,532✔
78
    }
11,532✔
79
}
80

81
impl LiteralExpr {
82
    pub fn new(value: impl Into<Scalar>) -> Self {
41,423✔
83
        Self {
41,423✔
84
            value: value.into(),
41,423✔
85
        }
41,423✔
86
    }
41,423✔
87

88
    pub fn new_expr(value: impl Into<Scalar>) -> ExprRef {
7✔
89
        Self::new(value).into_expr()
7✔
90
    }
7✔
91

92
    pub fn value(&self) -> &Scalar {
947✔
93
        &self.value
947✔
94
    }
947✔
95

96
    pub fn maybe_from(expr: &ExprRef) -> Option<&LiteralExpr> {
1,053✔
97
        expr.as_opt::<LiteralVTable>()
1,053✔
98
    }
1,053✔
99
}
100

101
impl Display for LiteralExpr {
102
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12✔
103
        write!(f, "{}", self.value)
12✔
104
    }
12✔
105
}
106

107
impl AnalysisExpr for LiteralExpr {
108
    fn max(&self, _catalog: &mut dyn StatsCatalog) -> Option<ExprRef> {
708✔
109
        Some(lit(self.value.clone()))
708✔
110
    }
708✔
111

112
    fn min(&self, _catalog: &mut dyn StatsCatalog) -> Option<ExprRef> {
883✔
113
        Some(lit(self.value.clone()))
883✔
114
    }
883✔
115

116
    fn nan_count(&self, _catalog: &mut dyn StatsCatalog) -> Option<ExprRef> {
973✔
117
        // The NaNCount for a non-float literal is not defined.
118
        // For floating point types, the NaNCount is 1 for lit(NaN), and 0 otherwise.
119
        let value = self.value.as_primitive_opt()?;
973✔
120
        if !value.ptype().is_float() {
595✔
121
            return None;
551✔
122
        }
44✔
123

124
        match_each_float_ptype!(value.ptype(), |T| {
44✔
UNCOV
125
            match value.typed_value::<T>() {
×
126
                None => Some(lit(0u64)),
127
                Some(value) if value.is_nan() => Some(lit(1u64)),
UNCOV
128
                _ => Some(lit(0u64)),
×
129
            }
130
        })
131
    }
973✔
132
}
133

134
/// Create a new `Literal` expression from a type that coerces to `Scalar`.
135
///
136
///
137
/// ## Example usage
138
///
139
/// ```
140
/// use vortex_array::arrays::PrimitiveArray;
141
/// use vortex_dtype::Nullability;
142
/// use vortex_expr::{lit, LiteralVTable};
143
/// use vortex_scalar::Scalar;
144
///
145
/// let number = lit(34i32);
146
///
147
/// let literal = number.as_::<LiteralVTable>();
148
/// assert_eq!(literal.value(), &Scalar::primitive(34i32, Nullability::NonNullable));
149
/// ```
150
pub fn lit(value: impl Into<Scalar>) -> ExprRef {
15,732✔
151
    LiteralExpr::new(value.into()).into_expr()
15,732✔
152
}
15,732✔
153

154
#[cfg(test)]
155
mod tests {
156
    use vortex_dtype::{DType, Nullability, PType, StructFields};
157
    use vortex_scalar::Scalar;
158

159
    use crate::{lit, test_harness};
160

161
    #[test]
162
    fn dtype() {
1✔
163
        let dtype = test_harness::struct_dtype();
1✔
164

165
        assert_eq!(
1✔
166
            lit(10).return_dtype(&dtype).unwrap(),
1✔
167
            DType::Primitive(PType::I32, Nullability::NonNullable)
168
        );
169
        assert_eq!(
1✔
170
            lit(i64::MAX).return_dtype(&dtype).unwrap(),
1✔
171
            DType::Primitive(PType::I64, Nullability::NonNullable)
172
        );
173
        assert_eq!(
1✔
174
            lit(true).return_dtype(&dtype).unwrap(),
1✔
175
            DType::Bool(Nullability::NonNullable)
176
        );
177
        assert_eq!(
1✔
178
            lit(Scalar::null(DType::Bool(Nullability::Nullable)))
1✔
179
                .return_dtype(&dtype)
1✔
180
                .unwrap(),
1✔
181
            DType::Bool(Nullability::Nullable)
182
        );
183

184
        let sdtype = DType::Struct(
1✔
185
            StructFields::new(
1✔
186
                ["dog", "cat"].into(),
1✔
187
                vec![
1✔
188
                    DType::Primitive(PType::U32, Nullability::NonNullable),
1✔
189
                    DType::Utf8(Nullability::NonNullable),
1✔
190
                ],
1✔
191
            ),
1✔
192
            Nullability::NonNullable,
1✔
193
        );
1✔
194
        assert_eq!(
1✔
195
            lit(Scalar::struct_(
1✔
196
                sdtype.clone(),
1✔
197
                vec![Scalar::from(32_u32), Scalar::from("rufus".to_string())]
1✔
198
            ))
1✔
199
            .return_dtype(&dtype)
1✔
200
            .unwrap(),
1✔
201
            sdtype
202
        );
203
    }
1✔
204
}
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