#[cfg(not(feature = "std"))]
use alloc::string::String;
use core::fmt;
#[cfg(feature = "bigdecimal")]
use bigdecimal::BigDecimal;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "visitor")]
use sqlparser_derive::{Visit, VisitMut};
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum Value {
#[cfg(not(feature = "bigdecimal"))]
Number(String, bool),
#[cfg(feature = "bigdecimal")]
Number(BigDecimal, bool),
SingleQuotedString(String),
DollarQuotedString(DollarQuotedString),
EscapedStringLiteral(String),
SingleQuotedByteStringLiteral(String),
DoubleQuotedByteStringLiteral(String),
RawStringLiteral(String),
NationalStringLiteral(String),
HexStringLiteral(String),
DoubleQuotedString(String),
Boolean(bool),
Null,
Placeholder(String),
UnQuotedString(String),
}
impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Value::Number(v, l) => write!(f, "{}{long}", v, long = if *l { "L" } else { "" }),
Value::DoubleQuotedString(v) => write!(f, "\"{}\"", escape_double_quote_string(v)),
Value::SingleQuotedString(v) => write!(f, "'{}'", escape_single_quote_string(v)),
Value::DollarQuotedString(v) => write!(f, "{v}"),
Value::EscapedStringLiteral(v) => write!(f, "E'{}'", escape_escaped_string(v)),
Value::NationalStringLiteral(v) => write!(f, "N'{v}'"),
Value::HexStringLiteral(v) => write!(f, "X'{v}'"),
Value::Boolean(v) => write!(f, "{v}"),
Value::SingleQuotedByteStringLiteral(v) => write!(f, "B'{v}'"),
Value::DoubleQuotedByteStringLiteral(v) => write!(f, "B\"{v}\""),
Value::RawStringLiteral(v) => write!(f, "R'{v}'"),
Value::Null => write!(f, "NULL"),
Value::Placeholder(v) => write!(f, "{v}"),
Value::UnQuotedString(v) => write!(f, "{v}"),
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct DollarQuotedString {
pub value: String,
pub tag: Option<String>,
}
impl fmt::Display for DollarQuotedString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self.tag {
Some(tag) => {
write!(f, "${}${}${}$", tag, self.value, tag)
}
None => {
write!(f, "$${}$$", self.value)
}
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum DateTimeField {
Year,
Month,
Week,
Day,
Date,
Hour,
Minute,
Second,
Century,
Decade,
Dow,
Doy,
Epoch,
Isodow,
Isoyear,
Julian,
Microsecond,
Microseconds,
Millenium,
Millennium,
Millisecond,
Milliseconds,
Nanosecond,
Nanoseconds,
Quarter,
Timezone,
TimezoneHour,
TimezoneMinute,
NoDateTime,
}
impl fmt::Display for DateTimeField {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(match self {
DateTimeField::Year => "YEAR",
DateTimeField::Month => "MONTH",
DateTimeField::Week => "WEEK",
DateTimeField::Day => "DAY",
DateTimeField::Date => "DATE",
DateTimeField::Hour => "HOUR",
DateTimeField::Minute => "MINUTE",
DateTimeField::Second => "SECOND",
DateTimeField::Century => "CENTURY",
DateTimeField::Decade => "DECADE",
DateTimeField::Dow => "DOW",
DateTimeField::Doy => "DOY",
DateTimeField::Epoch => "EPOCH",
DateTimeField::Isodow => "ISODOW",
DateTimeField::Isoyear => "ISOYEAR",
DateTimeField::Julian => "JULIAN",
DateTimeField::Microsecond => "MICROSECOND",
DateTimeField::Microseconds => "MICROSECONDS",
DateTimeField::Millenium => "MILLENIUM",
DateTimeField::Millennium => "MILLENNIUM",
DateTimeField::Millisecond => "MILLISECOND",
DateTimeField::Milliseconds => "MILLISECONDS",
DateTimeField::Nanosecond => "NANOSECOND",
DateTimeField::Nanoseconds => "NANOSECONDS",
DateTimeField::Quarter => "QUARTER",
DateTimeField::Timezone => "TIMEZONE",
DateTimeField::TimezoneHour => "TIMEZONE_HOUR",
DateTimeField::TimezoneMinute => "TIMEZONE_MINUTE",
DateTimeField::NoDateTime => "NODATETIME",
})
}
}
pub struct EscapeQuotedString<'a> {
string: &'a str,
quote: char,
}
impl<'a> fmt::Display for EscapeQuotedString<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let quote = self.quote;
let mut previous_char = char::default();
let mut peekable_chars = self.string.chars().peekable();
while let Some(&ch) = peekable_chars.peek() {
match ch {
char if char == quote => {
if previous_char == '\\' {
write!(f, "{char}")?;
peekable_chars.next();
continue;
}
peekable_chars.next();
if peekable_chars.peek().map(|c| *c == quote).unwrap_or(false) {
write!(f, "{char}{char}")?;
peekable_chars.next();
} else {
write!(f, "{char}{char}")?;
}
}
_ => {
write!(f, "{ch}")?;
peekable_chars.next();
}
}
previous_char = ch;
}
Ok(())
}
}
pub fn escape_quoted_string(string: &str, quote: char) -> EscapeQuotedString<'_> {
EscapeQuotedString { string, quote }
}
pub fn escape_single_quote_string(s: &str) -> EscapeQuotedString<'_> {
escape_quoted_string(s, '\'')
}
pub fn escape_double_quote_string(s: &str) -> EscapeQuotedString<'_> {
escape_quoted_string(s, '\"')
}
pub struct EscapeEscapedStringLiteral<'a>(&'a str);
impl<'a> fmt::Display for EscapeEscapedStringLiteral<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for c in self.0.chars() {
match c {
'\'' => {
write!(f, r#"\'"#)?;
}
'\\' => {
write!(f, r#"\\"#)?;
}
'\n' => {
write!(f, r#"\n"#)?;
}
'\t' => {
write!(f, r#"\t"#)?;
}
'\r' => {
write!(f, r#"\r"#)?;
}
_ => {
write!(f, "{c}")?;
}
}
}
Ok(())
}
}
pub fn escape_escaped_string(s: &str) -> EscapeEscapedStringLiteral<'_> {
EscapeEscapedStringLiteral(s)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum TrimWhereField {
Both,
Leading,
Trailing,
}
impl fmt::Display for TrimWhereField {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use TrimWhereField::*;
f.write_str(match self {
Both => "BOTH",
Leading => "LEADING",
Trailing => "TRAILING",
})
}
}