risingwave_sqlparser/ast/
value.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5//     http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13use std::fmt;
14
15use super::ObjectName;
16
17/// Primitive SQL values such as number and string
18#[derive(Debug, Clone, PartialEq, Eq, Hash)]
19pub enum Value {
20    /// Numeric literal
21    Number(String),
22    /// 'string value'
23    SingleQuotedString(String),
24    // $<tag_name>$string value$<tag_name>$ (postgres syntax)
25    DollarQuotedString(DollarQuotedString),
26    /// String Constants With C-Style Escapes
27    CstyleEscapedString(CstyleEscapedString),
28    /// N'string value'
29    NationalStringLiteral(String),
30    /// X'hex value'
31    HexStringLiteral(String),
32    DoubleQuotedString(String),
33    /// Boolean value true or false
34    Boolean(bool),
35    /// INTERVAL literals, roughly in the following format:
36    /// `INTERVAL '<value>' [ <leading_field> [ (<leading_precision>) ] ]
37    /// [ TO <last_field> [ (<fractional_seconds_precision>) ] ]`,
38    /// e.g. `INTERVAL '123:45.67' MINUTE(3) TO SECOND(2)`.
39    ///
40    /// The parser does not validate the `<value>`, nor does it ensure
41    /// that the `<leading_field>` units >= the units in `<last_field>`,
42    /// so the user will have to reject intervals like `HOUR TO YEAR`.
43    Interval {
44        value: String,
45        leading_field: Option<DateTimeField>,
46        leading_precision: Option<u64>,
47        last_field: Option<DateTimeField>,
48        /// The seconds precision can be specified in SQL source as
49        /// `INTERVAL '__' SECOND(_, x)` (in which case the `leading_field`
50        /// will be `Second` and the `last_field` will be `None`),
51        /// or as `__ TO SECOND(x)`.
52        fractional_seconds_precision: Option<u64>,
53    },
54    /// `NULL` value
55    Null,
56}
57
58impl fmt::Display for Value {
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        match self {
61            Value::Number(v) => write!(f, "{}", v),
62            Value::DoubleQuotedString(v) => write!(f, "\"{}\"", v),
63            Value::SingleQuotedString(v) => write!(f, "'{}'", escape_single_quote_string(v)),
64            Value::DollarQuotedString(v) => write!(f, "{}", v),
65            Value::NationalStringLiteral(v) => write!(f, "N'{}'", v),
66            Value::HexStringLiteral(v) => write!(f, "X'{}'", v),
67            Value::CstyleEscapedString(v) => write!(f, "E'{}'", v),
68            Value::Boolean(v) => write!(f, "{}", v),
69            Value::Interval {
70                value,
71                leading_field: Some(DateTimeField::Second),
72                leading_precision: Some(leading_precision),
73                last_field,
74                fractional_seconds_precision: Some(fractional_seconds_precision),
75            } => {
76                // When the leading field is SECOND, the parser guarantees that
77                // the last field is None.
78                assert!(last_field.is_none());
79                write!(
80                    f,
81                    "INTERVAL '{}' SECOND ({}, {})",
82                    escape_single_quote_string(value),
83                    leading_precision,
84                    fractional_seconds_precision
85                )
86            }
87            Value::Interval {
88                value,
89                leading_field,
90                leading_precision,
91                last_field,
92                fractional_seconds_precision,
93            } => {
94                write!(f, "INTERVAL '{}'", escape_single_quote_string(value))?;
95                if let Some(leading_field) = leading_field {
96                    write!(f, " {}", leading_field)?;
97                }
98                if let Some(leading_precision) = leading_precision {
99                    write!(f, " ({})", leading_precision)?;
100                }
101                if let Some(last_field) = last_field {
102                    write!(f, " TO {}", last_field)?;
103                }
104                if let Some(fractional_seconds_precision) = fractional_seconds_precision {
105                    write!(f, " ({})", fractional_seconds_precision)?;
106                }
107                Ok(())
108            }
109            Value::Null => write!(f, "NULL"),
110        }
111    }
112}
113
114#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
115pub struct DollarQuotedString {
116    pub value: String,
117    pub tag: Option<String>,
118}
119
120impl fmt::Display for DollarQuotedString {
121    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122        match &self.tag {
123            Some(tag) => {
124                write!(f, "${}${}${}$", tag, self.value, tag)
125            }
126            None => {
127                write!(f, "$${}$$", self.value)
128            }
129        }
130    }
131}
132
133#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
134pub struct CstyleEscapedString {
135    /// The unescaped string.
136    pub value: String,
137    /// The raw string used for simplifying `fmt::Display` (unparsing) implementation.
138    pub raw: String,
139}
140
141impl fmt::Display for CstyleEscapedString {
142    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143        write!(f, "{}", self.raw)
144    }
145}
146
147#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
148pub enum DateTimeField {
149    Year,
150    Month,
151    Day,
152    Hour,
153    Minute,
154    Second,
155}
156
157impl fmt::Display for DateTimeField {
158    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159        f.write_str(match self {
160            DateTimeField::Year => "YEAR",
161            DateTimeField::Month => "MONTH",
162            DateTimeField::Day => "DAY",
163            DateTimeField::Hour => "HOUR",
164            DateTimeField::Minute => "MINUTE",
165            DateTimeField::Second => "SECOND",
166        })
167    }
168}
169
170pub struct EscapeSingleQuoteString<'a>(&'a str);
171
172impl fmt::Display for EscapeSingleQuoteString<'_> {
173    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174        for c in self.0.chars() {
175            if c == '\'' {
176                write!(f, "\'\'")?;
177            } else {
178                write!(f, "{}", c)?;
179            }
180        }
181        Ok(())
182    }
183}
184
185pub fn escape_single_quote_string(s: &str) -> EscapeSingleQuoteString<'_> {
186    EscapeSingleQuoteString(s)
187}
188
189#[derive(Debug, Clone, PartialEq, Eq, Hash)]
190pub enum TrimWhereField {
191    Both,
192    Leading,
193    Trailing,
194}
195
196impl fmt::Display for TrimWhereField {
197    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198        use TrimWhereField::*;
199        f.write_str(match self {
200            Both => "BOTH",
201            Leading => "LEADING",
202            Trailing => "TRAILING",
203        })
204    }
205}
206
207#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
208pub enum JsonPredicateType {
209    #[default]
210    Value,
211    Array,
212    Object,
213    Scalar,
214}
215
216impl fmt::Display for JsonPredicateType {
217    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218        use JsonPredicateType::*;
219        f.write_str(match self {
220            Value => "",
221            Array => " ARRAY",
222            Object => " OBJECT",
223            Scalar => " SCALAR",
224        })
225    }
226}
227#[derive(Debug, Clone, PartialEq, Eq, Hash)]
228pub struct SecretRefValue {
229    pub secret_name: ObjectName,
230    pub ref_as: SecretRefAsType,
231}
232
233impl fmt::Display for SecretRefValue {
234    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
235        match self.ref_as {
236            SecretRefAsType::Text => write!(f, "{}", self.secret_name),
237            SecretRefAsType::File => write!(f, "{} AS FILE", self.secret_name),
238        }
239    }
240}
241
242#[derive(Debug, Clone, PartialEq, Eq, Hash)]
243pub enum SecretRefAsType {
244    Text,
245    File,
246}
247
248#[derive(Debug, Clone, PartialEq, Eq, Hash)]
249pub struct ConnectionRefValue {
250    pub connection_name: ObjectName,
251}
252
253impl fmt::Display for ConnectionRefValue {
254    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
255        write!(f, "{}", self.connection_name)
256    }
257}