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

vortex-data / vortex / 16935267080

13 Aug 2025 11:00AM UTC coverage: 24.312% (-63.3%) from 87.658%
16935267080

Pull #4226

github

web-flow
Merge 81b48c7fb into baa6ea202
Pull Request #4226: Support converting TimestampTZ to and from duckdb

0 of 2 new or added lines in 1 file covered. (0.0%)

20666 existing lines in 469 files now uncovered.

8726 of 35892 relevant lines covered (24.31%)

147.74 hits per line

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

0.0
/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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

UNCOV
116
    fn nan_count(&self, _catalog: &mut dyn StatsCatalog) -> Option<ExprRef> {
×
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.
UNCOV
119
        let value = self.value.as_primitive_opt()?;
×
UNCOV
120
        if !value.ptype().is_float() {
×
UNCOV
121
            return None;
×
UNCOV
122
        }
×
123

UNCOV
124
        match_each_float_ptype!(value.ptype(), |T| {
×
125
            match value.typed_value::<T>() {
×
126
                None => Some(lit(0u64)),
×
127
                Some(value) if value.is_nan() => Some(lit(1u64)),
×
128
                _ => Some(lit(0u64)),
×
129
            }
130
        })
UNCOV
131
    }
×
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
/// ```
UNCOV
150
pub fn lit(value: impl Into<Scalar>) -> ExprRef {
×
UNCOV
151
    LiteralExpr::new(value.into()).into_expr()
×
UNCOV
152
}
×
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() {
163
        let dtype = test_harness::struct_dtype();
164

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

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