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
13#[cfg(not(feature = "std"))]
14use alloc::string::String;
15use core::fmt;
16
17#[cfg(feature = "bigdecimal")]
18use bigdecimal::BigDecimal;
19
20#[cfg(feature = "serde")]
21use serde::{Deserialize, Serialize};
22
23#[cfg(feature = "visitor")]
24use sqlparser_derive::{Visit, VisitMut};
25
26/// Primitive SQL values such as number and string
27#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
28#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
29#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
30pub enum Value {
31    /// Numeric literal
32    #[cfg(not(feature = "bigdecimal"))]
33    Number(String, bool),
34    #[cfg(feature = "bigdecimal")]
35    Number(BigDecimal, bool),
36    /// 'string value'
37    SingleQuotedString(String),
38    // $<tag_name>$string value$<tag_name>$ (postgres syntax)
39    DollarQuotedString(DollarQuotedString),
40    /// e'string value' (postgres extension)
41    /// See [Postgres docs](https://www.postgresql.org/docs/8.3/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS)
42    /// for more details.
43    EscapedStringLiteral(String),
44    /// B'string value'
45    SingleQuotedByteStringLiteral(String),
46    /// B"string value"
47    DoubleQuotedByteStringLiteral(String),
48    /// R'string value' or r'string value' or r"string value"
49    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#quoted_literals>
50    RawStringLiteral(String),
51    /// N'string value'
52    NationalStringLiteral(String),
53    /// X'hex value'
54    HexStringLiteral(String),
55
56    DoubleQuotedString(String),
57    /// Boolean value true or false
58    Boolean(bool),
59    /// `NULL` value
60    Null,
61    /// `?` or `$` Prepared statement arg placeholder
62    Placeholder(String),
63    /// Add support of snowflake field:key - key should be a value
64    UnQuotedString(String),
65}
66
67impl fmt::Display for Value {
68    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69        match self {
70            Value::Number(v, l) => write!(f, "{}{long}", v, long = if *l { "L" } else { "" }),
71            Value::DoubleQuotedString(v) => write!(f, "\"{v}\""),
72            Value::SingleQuotedString(v) => write!(f, "'{}'", escape_single_quote_string(v)),
73            Value::DollarQuotedString(v) => write!(f, "{v}"),
74            Value::EscapedStringLiteral(v) => write!(f, "E'{}'", escape_escaped_string(v)),
75            Value::NationalStringLiteral(v) => write!(f, "N'{v}'"),
76            Value::HexStringLiteral(v) => write!(f, "X'{v}'"),
77            Value::Boolean(v) => write!(f, "{v}"),
78            Value::SingleQuotedByteStringLiteral(v) => write!(f, "B'{v}'"),
79            Value::DoubleQuotedByteStringLiteral(v) => write!(f, "B\"{v}\""),
80            Value::RawStringLiteral(v) => write!(f, "R'{v}'"),
81            Value::Null => write!(f, "NULL"),
82            Value::Placeholder(v) => write!(f, "{v}"),
83            Value::UnQuotedString(v) => write!(f, "{v}"),
84        }
85    }
86}
87
88#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
89#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
90#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
91pub struct DollarQuotedString {
92    pub value: String,
93    pub tag: Option<String>,
94}
95
96impl fmt::Display for DollarQuotedString {
97    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
98        match &self.tag {
99            Some(tag) => {
100                write!(f, "${}${}${}$", tag, self.value, tag)
101            }
102            None => {
103                write!(f, "$${}$$", self.value)
104            }
105        }
106    }
107}
108
109#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
110#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
111#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
112pub enum DateTimeField {
113    Year,
114    Month,
115    Week,
116    Day,
117    Date,
118    Hour,
119    Minute,
120    Second,
121    Century,
122    Decade,
123    Dow,
124    Doy,
125    Epoch,
126    Isodow,
127    Isoyear,
128    Julian,
129    Microsecond,
130    Microseconds,
131    Millenium,
132    Millennium,
133    Millisecond,
134    Milliseconds,
135    Nanosecond,
136    Nanoseconds,
137    Quarter,
138    Timezone,
139    TimezoneHour,
140    TimezoneMinute,
141    NoDateTime,
142}
143
144impl fmt::Display for DateTimeField {
145    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146        f.write_str(match self {
147            DateTimeField::Year => "YEAR",
148            DateTimeField::Month => "MONTH",
149            DateTimeField::Week => "WEEK",
150            DateTimeField::Day => "DAY",
151            DateTimeField::Date => "DATE",
152            DateTimeField::Hour => "HOUR",
153            DateTimeField::Minute => "MINUTE",
154            DateTimeField::Second => "SECOND",
155            DateTimeField::Century => "CENTURY",
156            DateTimeField::Decade => "DECADE",
157            DateTimeField::Dow => "DOW",
158            DateTimeField::Doy => "DOY",
159            DateTimeField::Epoch => "EPOCH",
160            DateTimeField::Isodow => "ISODOW",
161            DateTimeField::Isoyear => "ISOYEAR",
162            DateTimeField::Julian => "JULIAN",
163            DateTimeField::Microsecond => "MICROSECOND",
164            DateTimeField::Microseconds => "MICROSECONDS",
165            DateTimeField::Millenium => "MILLENIUM",
166            DateTimeField::Millennium => "MILLENNIUM",
167            DateTimeField::Millisecond => "MILLISECOND",
168            DateTimeField::Milliseconds => "MILLISECONDS",
169            DateTimeField::Nanosecond => "NANOSECOND",
170            DateTimeField::Nanoseconds => "NANOSECONDS",
171            DateTimeField::Quarter => "QUARTER",
172            DateTimeField::Timezone => "TIMEZONE",
173            DateTimeField::TimezoneHour => "TIMEZONE_HOUR",
174            DateTimeField::TimezoneMinute => "TIMEZONE_MINUTE",
175            DateTimeField::NoDateTime => "NODATETIME",
176        })
177    }
178}
179
180pub struct EscapeQuotedString<'a> {
181    string: &'a str,
182    quote: char,
183}
184
185impl<'a> fmt::Display for EscapeQuotedString<'a> {
186    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
187        for c in self.string.chars() {
188            if c == self.quote {
189                write!(f, "{q}{q}", q = self.quote)?;
190            } else {
191                write!(f, "{c}")?;
192            }
193        }
194        Ok(())
195    }
196}
197
198pub fn escape_quoted_string(string: &str, quote: char) -> EscapeQuotedString<'_> {
199    EscapeQuotedString { string, quote }
200}
201
202pub fn escape_single_quote_string(s: &str) -> EscapeQuotedString<'_> {
203    escape_quoted_string(s, '\'')
204}
205
206pub struct EscapeEscapedStringLiteral<'a>(&'a str);
207
208impl<'a> fmt::Display for EscapeEscapedStringLiteral<'a> {
209    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
210        for c in self.0.chars() {
211            match c {
212                '\'' => {
213                    write!(f, r#"\'"#)?;
214                }
215                '\\' => {
216                    write!(f, r#"\\"#)?;
217                }
218                '\n' => {
219                    write!(f, r#"\n"#)?;
220                }
221                '\t' => {
222                    write!(f, r#"\t"#)?;
223                }
224                '\r' => {
225                    write!(f, r#"\r"#)?;
226                }
227                _ => {
228                    write!(f, "{c}")?;
229                }
230            }
231        }
232        Ok(())
233    }
234}
235
236pub fn escape_escaped_string(s: &str) -> EscapeEscapedStringLiteral<'_> {
237    EscapeEscapedStringLiteral(s)
238}
239
240#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
241#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
242#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
243pub enum TrimWhereField {
244    Both,
245    Leading,
246    Trailing,
247}
248
249impl fmt::Display for TrimWhereField {
250    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
251        use TrimWhereField::*;
252        f.write_str(match self {
253            Both => "BOTH",
254            Leading => "LEADING",
255            Trailing => "TRAILING",
256        })
257    }
258}