diff --git a/src/backend/query_builder.rs b/src/backend/query_builder.rs index 41cac862..85984700 100644 --- a/src/backend/query_builder.rs +++ b/src/backend/query_builder.rs @@ -387,9 +387,24 @@ pub trait QueryBuilder: SimpleExpr::Constant(val) => { self.prepare_constant(val, sql); } + SimpleExpr::IfElse(val) => { + self.prepare_if_else_statement(val, sql); + } } } + fn prepare_if_else_statement(&self, val: &Box, sql: &mut dyn SqlWriter) { + write!(sql, "IF ").unwrap(); + self.prepare_simple_expr(&val.when, sql); + write!(sql, " THEN\n").unwrap(); + self.prepare_simple_expr(&val.then, sql); + if let Some(otherwise) = &val.otherwise { + write!(sql, "\nELSE\n").unwrap(); + self.prepare_simple_expr(otherwise, sql); + }; + write!(sql, "\nEND IF").unwrap(); + } + /// Translate [`CaseStatement`] into SQL statement. fn prepare_case_statement(&self, stmts: &CaseStatement, sql: &mut dyn SqlWriter) { write!(sql, "(CASE").unwrap(); diff --git a/src/expr.rs b/src/expr.rs index b6894c94..11a95306 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -4,7 +4,7 @@ //! //! [`SimpleExpr`] is the expression common among select fields, where clauses and many other places. -use crate::{func::*, query::*, types::*, value::*}; +use crate::{func::*, if_else::*, query::*, types::*, value::*}; /// Helper to build a [`SimpleExpr`]. #[derive(Debug, Clone)] @@ -35,6 +35,7 @@ pub enum SimpleExpr { AsEnum(DynIden, Box), Case(Box), Constant(Value), + IfElse(Box), } /// "Operator" methods for building complex expressions. diff --git a/src/if_else.rs b/src/if_else.rs new file mode 100644 index 00000000..1d89611d --- /dev/null +++ b/src/if_else.rs @@ -0,0 +1,33 @@ +use crate::{QueryBuilder, SimpleExpr}; + +#[derive(Debug, Clone, PartialEq)] +pub struct IfElseStatement { + pub when: SimpleExpr, + pub then: SimpleExpr, + pub otherwise: Option, +} + +impl IfElseStatement { + pub fn new(when: SimpleExpr, then: SimpleExpr, otherwise: Option) -> Self { + Self { + when, + then, + otherwise, + } + } + + pub fn to_string(&self, query_builder: T) -> String { + let mut sql = String::with_capacity(256); + query_builder.prepare_if_else_statement(&Box::new(self.clone()), &mut sql); + sql + } +} +pub trait IfElseStatementBuilder { + /// Build corresponding SQL statement for certain database backend and return SQL string + fn build(&self, query_builder: T) -> String; + + /// Build corresponding SQL statement for certain database backend and return SQL string + fn to_string(&self, query_builder: T) -> String { + self.build(query_builder) + } +} diff --git a/src/lib.rs b/src/lib.rs index 15e1a189..7ee5411c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -818,6 +818,7 @@ pub mod expr; pub mod extension; pub mod foreign_key; pub mod func; +pub mod if_else; pub mod index; pub mod prepare; pub mod query; @@ -835,6 +836,7 @@ pub use backend::*; pub use expr::*; pub use foreign_key::*; pub use func::*; +pub use if_else::*; pub use index::*; pub use prepare::*; pub use query::*; diff --git a/tests/mysql/if_else.rs b/tests/mysql/if_else.rs new file mode 100644 index 00000000..bd5e94b7 --- /dev/null +++ b/tests/mysql/if_else.rs @@ -0,0 +1,45 @@ +use super::*; +use pretty_assertions::assert_eq; + +#[rustfmt::skip] +#[test] +fn if_without_else() { + let query = Query::select().column(Asterisk).from(Glyph::Table).take(); + let then = SimpleExpr::SubQuery(None, Box::new(query.into_sub_query_statement())); + let if_statement = IfElseStatement::new( + Expr::col(Glyph::Id).eq(1), + then, + None + ); + assert_eq!( + if_statement.to_string(MysqlQueryBuilder), + [ + "IF `id` = 1 THEN", + "(SELECT * FROM `glyph`)", + "END IF" + ].join("\n") + ) +} + +#[rustfmt::skip] +#[test] +fn if_with_else() { + let query = Query::select().column(Asterisk).from(Glyph::Table).take(); + let then = SimpleExpr::SubQuery(None, Box::new(query.into_sub_query_statement())); + let if_statement = IfElseStatement::new( + Expr::col(Glyph::Id).eq(1), + then, + Some(Expr::val("23").into()), + ); + assert_eq!( + if_statement.to_string(MysqlQueryBuilder), + [ + "IF `id` = 1 THEN", + "(SELECT * FROM `glyph`)", + "ELSE", + "'23'", + "END IF" + ] + .join("\n") + ) +} diff --git a/tests/mysql/mod.rs b/tests/mysql/mod.rs index d717774f..d3a4fe85 100644 --- a/tests/mysql/mod.rs +++ b/tests/mysql/mod.rs @@ -1,6 +1,7 @@ use sea_query::{extension::mysql::*, tests_cfg::*, *}; mod foreign_key; +mod if_else; mod index; mod query; mod table;