mz_sql_parser/ast/defs/
value.rs

1// Copyright 2018 sqlparser-rs contributors. All rights reserved.
2// Copyright Materialize, Inc. and contributors. All rights reserved.
3//
4// This file is derived from the sqlparser-rs project, available at
5// https://github.com/andygrove/sqlparser-rs. It was incorporated
6// directly into Materialize on December 21, 2019.
7//
8// Licensed under the Apache License, Version 2.0 (the "License");
9// you may not use this file except in compliance with the License.
10// You may obtain a copy of the License in the LICENSE file at the
11// root of this repository, or online at
12//
13//     http://www.apache.org/licenses/LICENSE-2.0
14//
15// Unless required by applicable law or agreed to in writing, software
16// distributed under the License is distributed on an "AS IS" BASIS,
17// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18// See the License for the specific language governing permissions and
19// limitations under the License.
20
21use std::fmt;
22use std::str::FromStr;
23
24use serde::{Deserialize, Serialize};
25
26use crate::ast::Ident;
27use crate::ast::display::{self, AstDisplay, AstFormatter};
28
29#[derive(Debug)]
30pub struct ValueError(pub(crate) String);
31
32impl std::error::Error for ValueError {}
33
34impl fmt::Display for ValueError {
35    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36        write!(f, "{}", self.0)
37    }
38}
39
40/// Primitive SQL values.
41#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
42pub enum Value {
43    /// Numeric value.
44    Number(String),
45    /// String value.
46    String(String),
47    /// Hex string value.
48    HexString(String),
49    /// Boolean value.
50    Boolean(bool),
51    /// INTERVAL literals, roughly in the following format:
52    ///
53    /// ```text
54    /// INTERVAL '<value>' <leading_field> [ TO <last_field>
55    ///     [ (<fractional_seconds_precision>) ] ]
56    /// ```
57    /// e.g. `INTERVAL '123:45.678' MINUTE TO SECOND(2)`.
58    Interval(IntervalValue),
59    /// `NULL` value.
60    Null,
61}
62
63impl AstDisplay for Value {
64    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
65        if f.redacted() {
66            // When adding branches to this match statement, think about whether it is OK for us to collect
67            // the value as part of our telemetry. Check the data management policy to be sure!
68            match self {
69                Value::Number(_) | Value::String(_) | Value::HexString(_) => {
70                    f.write_str("'<REDACTED>'");
71                    return;
72                }
73                Value::Interval(_) => {
74                    f.write_str("INTERVAL '<REDACTED>'");
75                    return;
76                }
77                Value::Boolean(_) | Value::Null => {
78                    // These are fine to log, so just fall through.
79                }
80            }
81        }
82        match self {
83            Value::Number(v) => f.write_str(v),
84            Value::String(v) => {
85                f.write_str("'");
86                f.write_node(&display::escape_single_quote_string(v));
87                f.write_str("'");
88            }
89            Value::HexString(v) => {
90                f.write_str("X'");
91                f.write_str(v);
92                f.write_str("'");
93            }
94            Value::Boolean(v) => f.write_str(v),
95            Value::Interval(interval_value) => {
96                f.write_str("INTERVAL '");
97                f.write_node(interval_value);
98            }
99            Value::Null => f.write_str("NULL"),
100        }
101    }
102}
103impl_display!(Value);
104
105impl AstDisplay for IntervalValue {
106    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
107        if f.redacted() {
108            f.write_str("<REDACTED>'");
109        } else {
110            let IntervalValue {
111                value,
112                precision_high,
113                precision_low,
114                fsec_max_precision,
115            } = self;
116            f.write_node(&display::escape_single_quote_string(value));
117            f.write_str("'");
118            match (precision_high, precision_low, fsec_max_precision) {
119                (DateTimeField::Year, DateTimeField::Second, None) => {}
120                (DateTimeField::Year, DateTimeField::Second, Some(ns)) => {
121                    f.write_str(" SECOND(");
122                    f.write_str(ns);
123                    f.write_str(")");
124                }
125                (DateTimeField::Year, low, None) => {
126                    f.write_str(" ");
127                    f.write_str(low);
128                }
129                (high, low, None) => {
130                    f.write_str(" ");
131                    f.write_str(high);
132                    f.write_str(" TO ");
133                    f.write_str(low);
134                }
135                (high, low, Some(ns)) => {
136                    f.write_str(" ");
137                    f.write_str(high);
138                    f.write_str(" TO ");
139                    f.write_str(low);
140                    f.write_str("(");
141                    f.write_str(ns);
142                    f.write_str(")");
143                }
144            }
145        }
146    }
147}
148
149impl From<Ident> for Value {
150    fn from(ident: Ident) -> Self {
151        Self::String(ident.0)
152    }
153}
154
155#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize)]
156pub enum DateTimeField {
157    Millennium,
158    Century,
159    Decade,
160    Year,
161    Month,
162    Day,
163    Hour,
164    Minute,
165    Second,
166    Milliseconds,
167    Microseconds,
168}
169
170impl fmt::Display for DateTimeField {
171    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
172        f.write_str(match self {
173            DateTimeField::Millennium => "MILLENNIUM",
174            DateTimeField::Century => "CENTURY",
175            DateTimeField::Decade => "DECADE",
176            DateTimeField::Year => "YEAR",
177            DateTimeField::Month => "MONTH",
178            DateTimeField::Day => "DAY",
179            DateTimeField::Hour => "HOUR",
180            DateTimeField::Minute => "MINUTE",
181            DateTimeField::Second => "SECOND",
182            DateTimeField::Milliseconds => "MILLISECONDS",
183            DateTimeField::Microseconds => "MICROSECONDS",
184        })
185    }
186}
187
188impl FromStr for DateTimeField {
189    type Err = String;
190
191    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
192        match s.to_uppercase().as_ref() {
193            "MILLENNIUM" | "MILLENNIA" | "MIL" | "MILS" => Ok(Self::Millennium),
194            "CENTURY" | "CENTURIES" | "CENT" | "C" => Ok(Self::Century),
195            "DECADE" | "DECADES" | "DEC" | "DECS" => Ok(Self::Decade),
196            "YEAR" | "YEARS" | "YR" | "YRS" | "Y" => Ok(Self::Year),
197            "MONTH" | "MONTHS" | "MON" | "MONS" => Ok(Self::Month),
198            "DAY" | "DAYS" | "D" => Ok(Self::Day),
199            "HOUR" | "HOURS" | "HR" | "HRS" | "H" => Ok(Self::Hour),
200            "MINUTE" | "MINUTES" | "MIN" | "MINS" | "M" => Ok(Self::Minute),
201            "SECOND" | "SECONDS" | "SEC" | "SECS" | "S" => Ok(Self::Second),
202            "MILLISECOND" | "MILLISECONDS" | "MILLISECON" | "MILLISECONS" | "MSECOND"
203            | "MSECONDS" | "MSEC" | "MSECS" | "MS" => Ok(Self::Milliseconds),
204            "MICROSECOND" | "MICROSECONDS" | "MICROSECON" | "MICROSECONS" | "USECOND"
205            | "USECONDS" | "USEC" | "USECS" | "US" => Ok(Self::Microseconds),
206            _ => Err(format!("invalid DateTimeField: {}", s)),
207        }
208    }
209}
210
211/// An intermediate value for Intervals, which tracks all data from
212/// the user, as well as the computed ParsedDateTime.
213#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
214pub struct IntervalValue {
215    /// The raw `[value]` that was present in `INTERVAL '[value]'`
216    pub value: String,
217    /// The most significant DateTimeField to propagate to Interval in
218    /// compute_interval.
219    pub precision_high: DateTimeField,
220    /// The least significant DateTimeField to propagate to Interval in
221    /// compute_interval.
222    /// precision_low is also used to provide a TimeUnit if the final
223    /// part of `value` is ambiguous, e.g. INTERVAL '1-2 3' DAY uses
224    /// 'day' as the TimeUnit for 3.
225    pub precision_low: DateTimeField,
226    /// Maximum nanosecond precision can be specified in SQL source as
227    /// `INTERVAL '__' SECOND(_)`.
228    pub fsec_max_precision: Option<u64>,
229}
230
231impl Default for IntervalValue {
232    fn default() -> Self {
233        Self {
234            value: String::default(),
235            precision_high: DateTimeField::Year,
236            precision_low: DateTimeField::Second,
237            fsec_max_precision: None,
238        }
239    }
240}
241
242#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
243pub struct Version(pub(crate) u64);
244
245impl Version {
246    pub fn new(val: u64) -> Self {
247        Version(val)
248    }
249
250    pub fn into_inner(self) -> u64 {
251        self.0
252    }
253}
254
255impl AstDisplay for Version {
256    fn fmt<W>(&self, f: &mut AstFormatter<W>)
257    where
258        W: fmt::Write,
259    {
260        f.write_node(&self.0);
261    }
262}
263impl_display!(Version);