Skip to main content

mz_sql/plan/
literal.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10use mz_repr::adt::interval::{Interval, RoundBehavior};
11use mz_repr::strconv;
12use mz_sql_parser::ast::IntervalValue;
13
14use crate::plan::PlanError;
15
16/// Convert an [`IntervalValue`] into an [`Interval`].
17///
18/// The reverse of [`unplan_interval`].
19pub fn plan_interval(iv: &IntervalValue) -> Result<Interval, PlanError> {
20    let leading_precision = parser_datetimefield_to_adt(iv.precision_high);
21    let mut i = strconv::parse_interval_w_disambiguator(
22        &iv.value,
23        match leading_precision {
24            mz_repr::adt::datetime::DateTimeField::Hour
25            | mz_repr::adt::datetime::DateTimeField::Minute => Some(leading_precision),
26            _ => None,
27        },
28        parser_datetimefield_to_adt(iv.precision_low),
29    )?;
30    // Like PostgreSQL, the range qualifier only disambiguates parsing and
31    // discards fields below precision_low. Fields above precision_high are
32    // kept as written.
33    i.truncate_low_fields(
34        parser_datetimefield_to_adt(iv.precision_low),
35        iv.fsec_max_precision,
36        RoundBehavior::Nearest,
37    )?;
38    Ok(i)
39}
40
41/// Convert an [`Interval`] into an [`IntervalValue`].
42///
43/// The reverse of [`plan_interval`].
44pub fn unplan_interval(i: &Interval) -> IntervalValue {
45    let mut iv = IntervalValue::default();
46    iv.value = i.to_string();
47    iv
48}
49
50fn parser_datetimefield_to_adt(
51    dtf: mz_sql_parser::ast::DateTimeField,
52) -> mz_repr::adt::datetime::DateTimeField {
53    use mz_sql_parser::ast::DateTimeField::*;
54    match dtf {
55        Millennium => mz_repr::adt::datetime::DateTimeField::Millennium,
56        Century => mz_repr::adt::datetime::DateTimeField::Century,
57        Decade => mz_repr::adt::datetime::DateTimeField::Decade,
58        Year => mz_repr::adt::datetime::DateTimeField::Year,
59        Month => mz_repr::adt::datetime::DateTimeField::Month,
60        Day => mz_repr::adt::datetime::DateTimeField::Day,
61        Hour => mz_repr::adt::datetime::DateTimeField::Hour,
62        Minute => mz_repr::adt::datetime::DateTimeField::Minute,
63        Second => mz_repr::adt::datetime::DateTimeField::Second,
64        Milliseconds => mz_repr::adt::datetime::DateTimeField::Milliseconds,
65        Microseconds => mz_repr::adt::datetime::DateTimeField::Microseconds,
66    }
67}