use chrono::{DateTime, NaiveDate, NaiveDateTime, Utc};
use crate::common::*;
pub(crate) trait WriteBigQuerySql<W: Write> {
fn write_bigquery_sql(&self, sql: &mut W) -> Result<(), io::Error>;
}
impl<W: Write> WriteBigQuerySql<W> for bool {
fn write_bigquery_sql(&self, sql: &mut W) -> Result<(), io::Error> {
if *self {
write!(sql, "TRUE")
} else {
write!(sql, "FALSE")
}
}
}
impl<W: Write> WriteBigQuerySql<W> for &'_ str {
fn write_bigquery_sql(&self, sql: &mut W) -> Result<(), io::Error> {
write!(sql, "'")?;
for c in self.chars() {
match c {
'\'' | '\\' => write!(sql, "\\{}", c),
'\r' => write!(sql, "\\r"),
'\n' => write!(sql, "\\n"),
_ if c.is_ascii_graphic() => write!(sql, "{}", c),
_ => write!(sql, "\\U{:08x}", u32::from(c)),
}?;
}
write!(sql, "'")?;
Ok(())
}
}
pub(crate) struct BytesLiteral<'a>(pub(crate) &'a str);
impl<'a, W: Write> WriteBigQuerySql<W> for BytesLiteral<'a> {
fn write_bigquery_sql(&self, sql: &mut W) -> Result<(), io::Error> {
write!(sql, "B")?;
self.0.write_bigquery_sql(sql)
}
}
impl<W: Write> WriteBigQuerySql<W> for f64 {
fn write_bigquery_sql(&self, sql: &mut W) -> Result<(), io::Error> {
write!(sql, "{}", *self)
}
}
pub(crate) struct ExpNotation(pub f64);
impl<W: Write> WriteBigQuerySql<W> for ExpNotation {
fn write_bigquery_sql(&self, sql: &mut W) -> Result<(), io::Error> {
write!(sql, "{:e}", self.0)
}
}
impl<W: Write> WriteBigQuerySql<W> for i64 {
fn write_bigquery_sql(&self, sql: &mut W) -> Result<(), io::Error> {
write!(sql, "{}", *self)
}
}
pub(crate) struct NumericLiteral<'a>(pub(crate) &'a str);
impl<'a, W: Write> WriteBigQuerySql<W> for NumericLiteral<'a> {
fn write_bigquery_sql(&self, sql: &mut W) -> Result<(), io::Error> {
write!(sql, "NUMERIC ")?;
self.0.write_bigquery_sql(sql)
}
}
pub(crate) struct GeographyLiteral<'a>(pub(crate) &'a str);
impl<'a, W: Write> WriteBigQuerySql<W> for GeographyLiteral<'a> {
fn write_bigquery_sql(&self, sql: &mut W) -> Result<(), io::Error> {
write!(sql, "ST_GEOGFROMGEOJSON(")?;
self.0.write_bigquery_sql(sql)?;
write!(sql, ")")
}
}
impl<'a, W: Write, Elem: WriteBigQuerySql<W>> WriteBigQuerySql<W> for &'a [Elem] {
fn write_bigquery_sql(&self, sql: &mut W) -> Result<(), io::Error> {
write!(sql, "ARRAY[")?;
for (idx, elem) in self.iter().enumerate() {
if idx != 0 {
write!(sql, ",")?;
}
elem.write_bigquery_sql(sql)?;
}
write!(sql, "]")
}
}
impl<W: Write> WriteBigQuerySql<W> for NaiveDate {
fn write_bigquery_sql(&self, sql: &mut W) -> Result<(), io::Error> {
write!(sql, "DATE '{}'", self.format("%Y-%m-%d"))
}
}
impl<W: Write> WriteBigQuerySql<W> for NaiveDateTime {
fn write_bigquery_sql(&self, sql: &mut W) -> Result<(), io::Error> {
write!(sql, "DATETIME '{}'", self.format("%Y-%m-%dT%H:%M:%S%.f"))
}
}
impl<W: Write> WriteBigQuerySql<W> for DateTime<Utc> {
fn write_bigquery_sql(&self, sql: &mut W) -> Result<(), io::Error> {
write!(
sql,
"TIMESTAMP '{}'",
self.format("%Y-%m-%dT%H:%M:%S%.f%:z")
)
}
}