Skip to content

Commit

Permalink
implement IfElseStatement for MySQL backend
Browse files Browse the repository at this point in the history
  • Loading branch information
gronke committed Dec 26, 2024
1 parent 605ec44 commit 181a045
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 1 deletion.
15 changes: 15 additions & 0 deletions src/backend/query_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<IfElseStatement>, 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();
Expand Down
3 changes: 2 additions & 1 deletion src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -35,6 +35,7 @@ pub enum SimpleExpr {
AsEnum(DynIden, Box<SimpleExpr>),
Case(Box<CaseStatement>),
Constant(Value),
IfElse(Box<IfElseStatement>),
}

/// "Operator" methods for building complex expressions.
Expand Down
33 changes: 33 additions & 0 deletions src/if_else.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use crate::{QueryBuilder, SimpleExpr};

#[derive(Debug, Clone, PartialEq)]
pub struct IfElseStatement {
pub when: SimpleExpr,
pub then: SimpleExpr,
pub otherwise: Option<SimpleExpr>,
}

impl IfElseStatement {
pub fn new(when: SimpleExpr, then: SimpleExpr, otherwise: Option<SimpleExpr>) -> Self {
Self {
when,
then,
otherwise,
}
}

pub fn to_string<T: QueryBuilder>(&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<T: QueryBuilder>(&self, query_builder: T) -> String;

/// Build corresponding SQL statement for certain database backend and return SQL string
fn to_string<T: QueryBuilder>(&self, query_builder: T) -> String {
self.build(query_builder)
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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::*;
Expand Down
45 changes: 45 additions & 0 deletions tests/mysql/if_else.rs
Original file line number Diff line number Diff line change
@@ -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")
)
}
1 change: 1 addition & 0 deletions tests/mysql/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use sea_query::{extension::mysql::*, tests_cfg::*, *};

mod foreign_key;
mod if_else;
mod index;
mod query;
mod table;
Expand Down

0 comments on commit 181a045

Please sign in to comment.