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 Oct 13, 2024
1 parent 098e88b commit 55ada32
Show file tree
Hide file tree
Showing 6 changed files with 97 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::*, query::*, types::*, value::*, if_else::*};

/// 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
35 changes: 35 additions & 0 deletions src/if_else.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
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 @@ -826,6 +826,7 @@ pub mod table;
pub mod token;
pub mod types;
pub mod value;
pub mod if_else;

#[doc(hidden)]
#[cfg(feature = "tests-cfg")]
Expand All @@ -843,6 +844,7 @@ pub use table::*;
pub use token::*;
pub use types::*;
pub use value::*;
pub use if_else::*;

#[cfg(feature = "derive")]
pub use sea_query_derive::{enum_def, Iden, IdenStatic};
Expand Down
42 changes: 42 additions & 0 deletions tests/mysql/if_else.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use super::*;
use pretty_assertions::assert_eq;

#[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")
)
}

#[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
Expand Up @@ -4,6 +4,7 @@ mod foreign_key;
mod index;
mod query;
mod table;
mod if_else;

#[path = "../common.rs"]
mod common;
Expand Down

0 comments on commit 55ada32

Please sign in to comment.