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

getdozer / dozer / 4370408272

pending completion
4370408272

push

github

GitHub
fix: Fix compilation error introduced in #1158 (#1183)

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

28163 of 39541 relevant lines covered (71.22%)

73625.66 hits per line

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

67.97
/dozer-sql/src/pipeline/expression/datetime.rs
1
use crate::pipeline::errors::PipelineError::{
2
    InvalidFunctionArgument, InvalidFunctionArgumentType,
3
};
4
use crate::pipeline::errors::{FieldTypes, PipelineError};
5

6
use crate::pipeline::expression::datetime::PipelineError::InvalidValue;
7
use crate::pipeline::expression::execution::{Expression, ExpressionExecutor, ExpressionType};
8
use dozer_types::chrono::{DateTime, Datelike, Offset, Timelike, Utc};
9
use dozer_types::types::{Field, FieldType, Record, Schema};
10
use num_traits::ToPrimitive;
11
use sqlparser::ast::DateTimeField;
12
use std::fmt::{Display, Formatter};
×
13

14
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
32✔
15
pub enum DateTimeFunctionType {
16
    Extract {
17
        field: sqlparser::ast::DateTimeField,
18
    },
×
19
}
×
20

×
21
impl Display for DateTimeFunctionType {
×
22
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
×
23
        match self {
×
24
            DateTimeFunctionType::Extract { field } => {
×
25
                f.write_str(format!("EXTRACT {field}").as_str())
×
26
            }
×
27
        }
×
28
    }
×
29
}
×
30

×
31
pub(crate) fn get_datetime_function_type(
32✔
32
    function: &DateTimeFunctionType,
32✔
33
    arg: &Expression,
32✔
34
    schema: &Schema,
32✔
35
) -> Result<ExpressionType, PipelineError> {
32✔
36
    let return_type = arg.get_type(schema)?.return_type;
32✔
37
    if return_type != FieldType::Date && return_type != FieldType::Timestamp {
32✔
38
        return Err(InvalidFunctionArgumentType(
×
39
            function.to_string(),
×
40
            return_type,
×
41
            FieldTypes::new(vec![FieldType::Date, FieldType::Timestamp]),
×
42
            0,
×
43
        ));
×
44
    }
32✔
45
    match function {
32✔
46
        DateTimeFunctionType::Extract { field: _ } => Ok(ExpressionType::new(
32✔
47
            FieldType::Int,
32✔
48
            false,
32✔
49
            dozer_types::types::SourceDefinition::Dynamic,
32✔
50
            false,
32✔
51
        )),
32✔
52
    }
53
}
32✔
54

×
55
impl DateTimeFunctionType {
×
56
    pub(crate) fn evaluate(
32✔
57
        &self,
32✔
58
        schema: &Schema,
32✔
59
        arg: &Expression,
32✔
60
        record: &Record,
32✔
61
    ) -> Result<Field, PipelineError> {
32✔
62
        match self {
32✔
63
            DateTimeFunctionType::Extract { field } => {
32✔
64
                evaluate_date_part(schema, field, arg, record)
32✔
65
            }
32✔
66
        }
32✔
67
    }
32✔
68
}
×
69

×
70
pub(crate) fn evaluate_date_part(
38✔
71
    schema: &Schema,
38✔
72
    field: &sqlparser::ast::DateTimeField,
38✔
73
    arg: &Expression,
38✔
74
    record: &Record,
38✔
75
) -> Result<Field, PipelineError> {
38✔
76
    let value = arg.evaluate(record, schema)?;
38✔
77

×
78
    let ts = match value {
38✔
79
        Field::Timestamp(ts) => Ok(ts),
16✔
80
        Field::Date(d) => d
22✔
81
            .and_hms_milli_opt(0, 0, 0, 0)
22✔
82
            .map(|ts| DateTime::from_utc(ts, Utc.fix()))
22✔
83
            .ok_or(InvalidValue(format!(
22✔
84
                "Unable to cast date {d} to timestamp"
22✔
85
            ))),
22✔
86
        _ => {
×
87
            return Err(InvalidFunctionArgument(
×
88
                DateTimeFunctionType::Extract { field: *field }.to_string(),
×
89
                value,
×
90
                0,
×
91
            ))
×
92
        }
×
93
    }?;
×
94

95
    match field {
38✔
96
        DateTimeField::Dow => ts.weekday().num_days_from_monday().to_i64(),
3✔
97
        DateTimeField::Day => ts.day().to_i64(),
2✔
98
        DateTimeField::Month => ts.month().to_i64(),
3✔
99
        DateTimeField::Year => ts.year().to_i64(),
3✔
100
        DateTimeField::Hour => ts.hour().to_i64(),
3✔
101
        DateTimeField::Minute => ts.minute().to_i64(),
2✔
102
        DateTimeField::Second => ts.second().to_i64(),
3✔
103
        DateTimeField::Millisecond | DateTimeField::Milliseconds => ts.timestamp_millis().to_i64(),
2✔
104
        DateTimeField::Microsecond | DateTimeField::Microseconds => ts.timestamp_micros().to_i64(),
2✔
105
        DateTimeField::Nanoseconds | DateTimeField::Nanosecond => ts.timestamp_nanos().to_i64(),
2✔
106
        DateTimeField::Quarter => ts.month0().to_i64().map(|m| m / 3 + 1),
3✔
107
        DateTimeField::Epoch => ts.timestamp().to_i64(),
2✔
108
        DateTimeField::Week => ts.iso_week().week().to_i64(),
2✔
109
        DateTimeField::Century => ts.year().to_i64().map(|y| (y as f64 / 100.0).ceil() as i64),
2✔
110
        DateTimeField::Decade => ts.year().to_i64().map(|y| (y as f64 / 10.0).ceil() as i64),
2✔
111
        DateTimeField::Doy => ts.ordinal().to_i64(),
2✔
112
        DateTimeField::Timezone => ts.offset().fix().local_minus_utc().to_i64(),
×
113
        DateTimeField::Isodow
×
114
        | DateTimeField::Isoyear
×
115
        | DateTimeField::Julian
×
116
        | DateTimeField::Millenium
×
117
        | DateTimeField::Millennium
×
118
        | DateTimeField::TimezoneHour
×
119
        | DateTimeField::TimezoneMinute
120
        | DateTimeField::Date
121
        | DateTimeField::NoDateTime => None,
×
122
    }
123
    .ok_or(PipelineError::InvalidOperandType(format!(
38✔
124
        "Unable to extract date part {field} from {value}"
38✔
125
    )))
38✔
126
    .map(Field::Int)
38✔
127
}
38✔
128

129
#[test]
1✔
130
fn test_date_parts() {
1✔
131
    let row = Record::new(None, vec![], None);
1✔
132

1✔
133
    let date_parts = vec![
1✔
134
        (DateTimeField::Dow, 6),
1✔
135
        (DateTimeField::Year, 2023),
1✔
136
        (DateTimeField::Month, 1),
1✔
137
        (DateTimeField::Hour, 0),
1✔
138
        (DateTimeField::Second, 0),
1✔
139
        (DateTimeField::Quarter, 1),
1✔
140
    ];
1✔
141
    let v = Expression::Literal(Field::Date(
1✔
142
        dozer_types::chrono::NaiveDate::from_ymd_opt(2023, 1, 1).unwrap(),
1✔
143
    ));
1✔
144

145
    for (part, value) in date_parts {
7✔
146
        assert_eq!(
6✔
147
            evaluate_date_part(&Schema::empty(), &part, &v, &row).unwrap(),
6✔
148
            Field::Int(value)
6✔
149
        );
6✔
150
    }
151
}
1✔
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