mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-06 01:34:21 +01:00
remove ToSqlString trait
This commit is contained in:
@@ -1,428 +1,2 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use crate::ast::{self, fmt::ToTokens, Expr};
|
||||
|
||||
use super::ToSqlString;
|
||||
|
||||
impl ToSqlString for Expr {
|
||||
fn to_sql_string<C: super::ToSqlContext>(&self, context: &C) -> String {
|
||||
let mut ret = String::new();
|
||||
match self {
|
||||
Expr::Between {
|
||||
lhs,
|
||||
not,
|
||||
start,
|
||||
end,
|
||||
} => {
|
||||
ret.push_str(&lhs.to_sql_string(context));
|
||||
ret.push(' ');
|
||||
|
||||
if *not {
|
||||
ret.push_str("NOT ");
|
||||
}
|
||||
|
||||
ret.push_str("BETWEEN ");
|
||||
|
||||
ret.push_str(&start.to_sql_string(context));
|
||||
|
||||
ret.push_str(" AND ");
|
||||
|
||||
ret.push_str(&end.to_sql_string(context));
|
||||
}
|
||||
Expr::Binary(lhs, op, rhs) => {
|
||||
ret.push_str(&lhs.to_sql_string(context));
|
||||
ret.push(' ');
|
||||
ret.push_str(&op.to_string());
|
||||
ret.push(' ');
|
||||
ret.push_str(&rhs.to_sql_string(context));
|
||||
}
|
||||
Expr::Case {
|
||||
base,
|
||||
when_then_pairs,
|
||||
else_expr,
|
||||
} => {
|
||||
ret.push_str("CASE ");
|
||||
if let Some(base) = base {
|
||||
ret.push_str(&base.to_sql_string(context));
|
||||
ret.push(' ');
|
||||
}
|
||||
for (when, then) in when_then_pairs {
|
||||
ret.push_str("WHEN ");
|
||||
ret.push_str(&when.to_sql_string(context));
|
||||
ret.push_str(" THEN ");
|
||||
ret.push_str(&then.to_sql_string(context));
|
||||
}
|
||||
if let Some(else_expr) = else_expr {
|
||||
ret.push_str(" ELSE ");
|
||||
ret.push_str(&else_expr.to_sql_string(context));
|
||||
}
|
||||
ret.push_str(" END");
|
||||
}
|
||||
Expr::Cast { expr, type_name } => {
|
||||
ret.push_str("CAST");
|
||||
ret.push('(');
|
||||
ret.push_str(&expr.to_sql_string(context));
|
||||
if let Some(type_name) = type_name {
|
||||
ret.push_str(" AS ");
|
||||
ret.push_str(&type_name.to_sql_string(context));
|
||||
}
|
||||
ret.push(')');
|
||||
}
|
||||
Expr::Collate(expr, name) => {
|
||||
ret.push_str(&expr.to_sql_string(context));
|
||||
ret.push_str(" COLLATE ");
|
||||
ret.push_str(name);
|
||||
}
|
||||
Expr::DoublyQualified(name, name1, name2) => {
|
||||
ret.push_str(&name.0);
|
||||
ret.push('.');
|
||||
ret.push_str(&name1.0);
|
||||
ret.push('.');
|
||||
ret.push_str(&name2.0);
|
||||
}
|
||||
Expr::Exists(select) => {
|
||||
ret.push_str("EXISTS (");
|
||||
ret.push_str(&select.to_sql_string(context));
|
||||
ret.push(')');
|
||||
}
|
||||
Expr::FunctionCall {
|
||||
name,
|
||||
distinctness: _,
|
||||
args,
|
||||
order_by: _,
|
||||
filter_over,
|
||||
} => {
|
||||
ret.push_str(&name.0);
|
||||
// TODO: pretty sure there should be no ORDER_BY nor DISTINCT
|
||||
ret.push('(');
|
||||
if let Some(args) = args {
|
||||
let joined_args = args
|
||||
.iter()
|
||||
.map(|arg| arg.to_sql_string(context))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
ret.push_str(&joined_args);
|
||||
}
|
||||
ret.push(')');
|
||||
if let Some(filter_over) = filter_over {
|
||||
if let Some(filter) = &filter_over.filter_clause {
|
||||
ret.push_str(&format!(
|
||||
" FILTER (WHERE {})",
|
||||
filter.to_sql_string(context)
|
||||
));
|
||||
}
|
||||
if let Some(over) = &filter_over.over_clause {
|
||||
ret.push(' ');
|
||||
ret.push_str(&over.to_sql_string(context));
|
||||
}
|
||||
}
|
||||
}
|
||||
Expr::FunctionCallStar { name, filter_over } => {
|
||||
ret.push_str(&name.0);
|
||||
ret.push_str("(*)");
|
||||
if let Some(filter_over) = filter_over {
|
||||
if let Some(filter) = &filter_over.filter_clause {
|
||||
ret.push_str(&format!(
|
||||
" FILTER (WHERE {})",
|
||||
filter.to_sql_string(context)
|
||||
));
|
||||
}
|
||||
if let Some(over) = &filter_over.over_clause {
|
||||
ret.push(' ');
|
||||
ret.push_str(&over.to_sql_string(context));
|
||||
}
|
||||
}
|
||||
}
|
||||
Expr::Id(id) => {
|
||||
ret.push_str(&id.0);
|
||||
}
|
||||
Expr::Column {
|
||||
database: _, // TODO: Ignore database for now
|
||||
table,
|
||||
column,
|
||||
is_rowid_alias: _,
|
||||
} => {
|
||||
ret.push_str(context.get_table_name(*table));
|
||||
ret.push('.');
|
||||
ret.push_str(context.get_column_name(*table, *column));
|
||||
}
|
||||
Expr::RowId { database: _, table } => {
|
||||
ret.push_str(&format!("{}.rowid", context.get_table_name(*table)))
|
||||
}
|
||||
Expr::InList { lhs, not, rhs } => {
|
||||
ret.push_str(&format!(
|
||||
"{} {}IN ({})",
|
||||
lhs.to_sql_string(context),
|
||||
if *not { "NOT " } else { "" },
|
||||
if let Some(rhs) = rhs {
|
||||
rhs.iter()
|
||||
.map(|expr| expr.to_sql_string(context))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
} else {
|
||||
"".to_string()
|
||||
}
|
||||
));
|
||||
}
|
||||
Expr::InSelect { lhs, not, rhs } => {
|
||||
ret.push_str(&format!(
|
||||
"{} {}IN ({})",
|
||||
lhs.to_sql_string(context),
|
||||
if *not { "NOT " } else { "" },
|
||||
rhs.to_sql_string(context)
|
||||
));
|
||||
}
|
||||
Expr::InTable {
|
||||
lhs,
|
||||
not,
|
||||
rhs,
|
||||
args,
|
||||
} => {
|
||||
ret.push_str(&lhs.to_sql_string(context));
|
||||
ret.push(' ');
|
||||
if *not {
|
||||
ret.push_str("NOT ");
|
||||
}
|
||||
ret.push_str(&rhs.to_sql_string(context));
|
||||
|
||||
if let Some(args) = args {
|
||||
ret.push('(');
|
||||
let joined_args = args
|
||||
.iter()
|
||||
.map(|expr| expr.to_sql_string(context))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
ret.push_str(&joined_args);
|
||||
ret.push(')');
|
||||
}
|
||||
}
|
||||
Expr::IsNull(expr) => {
|
||||
ret.push_str(&expr.to_sql_string(context));
|
||||
ret.push_str(" ISNULL");
|
||||
}
|
||||
Expr::Like {
|
||||
lhs,
|
||||
not,
|
||||
op,
|
||||
rhs,
|
||||
escape,
|
||||
} => {
|
||||
ret.push_str(&lhs.to_sql_string(context));
|
||||
ret.push(' ');
|
||||
if *not {
|
||||
ret.push_str("NOT ");
|
||||
}
|
||||
ret.push_str(&op.to_string());
|
||||
ret.push(' ');
|
||||
ret.push_str(&rhs.to_sql_string(context));
|
||||
if let Some(escape) = escape {
|
||||
ret.push_str(" ESCAPE ");
|
||||
ret.push_str(&escape.to_sql_string(context));
|
||||
}
|
||||
}
|
||||
Expr::Literal(literal) => {
|
||||
ret.push_str(&literal.to_string());
|
||||
}
|
||||
Expr::Name(name) => {
|
||||
ret.push_str(&name.0);
|
||||
}
|
||||
Expr::NotNull(expr) => {
|
||||
ret.push_str(&expr.to_sql_string(context));
|
||||
ret.push_str(" NOT NULL");
|
||||
}
|
||||
Expr::Parenthesized(exprs) => {
|
||||
ret.push('(');
|
||||
let joined_args = exprs
|
||||
.iter()
|
||||
.map(|expr| expr.to_sql_string(context))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
ret.push_str(&joined_args);
|
||||
ret.push(')');
|
||||
}
|
||||
Expr::Qualified(name, name1) => {
|
||||
ret.push_str(&name.0);
|
||||
ret.push('.');
|
||||
ret.push_str(&name1.0);
|
||||
}
|
||||
Expr::Raise(resolve_type, expr) => {
|
||||
ret.push_str("RAISE(");
|
||||
ret.push_str(&resolve_type.to_string());
|
||||
if let Some(expr) = expr {
|
||||
ret.push_str(", ");
|
||||
ret.push_str(&expr.to_sql_string(context));
|
||||
}
|
||||
ret.push(')');
|
||||
}
|
||||
Expr::Subquery(select) => {
|
||||
ret.push('(');
|
||||
ret.push_str(&select.to_sql_string(context));
|
||||
ret.push(')');
|
||||
}
|
||||
Expr::Unary(unary_operator, expr) => {
|
||||
ret.push_str(&unary_operator.to_string());
|
||||
ret.push(' ');
|
||||
ret.push_str(&expr.to_sql_string(context));
|
||||
}
|
||||
Expr::Variable(variable) => {
|
||||
ret.push_str(variable);
|
||||
}
|
||||
};
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ast::Operator {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let value = match self {
|
||||
Self::Add => "+",
|
||||
Self::And => "AND",
|
||||
Self::ArrowRight => "->",
|
||||
Self::ArrowRightShift => "->>",
|
||||
Self::BitwiseAnd => "&",
|
||||
Self::BitwiseNot => "~",
|
||||
Self::BitwiseOr => "|",
|
||||
Self::Concat => "||",
|
||||
Self::Divide => "/",
|
||||
Self::Equals => "=",
|
||||
Self::Greater => ">",
|
||||
Self::GreaterEquals => ">=",
|
||||
Self::Is => "IS",
|
||||
Self::IsNot => "IS NOT",
|
||||
Self::LeftShift => "<<",
|
||||
Self::Less => "<",
|
||||
Self::LessEquals => "<=",
|
||||
Self::Modulus => "%",
|
||||
Self::Multiply => "*",
|
||||
Self::NotEquals => "!=",
|
||||
Self::Or => "OR",
|
||||
Self::RightShift => ">>",
|
||||
Self::Subtract => "-",
|
||||
};
|
||||
write!(f, "{value}")
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSqlString for ast::Type {
|
||||
fn to_sql_string<C: super::ToSqlContext>(&self, context: &C) -> String {
|
||||
let mut ret = self.name.clone();
|
||||
if let Some(size) = &self.size {
|
||||
ret.push(' ');
|
||||
ret.push('(');
|
||||
ret.push_str(&size.to_sql_string(context));
|
||||
ret.push(')');
|
||||
}
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSqlString for ast::TypeSize {
|
||||
fn to_sql_string<C: super::ToSqlContext>(&self, context: &C) -> String {
|
||||
let mut ret = String::new();
|
||||
match self {
|
||||
Self::MaxSize(e) => {
|
||||
ret.push_str(&e.to_sql_string(context));
|
||||
}
|
||||
Self::TypeSize(lhs, rhs) => {
|
||||
ret.push_str(&lhs.to_sql_string(context));
|
||||
ret.push_str(", ");
|
||||
ret.push_str(&rhs.to_sql_string(context));
|
||||
}
|
||||
};
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ast::Distinctness {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
Self::All => "ALL",
|
||||
Self::Distinct => "DISTINCT",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Can't impl Display here as it is already implemented for it
|
||||
impl ToSqlString for ast::QualifiedName {
|
||||
fn to_sql_string<C: super::ToSqlContext>(&self, _context: &C) -> String {
|
||||
let mut ret = String::new();
|
||||
if let Some(db_name) = &self.db_name {
|
||||
ret.push_str(&db_name.0);
|
||||
ret.push('.');
|
||||
}
|
||||
if let Some(alias) = &self.alias {
|
||||
ret.push_str(&alias.0);
|
||||
ret.push('.');
|
||||
}
|
||||
ret.push_str(&self.name.0);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ast::LikeOperator {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.to_fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ast::Literal {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
Self::Blob(b) => format!("x'{b}'"),
|
||||
Self::CurrentDate => "CURRENT_DATE".to_string(),
|
||||
Self::CurrentTime => "CURRENT_TIME".to_string(),
|
||||
Self::CurrentTimestamp => "CURRENT_TIMESTAMP".to_string(),
|
||||
Self::Keyword(keyword) => keyword.clone(),
|
||||
Self::Null => "NULL".to_string(),
|
||||
Self::Numeric(num) => num.clone(),
|
||||
Self::String(s) => s.clone(),
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ast::ResolveType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.to_fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ast::UnaryOperator {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
Self::BitwiseNot => "~",
|
||||
Self::Negative => "-",
|
||||
Self::Not => "NOT",
|
||||
Self::Positive => "+",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSqlString for ast::Over {
|
||||
fn to_sql_string<C: super::ToSqlContext>(&self, context: &C) -> String {
|
||||
let mut ret = vec!["OVER".to_string()];
|
||||
match self {
|
||||
Self::Name(name) => {
|
||||
ret.push(name.0.clone());
|
||||
}
|
||||
Self::Window(window) => {
|
||||
ret.push(window.to_sql_string(context));
|
||||
}
|
||||
}
|
||||
ret.join(" ")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {}
|
||||
|
||||
Reference in New Issue
Block a user