use crate::prelude::*;
use crate::{Param, Placeholder, SQLColumnInfo, SQLParam, SQLTableInfo, sql::tokens::Token};
#[derive(Clone)]
pub enum SQLChunk<'a, V: SQLParam> {
Token(Token),
Ident(Cow<'a, str>),
Raw(Cow<'a, str>),
Param(Param<'a, V>),
Table(&'static dyn SQLTableInfo),
Column(&'static dyn SQLColumnInfo),
}
impl<'a, V: SQLParam> SQLChunk<'a, V> {
#[inline]
pub const fn token(t: Token) -> Self {
Self::Token(t)
}
#[inline]
pub const fn ident_static(name: &'static str) -> Self {
Self::Ident(Cow::Borrowed(name))
}
#[inline]
pub const fn raw_static(text: &'static str) -> Self {
Self::Raw(Cow::Borrowed(text))
}
#[inline]
pub const fn table(table: &'static dyn SQLTableInfo) -> Self {
Self::Table(table)
}
#[inline]
pub const fn column(column: &'static dyn SQLColumnInfo) -> Self {
Self::Column(column)
}
#[inline]
pub const fn param_borrowed(value: &'a V, placeholder: Placeholder) -> Self {
Self::Param(Param {
value: Some(Cow::Borrowed(value)),
placeholder,
})
}
#[inline]
pub fn ident(name: impl Into<Cow<'a, str>>) -> Self {
Self::Ident(name.into())
}
#[inline]
pub fn raw(text: impl Into<Cow<'a, str>>) -> Self {
Self::Raw(text.into())
}
#[inline]
pub fn param(value: impl Into<Cow<'a, V>>, placeholder: Placeholder) -> Self {
Self::Param(Param {
value: Some(value.into()),
placeholder,
})
}
pub(crate) fn write(&self, buf: &mut impl core::fmt::Write) {
match self {
SQLChunk::Token(token) => {
let _ = buf.write_str(token.as_str());
}
SQLChunk::Ident(name) => {
let _ = buf.write_char('"');
let _ = buf.write_str(name);
let _ = buf.write_char('"');
}
SQLChunk::Raw(text) => {
let _ = buf.write_str(text);
}
SQLChunk::Param(Param { placeholder, .. }) => {
let _ = write!(buf, "{}", placeholder);
}
SQLChunk::Table(table) => {
let _ = buf.write_char('"');
let _ = buf.write_str(table.name());
let _ = buf.write_char('"');
}
SQLChunk::Column(column) => {
let _ = buf.write_char('"');
let _ = buf.write_str(column.table().name());
let _ = buf.write_str("\".\"");
let _ = buf.write_str(column.name());
let _ = buf.write_char('"');
}
}
}
#[inline]
pub(crate) const fn is_word_like(&self) -> bool {
match self {
SQLChunk::Token(t) => !t.is_punctuation() && !t.is_operator(),
SQLChunk::Ident(_)
| SQLChunk::Raw(_)
| SQLChunk::Param(_)
| SQLChunk::Table(_)
| SQLChunk::Column(_) => true,
}
}
}
impl<'a, V: SQLParam + core::fmt::Debug> core::fmt::Debug for SQLChunk<'a, V> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
SQLChunk::Token(token) => f.debug_tuple("Token").field(token).finish(),
SQLChunk::Ident(name) => f.debug_tuple("Ident").field(name).finish(),
SQLChunk::Raw(text) => f.debug_tuple("Raw").field(text).finish(),
SQLChunk::Param(param) => f.debug_tuple("Param").field(param).finish(),
SQLChunk::Table(table) => f.debug_tuple("Table").field(&table.name()).finish(),
SQLChunk::Column(column) => f
.debug_tuple("Column")
.field(&format!("{}.{}", column.table().name(), column.name()))
.finish(),
}
}
}
impl<'a, V: SQLParam> From<Token> for SQLChunk<'a, V> {
#[inline]
fn from(value: Token) -> Self {
Self::Token(value)
}
}
impl<'a, V: SQLParam> From<&'static dyn SQLColumnInfo> for SQLChunk<'a, V> {
#[inline]
fn from(value: &'static dyn SQLColumnInfo) -> Self {
Self::Column(value)
}
}
impl<'a, V: SQLParam> From<&'static dyn SQLTableInfo> for SQLChunk<'a, V> {
#[inline]
fn from(value: &'static dyn SQLTableInfo) -> Self {
Self::Table(value)
}
}
impl<'a, V: SQLParam> From<Param<'a, V>> for SQLChunk<'a, V> {
#[inline]
fn from(value: Param<'a, V>) -> Self {
Self::Param(value)
}
}