1#[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#[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 #[cfg(not(feature = "bigdecimal"))]
33 Number(String, bool),
34 #[cfg(feature = "bigdecimal")]
35 Number(BigDecimal, bool),
39 SingleQuotedString(String),
41 DollarQuotedString(DollarQuotedString),
43 EscapedStringLiteral(String),
47 SingleQuotedByteStringLiteral(String),
49 DoubleQuotedByteStringLiteral(String),
51 RawStringLiteral(String),
54 NationalStringLiteral(String),
56 HexStringLiteral(String),
58
59 DoubleQuotedString(String),
60 Boolean(bool),
62 Null,
64 Placeholder(String),
66 UnQuotedString(String),
68}
69
70impl fmt::Display for Value {
71 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72 match self {
73 Value::Number(v, l) => write!(f, "{}{long}", v, long = if *l { "L" } else { "" }),
74 Value::DoubleQuotedString(v) => write!(f, "\"{}\"", escape_double_quote_string(v)),
75 Value::SingleQuotedString(v) => write!(f, "'{}'", escape_single_quote_string(v)),
76 Value::DollarQuotedString(v) => write!(f, "{v}"),
77 Value::EscapedStringLiteral(v) => write!(f, "E'{}'", escape_escaped_string(v)),
78 Value::NationalStringLiteral(v) => write!(f, "N'{v}'"),
79 Value::HexStringLiteral(v) => write!(f, "X'{v}'"),
80 Value::Boolean(v) => write!(f, "{v}"),
81 Value::SingleQuotedByteStringLiteral(v) => write!(f, "B'{v}'"),
82 Value::DoubleQuotedByteStringLiteral(v) => write!(f, "B\"{v}\""),
83 Value::RawStringLiteral(v) => write!(f, "R'{v}'"),
84 Value::Null => write!(f, "NULL"),
85 Value::Placeholder(v) => write!(f, "{v}"),
86 Value::UnQuotedString(v) => write!(f, "{v}"),
87 }
88 }
89}
90
91#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
92#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
93#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
94pub struct DollarQuotedString {
95 pub value: String,
96 pub tag: Option<String>,
97}
98
99impl fmt::Display for DollarQuotedString {
100 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101 match &self.tag {
102 Some(tag) => {
103 write!(f, "${}${}${}$", tag, self.value, tag)
104 }
105 None => {
106 write!(f, "$${}$$", self.value)
107 }
108 }
109 }
110}
111
112#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
113#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
114#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
115pub enum DateTimeField {
116 Year,
117 Month,
118 Week,
119 Day,
120 DayOfWeek,
121 DayOfYear,
122 Date,
123 Hour,
124 Minute,
125 Second,
126 Century,
127 Decade,
128 Dow,
129 Doy,
130 Epoch,
131 Isodow,
132 IsoWeek,
133 Isoyear,
134 Julian,
135 Microsecond,
136 Microseconds,
137 Millenium,
138 Millennium,
139 Millisecond,
140 Milliseconds,
141 Nanosecond,
142 Nanoseconds,
143 Quarter,
144 Time,
145 Timezone,
146 TimezoneAbbr,
147 TimezoneHour,
148 TimezoneMinute,
149 TimezoneRegion,
150 NoDateTime,
151}
152
153impl fmt::Display for DateTimeField {
154 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
155 f.write_str(match self {
156 DateTimeField::Year => "YEAR",
157 DateTimeField::Month => "MONTH",
158 DateTimeField::Week => "WEEK",
159 DateTimeField::Day => "DAY",
160 DateTimeField::DayOfWeek => "DAYOFWEEK",
161 DateTimeField::DayOfYear => "DAYOFYEAR",
162 DateTimeField::Date => "DATE",
163 DateTimeField::Hour => "HOUR",
164 DateTimeField::Minute => "MINUTE",
165 DateTimeField::Second => "SECOND",
166 DateTimeField::Century => "CENTURY",
167 DateTimeField::Decade => "DECADE",
168 DateTimeField::Dow => "DOW",
169 DateTimeField::Doy => "DOY",
170 DateTimeField::Epoch => "EPOCH",
171 DateTimeField::Isodow => "ISODOW",
172 DateTimeField::Isoyear => "ISOYEAR",
173 DateTimeField::IsoWeek => "ISOWEEK",
174 DateTimeField::Julian => "JULIAN",
175 DateTimeField::Microsecond => "MICROSECOND",
176 DateTimeField::Microseconds => "MICROSECONDS",
177 DateTimeField::Millenium => "MILLENIUM",
178 DateTimeField::Millennium => "MILLENNIUM",
179 DateTimeField::Millisecond => "MILLISECOND",
180 DateTimeField::Milliseconds => "MILLISECONDS",
181 DateTimeField::Nanosecond => "NANOSECOND",
182 DateTimeField::Nanoseconds => "NANOSECONDS",
183 DateTimeField::Quarter => "QUARTER",
184 DateTimeField::Time => "TIME",
185 DateTimeField::Timezone => "TIMEZONE",
186 DateTimeField::TimezoneAbbr => "TIMEZONE_ABBR",
187 DateTimeField::TimezoneHour => "TIMEZONE_HOUR",
188 DateTimeField::TimezoneMinute => "TIMEZONE_MINUTE",
189 DateTimeField::TimezoneRegion => "TIMEZONE_REGION",
190 DateTimeField::NoDateTime => "NODATETIME",
191 })
192 }
193}
194
195pub struct EscapeQuotedString<'a> {
196 string: &'a str,
197 quote: char,
198}
199
200impl<'a> fmt::Display for EscapeQuotedString<'a> {
201 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
202 let quote = self.quote;
221 let mut previous_char = char::default();
222 let mut peekable_chars = self.string.chars().peekable();
223 while let Some(&ch) = peekable_chars.peek() {
224 match ch {
225 char if char == quote => {
226 if previous_char == '\\' {
227 write!(f, "{char}")?;
228 peekable_chars.next();
229 continue;
230 }
231 peekable_chars.next();
232 if peekable_chars.peek().map(|c| *c == quote).unwrap_or(false) {
233 write!(f, "{char}{char}")?;
234 peekable_chars.next();
235 } else {
236 write!(f, "{char}{char}")?;
237 }
238 }
239 _ => {
240 write!(f, "{ch}")?;
241 peekable_chars.next();
242 }
243 }
244 previous_char = ch;
245 }
246 Ok(())
247 }
248}
249
250pub fn escape_quoted_string(string: &str, quote: char) -> EscapeQuotedString<'_> {
251 EscapeQuotedString { string, quote }
252}
253
254pub fn escape_single_quote_string(s: &str) -> EscapeQuotedString<'_> {
255 escape_quoted_string(s, '\'')
256}
257
258pub fn escape_double_quote_string(s: &str) -> EscapeQuotedString<'_> {
259 escape_quoted_string(s, '\"')
260}
261
262pub struct EscapeEscapedStringLiteral<'a>(&'a str);
263
264impl<'a> fmt::Display for EscapeEscapedStringLiteral<'a> {
265 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
266 for c in self.0.chars() {
267 match c {
268 '\'' => {
269 write!(f, r#"\'"#)?;
270 }
271 '\\' => {
272 write!(f, r#"\\"#)?;
273 }
274 '\n' => {
275 write!(f, r#"\n"#)?;
276 }
277 '\t' => {
278 write!(f, r#"\t"#)?;
279 }
280 '\r' => {
281 write!(f, r#"\r"#)?;
282 }
283 _ => {
284 write!(f, "{c}")?;
285 }
286 }
287 }
288 Ok(())
289 }
290}
291
292pub fn escape_escaped_string(s: &str) -> EscapeEscapedStringLiteral<'_> {
293 EscapeEscapedStringLiteral(s)
294}
295
296#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
297#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
298#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
299pub enum TrimWhereField {
300 Both,
301 Leading,
302 Trailing,
303}
304
305impl fmt::Display for TrimWhereField {
306 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
307 use TrimWhereField::*;
308 f.write_str(match self {
309 Both => "BOTH",
310 Leading => "LEADING",
311 Trailing => "TRAILING",
312 })
313 }
314}