Skip to main content

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(
42    Debug,
43    Clone,
44    PartialEq,
45    Eq,
46    Hash,
47    PartialOrd,
48    Ord,
49    Serialize,
50    Deserialize
51)]
52pub enum Value {
53    /// Numeric value.
54    Number(String),
55    /// String value.
56    String(String),
57    /// Hex string value.
58    HexString(String),
59    /// Boolean value.
60    Boolean(bool),
61    /// INTERVAL literals, roughly in the following format:
62    ///
63    /// ```text
64    /// INTERVAL '<value>' <leading_field> [ TO <last_field>
65    ///     [ (<fractional_seconds_precision>) ] ]
66    /// ```
67    /// e.g. `INTERVAL '123:45.678' MINUTE TO SECOND(2)`.
68    Interval(IntervalValue),
69    /// `NULL` value.
70    Null,
71}
72
73impl AstDisplay for Value {
74    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
75        if f.redacted() {
76            // When adding branches to this match statement, think about whether it is OK for us to collect
77            // the value as part of our telemetry. Check the data management policy to be sure!
78            match self {
79                Value::Number(_) | Value::String(_) | Value::HexString(_) => {
80                    f.write_str("'<REDACTED>'");
81                    return;
82                }
83                Value::Interval(_) => {
84                    f.write_str("INTERVAL '<REDACTED>'");
85                    return;
86                }
87                Value::Boolean(_) | Value::Null => {
88                    // These are fine to log, so just fall through.
89                }
90            }
91        }
92        match self {
93            Value::Number(v) => f.write_str(v),
94            Value::String(v) => {
95                f.write_str("'");
96                f.write_node(&display::escape_single_quote_string(v));
97                f.write_str("'");
98            }
99            Value::HexString(v) => {
100                f.write_str("X'");
101                f.write_str(v);
102                f.write_str("'");
103            }
104            Value::Boolean(v) => f.write_str(v),
105            Value::Interval(interval_value) => {
106                f.write_str("INTERVAL '");
107                f.write_node(interval_value);
108            }
109            Value::Null => f.write_str("NULL"),
110        }
111    }
112}
113impl_display!(Value);
114
115impl AstDisplay for IntervalValue {
116    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
117        if f.redacted() {
118            f.write_str("<REDACTED>'");
119        } else {
120            let IntervalValue {
121                value,
122                precision_high,
123                precision_low,
124                fsec_max_precision,
125            } = self;
126            f.write_node(&display::escape_single_quote_string(value));
127            f.write_str("'");
128            match (precision_high, precision_low, fsec_max_precision) {
129                (DateTimeField::Year, DateTimeField::Second, None) => {}
130                (DateTimeField::Year, DateTimeField::Second, Some(ns)) => {
131                    f.write_str(" SECOND(");
132                    f.write_str(ns);
133                    f.write_str(")");
134                }
135                (DateTimeField::Year, low, None) => {
136                    f.write_str(" ");
137                    f.write_str(low);
138                }
139                (high, low, None) => {
140                    f.write_str(" ");
141                    f.write_str(high);
142                    f.write_str(" TO ");
143                    f.write_str(low);
144                }
145                (high, low, Some(ns)) => {
146                    f.write_str(" ");
147                    f.write_str(high);
148                    f.write_str(" TO ");
149                    f.write_str(low);
150                    f.write_str("(");
151                    f.write_str(ns);
152                    f.write_str(")");
153                }
154            }
155        }
156    }
157}
158
159impl From<Ident> for Value {
160    fn from(ident: Ident) -> Self {
161        Self::String(ident.0)
162    }
163}
164
165#[derive(
166    Debug,
167    Clone,
168    Copy,
169    PartialOrd,
170    Ord,
171    PartialEq,
172    Eq,
173    Hash,
174    Serialize,
175    Deserialize
176)]
177pub enum DateTimeField {
178    Millennium,
179    Century,
180    Decade,
181    Year,
182    Month,
183    Day,
184    Hour,
185    Minute,
186    Second,
187    Milliseconds,
188    Microseconds,
189}
190
191impl fmt::Display for DateTimeField {
192    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
193        f.write_str(match self {
194            DateTimeField::Millennium => "MILLENNIUM",
195            DateTimeField::Century => "CENTURY",
196            DateTimeField::Decade => "DECADE",
197            DateTimeField::Year => "YEAR",
198            DateTimeField::Month => "MONTH",
199            DateTimeField::Day => "DAY",
200            DateTimeField::Hour => "HOUR",
201            DateTimeField::Minute => "MINUTE",
202            DateTimeField::Second => "SECOND",
203            DateTimeField::Milliseconds => "MILLISECONDS",
204            DateTimeField::Microseconds => "MICROSECONDS",
205        })
206    }
207}
208
209impl FromStr for DateTimeField {
210    type Err = String;
211
212    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
213        match s.to_uppercase().as_ref() {
214            "MILLENNIUM" | "MILLENNIA" | "MIL" | "MILS" => Ok(Self::Millennium),
215            "CENTURY" | "CENTURIES" | "CENT" | "C" => Ok(Self::Century),
216            "DECADE" | "DECADES" | "DEC" | "DECS" => Ok(Self::Decade),
217            "YEAR" | "YEARS" | "YR" | "YRS" | "Y" => Ok(Self::Year),
218            "MONTH" | "MONTHS" | "MON" | "MONS" => Ok(Self::Month),
219            "DAY" | "DAYS" | "D" => Ok(Self::Day),
220            "HOUR" | "HOURS" | "HR" | "HRS" | "H" => Ok(Self::Hour),
221            "MINUTE" | "MINUTES" | "MIN" | "MINS" | "M" => Ok(Self::Minute),
222            "SECOND" | "SECONDS" | "SEC" | "SECS" | "S" => Ok(Self::Second),
223            "MILLISECOND" | "MILLISECONDS" | "MILLISECON" | "MILLISECONS" | "MSECOND"
224            | "MSECONDS" | "MSEC" | "MSECS" | "MS" => Ok(Self::Milliseconds),
225            "MICROSECOND" | "MICROSECONDS" | "MICROSECON" | "MICROSECONS" | "USECOND"
226            | "USECONDS" | "USEC" | "USECS" | "US" => Ok(Self::Microseconds),
227            _ => Err(format!("invalid DateTimeField: {}", s)),
228        }
229    }
230}
231
232/// An intermediate value for Intervals, which tracks all data from
233/// the user, as well as the computed ParsedDateTime.
234#[derive(
235    Debug,
236    Clone,
237    PartialEq,
238    Eq,
239    Hash,
240    PartialOrd,
241    Ord,
242    Serialize,
243    Deserialize
244)]
245pub struct IntervalValue {
246    /// The raw `[value]` that was present in `INTERVAL '[value]'`
247    pub value: String,
248    /// The most significant DateTimeField to propagate to Interval in
249    /// compute_interval.
250    pub precision_high: DateTimeField,
251    /// The least significant DateTimeField to propagate to Interval in
252    /// compute_interval.
253    /// precision_low is also used to provide a TimeUnit if the final
254    /// part of `value` is ambiguous, e.g. INTERVAL '1-2 3' DAY uses
255    /// 'day' as the TimeUnit for 3.
256    pub precision_low: DateTimeField,
257    /// Maximum nanosecond precision can be specified in SQL source as
258    /// `INTERVAL '__' SECOND(_)`.
259    pub fsec_max_precision: Option<u64>,
260}
261
262impl Default for IntervalValue {
263    fn default() -> Self {
264        Self {
265            value: String::default(),
266            precision_high: DateTimeField::Year,
267            precision_low: DateTimeField::Second,
268            fsec_max_precision: None,
269        }
270    }
271}
272
273#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
274pub struct Version(pub(crate) u64);
275
276impl Version {
277    pub fn new(val: u64) -> Self {
278        Version(val)
279    }
280
281    pub fn into_inner(self) -> u64 {
282        self.0
283    }
284}
285
286impl AstDisplay for Version {
287    fn fmt<W>(&self, f: &mut AstFormatter<W>)
288    where
289        W: fmt::Write,
290    {
291        f.write_node(&self.0);
292    }
293}
294impl_display!(Version);