1#[cfg(not(feature = "std"))]
19use alloc::string::String;
20
21use core::fmt;
22
23#[cfg(feature = "bigdecimal")]
24use bigdecimal::BigDecimal;
25
26#[cfg(feature = "serde")]
27use serde::{Deserialize, Serialize};
28
29use crate::ast::Ident;
30#[cfg(feature = "visitor")]
31use sqltk_parser_derive::{Visit, VisitMut};
32
33#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
35#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
36#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
37pub enum Value {
38 #[cfg(not(feature = "bigdecimal"))]
40 Number(String, bool),
41 #[cfg(feature = "bigdecimal")]
42 Number(BigDecimal, bool),
46 SingleQuotedString(String),
48 DollarQuotedString(DollarQuotedString),
50 TripleSingleQuotedString(String),
53 TripleDoubleQuotedString(String),
56 EscapedStringLiteral(String),
60 UnicodeStringLiteral(String),
64 SingleQuotedByteStringLiteral(String),
66 DoubleQuotedByteStringLiteral(String),
68 TripleSingleQuotedByteStringLiteral(String),
71 TripleDoubleQuotedByteStringLiteral(String),
74 SingleQuotedRawStringLiteral(String),
77 DoubleQuotedRawStringLiteral(String),
80 TripleSingleQuotedRawStringLiteral(String),
83 TripleDoubleQuotedRawStringLiteral(String),
86 NationalStringLiteral(String),
88 HexStringLiteral(String),
90
91 DoubleQuotedString(String),
92 Boolean(bool),
94 Null,
96 Placeholder(String),
98}
99
100impl fmt::Display for Value {
101 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
102 match self {
103 Value::Number(v, l) => write!(f, "{}{long}", v, long = if *l { "L" } else { "" }),
104 Value::DoubleQuotedString(v) => write!(f, "\"{}\"", escape_double_quote_string(v)),
105 Value::SingleQuotedString(v) => write!(f, "'{}'", escape_single_quote_string(v)),
106 Value::TripleSingleQuotedString(v) => {
107 write!(f, "'''{v}'''")
108 }
109 Value::TripleDoubleQuotedString(v) => {
110 write!(f, r#""""{v}""""#)
111 }
112 Value::DollarQuotedString(v) => write!(f, "{v}"),
113 Value::EscapedStringLiteral(v) => write!(f, "E'{}'", escape_escaped_string(v)),
114 Value::UnicodeStringLiteral(v) => write!(f, "U&'{}'", escape_unicode_string(v)),
115 Value::NationalStringLiteral(v) => write!(f, "N'{v}'"),
116 Value::HexStringLiteral(v) => write!(f, "X'{v}'"),
117 Value::Boolean(v) => write!(f, "{v}"),
118 Value::SingleQuotedByteStringLiteral(v) => write!(f, "B'{v}'"),
119 Value::DoubleQuotedByteStringLiteral(v) => write!(f, "B\"{v}\""),
120 Value::TripleSingleQuotedByteStringLiteral(v) => write!(f, "B'''{v}'''"),
121 Value::TripleDoubleQuotedByteStringLiteral(v) => write!(f, r#"B"""{v}""""#),
122 Value::SingleQuotedRawStringLiteral(v) => write!(f, "R'{v}'"),
123 Value::DoubleQuotedRawStringLiteral(v) => write!(f, "R\"{v}\""),
124 Value::TripleSingleQuotedRawStringLiteral(v) => write!(f, "R'''{v}'''"),
125 Value::TripleDoubleQuotedRawStringLiteral(v) => write!(f, r#"R"""{v}""""#),
126 Value::Null => write!(f, "NULL"),
127 Value::Placeholder(v) => write!(f, "{v}"),
128 }
129 }
130}
131
132#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
133#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
134#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
135pub struct DollarQuotedString {
136 pub value: String,
137 pub tag: Option<String>,
138}
139
140impl fmt::Display for DollarQuotedString {
141 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
142 match &self.tag {
143 Some(tag) => {
144 write!(f, "${}${}${}$", tag, self.value, tag)
145 }
146 None => {
147 write!(f, "$${}$$", self.value)
148 }
149 }
150 }
151}
152
153#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
154#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
155#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
156pub enum DateTimeField {
157 Year,
158 Month,
159 Week(Option<Ident>),
167 Day,
168 DayOfWeek,
169 DayOfYear,
170 Date,
171 Datetime,
172 Hour,
173 Minute,
174 Second,
175 Century,
176 Decade,
177 Dow,
178 Doy,
179 Epoch,
180 Isodow,
181 IsoWeek,
182 Isoyear,
183 Julian,
184 Microsecond,
185 Microseconds,
186 Millenium,
187 Millennium,
188 Millisecond,
189 Milliseconds,
190 Nanosecond,
191 Nanoseconds,
192 Quarter,
193 Time,
194 Timezone,
195 TimezoneAbbr,
196 TimezoneHour,
197 TimezoneMinute,
198 TimezoneRegion,
199 NoDateTime,
200 Custom(Ident),
207}
208
209impl fmt::Display for DateTimeField {
210 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
211 match self {
212 DateTimeField::Year => write!(f, "YEAR"),
213 DateTimeField::Month => write!(f, "MONTH"),
214 DateTimeField::Week(week_day) => {
215 write!(f, "WEEK")?;
216 if let Some(week_day) = week_day {
217 write!(f, "({week_day})")?
218 }
219 Ok(())
220 }
221 DateTimeField::Day => write!(f, "DAY"),
222 DateTimeField::DayOfWeek => write!(f, "DAYOFWEEK"),
223 DateTimeField::DayOfYear => write!(f, "DAYOFYEAR"),
224 DateTimeField::Date => write!(f, "DATE"),
225 DateTimeField::Datetime => write!(f, "DATETIME"),
226 DateTimeField::Hour => write!(f, "HOUR"),
227 DateTimeField::Minute => write!(f, "MINUTE"),
228 DateTimeField::Second => write!(f, "SECOND"),
229 DateTimeField::Century => write!(f, "CENTURY"),
230 DateTimeField::Decade => write!(f, "DECADE"),
231 DateTimeField::Dow => write!(f, "DOW"),
232 DateTimeField::Doy => write!(f, "DOY"),
233 DateTimeField::Epoch => write!(f, "EPOCH"),
234 DateTimeField::Isodow => write!(f, "ISODOW"),
235 DateTimeField::Isoyear => write!(f, "ISOYEAR"),
236 DateTimeField::IsoWeek => write!(f, "ISOWEEK"),
237 DateTimeField::Julian => write!(f, "JULIAN"),
238 DateTimeField::Microsecond => write!(f, "MICROSECOND"),
239 DateTimeField::Microseconds => write!(f, "MICROSECONDS"),
240 DateTimeField::Millenium => write!(f, "MILLENIUM"),
241 DateTimeField::Millennium => write!(f, "MILLENNIUM"),
242 DateTimeField::Millisecond => write!(f, "MILLISECOND"),
243 DateTimeField::Milliseconds => write!(f, "MILLISECONDS"),
244 DateTimeField::Nanosecond => write!(f, "NANOSECOND"),
245 DateTimeField::Nanoseconds => write!(f, "NANOSECONDS"),
246 DateTimeField::Quarter => write!(f, "QUARTER"),
247 DateTimeField::Time => write!(f, "TIME"),
248 DateTimeField::Timezone => write!(f, "TIMEZONE"),
249 DateTimeField::TimezoneAbbr => write!(f, "TIMEZONE_ABBR"),
250 DateTimeField::TimezoneHour => write!(f, "TIMEZONE_HOUR"),
251 DateTimeField::TimezoneMinute => write!(f, "TIMEZONE_MINUTE"),
252 DateTimeField::TimezoneRegion => write!(f, "TIMEZONE_REGION"),
253 DateTimeField::NoDateTime => write!(f, "NODATETIME"),
254 DateTimeField::Custom(custom) => write!(f, "{custom}"),
255 }
256 }
257}
258
259pub struct EscapeQuotedString<'a> {
260 string: &'a str,
261 quote: char,
262}
263
264impl fmt::Display for EscapeQuotedString<'_> {
265 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
266 let quote = self.quote;
285 let mut previous_char = char::default();
286 let mut peekable_chars = self.string.chars().peekable();
287 while let Some(&ch) = peekable_chars.peek() {
288 match ch {
289 char if char == quote => {
290 if previous_char == '\\' {
291 write!(f, "{char}")?;
292 peekable_chars.next();
293 continue;
294 }
295 peekable_chars.next();
296 if peekable_chars.peek().map(|c| *c == quote).unwrap_or(false) {
297 write!(f, "{char}{char}")?;
298 peekable_chars.next();
299 } else {
300 write!(f, "{char}{char}")?;
301 }
302 }
303 _ => {
304 write!(f, "{ch}")?;
305 peekable_chars.next();
306 }
307 }
308 previous_char = ch;
309 }
310 Ok(())
311 }
312}
313
314pub fn escape_quoted_string(string: &str, quote: char) -> EscapeQuotedString<'_> {
315 EscapeQuotedString { string, quote }
316}
317
318pub fn escape_single_quote_string(s: &str) -> EscapeQuotedString<'_> {
319 escape_quoted_string(s, '\'')
320}
321
322pub fn escape_double_quote_string(s: &str) -> EscapeQuotedString<'_> {
323 escape_quoted_string(s, '\"')
324}
325
326pub struct EscapeEscapedStringLiteral<'a>(&'a str);
327
328impl fmt::Display for EscapeEscapedStringLiteral<'_> {
329 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
330 for c in self.0.chars() {
331 match c {
332 '\'' => {
333 write!(f, r#"\'"#)?;
334 }
335 '\\' => {
336 write!(f, r#"\\"#)?;
337 }
338 '\n' => {
339 write!(f, r#"\n"#)?;
340 }
341 '\t' => {
342 write!(f, r#"\t"#)?;
343 }
344 '\r' => {
345 write!(f, r#"\r"#)?;
346 }
347 _ => {
348 write!(f, "{c}")?;
349 }
350 }
351 }
352 Ok(())
353 }
354}
355
356pub fn escape_escaped_string(s: &str) -> EscapeEscapedStringLiteral<'_> {
357 EscapeEscapedStringLiteral(s)
358}
359
360pub struct EscapeUnicodeStringLiteral<'a>(&'a str);
361
362impl fmt::Display for EscapeUnicodeStringLiteral<'_> {
363 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
364 for c in self.0.chars() {
365 match c {
366 '\'' => {
367 write!(f, "''")?;
368 }
369 '\\' => {
370 write!(f, r#"\\"#)?;
371 }
372 x if x.is_ascii() => {
373 write!(f, "{}", c)?;
374 }
375 _ => {
376 let codepoint = c as u32;
377 if codepoint <= 0xFFFF {
380 write!(f, "\\{:04X}", codepoint)?;
381 } else {
382 write!(f, "\\+{:06X}", codepoint)?;
383 }
384 }
385 }
386 }
387 Ok(())
388 }
389}
390
391pub fn escape_unicode_string(s: &str) -> EscapeUnicodeStringLiteral<'_> {
392 EscapeUnicodeStringLiteral(s)
393}
394
395#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
396#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
397#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
398pub enum TrimWhereField {
399 Both,
400 Leading,
401 Trailing,
402}
403
404impl fmt::Display for TrimWhereField {
405 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
406 use TrimWhereField::*;
407 f.write_str(match self {
408 Both => "BOTH",
409 Leading => "LEADING",
410 Trailing => "TRAILING",
411 })
412 }
413}