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 TimezoneHour,
147 TimezoneMinute,
148 NoDateTime,
149}
150
151impl fmt::Display for DateTimeField {
152 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
153 f.write_str(match self {
154 DateTimeField::Year => "YEAR",
155 DateTimeField::Month => "MONTH",
156 DateTimeField::Week => "WEEK",
157 DateTimeField::Day => "DAY",
158 DateTimeField::DayOfWeek => "DAYOFWEEK",
159 DateTimeField::DayOfYear => "DAYOFYEAR",
160 DateTimeField::Date => "DATE",
161 DateTimeField::Hour => "HOUR",
162 DateTimeField::Minute => "MINUTE",
163 DateTimeField::Second => "SECOND",
164 DateTimeField::Century => "CENTURY",
165 DateTimeField::Decade => "DECADE",
166 DateTimeField::Dow => "DOW",
167 DateTimeField::Doy => "DOY",
168 DateTimeField::Epoch => "EPOCH",
169 DateTimeField::Isodow => "ISODOW",
170 DateTimeField::Isoyear => "ISOYEAR",
171 DateTimeField::IsoWeek => "ISOWEEK",
172 DateTimeField::Julian => "JULIAN",
173 DateTimeField::Microsecond => "MICROSECOND",
174 DateTimeField::Microseconds => "MICROSECONDS",
175 DateTimeField::Millenium => "MILLENIUM",
176 DateTimeField::Millennium => "MILLENNIUM",
177 DateTimeField::Millisecond => "MILLISECOND",
178 DateTimeField::Milliseconds => "MILLISECONDS",
179 DateTimeField::Nanosecond => "NANOSECOND",
180 DateTimeField::Nanoseconds => "NANOSECONDS",
181 DateTimeField::Quarter => "QUARTER",
182 DateTimeField::Time => "TIME",
183 DateTimeField::Timezone => "TIMEZONE",
184 DateTimeField::TimezoneHour => "TIMEZONE_HOUR",
185 DateTimeField::TimezoneMinute => "TIMEZONE_MINUTE",
186 DateTimeField::NoDateTime => "NODATETIME",
187 })
188 }
189}
190
191pub struct EscapeQuotedString<'a> {
192 string: &'a str,
193 quote: char,
194}
195
196impl<'a> fmt::Display for EscapeQuotedString<'a> {
197 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
198 let quote = self.quote;
217 let mut previous_char = char::default();
218 let mut peekable_chars = self.string.chars().peekable();
219 while let Some(&ch) = peekable_chars.peek() {
220 match ch {
221 char if char == quote => {
222 if previous_char == '\\' {
223 write!(f, "{char}")?;
224 peekable_chars.next();
225 continue;
226 }
227 peekable_chars.next();
228 if peekable_chars.peek().map(|c| *c == quote).unwrap_or(false) {
229 write!(f, "{char}{char}")?;
230 peekable_chars.next();
231 } else {
232 write!(f, "{char}{char}")?;
233 }
234 }
235 _ => {
236 write!(f, "{ch}")?;
237 peekable_chars.next();
238 }
239 }
240 previous_char = ch;
241 }
242 Ok(())
243 }
244}
245
246pub fn escape_quoted_string(string: &str, quote: char) -> EscapeQuotedString<'_> {
247 EscapeQuotedString { string, quote }
248}
249
250pub fn escape_single_quote_string(s: &str) -> EscapeQuotedString<'_> {
251 escape_quoted_string(s, '\'')
252}
253
254pub fn escape_double_quote_string(s: &str) -> EscapeQuotedString<'_> {
255 escape_quoted_string(s, '\"')
256}
257
258pub struct EscapeEscapedStringLiteral<'a>(&'a str);
259
260impl<'a> fmt::Display for EscapeEscapedStringLiteral<'a> {
261 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
262 for c in self.0.chars() {
263 match c {
264 '\'' => {
265 write!(f, r#"\'"#)?;
266 }
267 '\\' => {
268 write!(f, r#"\\"#)?;
269 }
270 '\n' => {
271 write!(f, r#"\n"#)?;
272 }
273 '\t' => {
274 write!(f, r#"\t"#)?;
275 }
276 '\r' => {
277 write!(f, r#"\r"#)?;
278 }
279 _ => {
280 write!(f, "{c}")?;
281 }
282 }
283 }
284 Ok(())
285 }
286}
287
288pub fn escape_escaped_string(s: &str) -> EscapeEscapedStringLiteral<'_> {
289 EscapeEscapedStringLiteral(s)
290}
291
292#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
293#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
294#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
295pub enum TrimWhereField {
296 Both,
297 Leading,
298 Trailing,
299}
300
301impl fmt::Display for TrimWhereField {
302 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
303 use TrimWhereField::*;
304 f.write_str(match self {
305 Both => "BOTH",
306 Leading => "LEADING",
307 Trailing => "TRAILING",
308 })
309 }
310}