Skip to content

Commit 018571e

Browse files
committed
elseif support in IfElseStatement
1 parent e0927e4 commit 018571e

File tree

9 files changed

+169
-4
lines changed

9 files changed

+169
-4
lines changed

src/backend/mysql/query.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ impl QueryBuilder for MysqlQueryBuilder {
147147
fn insert_default_keyword(&self) -> &str {
148148
"()"
149149
}
150+
151+
/// Prefix of the ELSEIF (MySQL)
152+
fn elseif_keyword_prefix(&self) -> &str {
153+
"ELSE"
154+
}
150155
}
151156

152157
impl MysqlQueryBuilder {

src/backend/postgres/query.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,11 @@ impl QueryBuilder for PostgresQueryBuilder {
174174
fn if_null_function(&self) -> &str {
175175
"COALESCE"
176176
}
177+
178+
/// Prefix of the ELSIF (Postgres)
179+
fn elseif_keyword_prefix(&self) -> &str {
180+
"ELS"
181+
}
177182
}
178183

179184
fn is_pg_comparison(b: &BinOper) -> bool {

src/backend/query_builder.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -393,16 +393,28 @@ pub trait QueryBuilder:
393393
}
394394
}
395395

396+
/// Prefix of the ELSEIF (MySQL) vs ELSIF (Postgres) keyword
397+
fn elseif_keyword_prefix(&self) -> &str {
398+
panic!("ELSEIF/ELSIF keyword prefix not implemented for this backend");
399+
}
400+
396401
fn prepare_if_else_statement(&self, val: &Box<IfElseStatement>, sql: &mut dyn SqlWriter) {
397402
write!(sql, "IF ").unwrap();
398403
self.prepare_simple_expr(&val.when, sql);
399404
write!(sql, " THEN\n").unwrap();
400405
self.prepare_simple_expr(&val.then, sql);
401-
if let Some(otherwise) = &val.otherwise {
402-
write!(sql, "\nELSE\n").unwrap();
403-
self.prepare_simple_expr(otherwise, sql);
406+
match &val.otherwise {
407+
Some(SimpleExpr::IfElse(value)) => {
408+
write!(sql, "\n{}", self.elseif_keyword_prefix()).unwrap();
409+
self.prepare_if_else_statement(value, sql);
410+
}
411+
Some(otherwise) => {
412+
write!(sql, "\nELSE\n").unwrap();
413+
self.prepare_simple_expr(otherwise, sql);
414+
write!(sql, "\nEND IF").unwrap();
415+
}
416+
None => write!(sql, "\nEND IF").unwrap(),
404417
};
405-
write!(sql, "\nEND IF").unwrap();
406418
}
407419

408420
/// Translate [`CaseStatement`] into SQL statement.

src/backend/sqlite/query.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,8 @@ impl QueryBuilder for SqliteQueryBuilder {
8484
// SQLite doesn't support inserting multiple rows with default values
8585
write!(sql, "DEFAULT VALUES").unwrap()
8686
}
87+
88+
fn prepare_if_else_statement(&self, _val: &Box<IfElseStatement>, _sql: &mut dyn SqlWriter) {
89+
panic!("Sqlite doesn't support if-else statements")
90+
}
8791
}

tests/mysql/if_else.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,57 @@ fn if_with_else() {
4343
.join("\n")
4444
)
4545
}
46+
47+
#[test]
48+
fn if_with_elseif() {
49+
let query = Query::select().column(Asterisk).from(Glyph::Table).take();
50+
let then = SimpleExpr::SubQuery(None, Box::new(query.into_sub_query_statement()));
51+
let if_statement = IfElseStatement::new(
52+
Expr::col(Glyph::Id).eq(1),
53+
then,
54+
Some(SimpleExpr::IfElse(Box::new(IfElseStatement::new(
55+
Expr::col(Glyph::Id).eq(2),
56+
Expr::val("42").into(),
57+
None,
58+
)))),
59+
);
60+
assert_eq!(
61+
if_statement.to_string(MysqlQueryBuilder),
62+
[
63+
"IF `id` = 1 THEN",
64+
"(SELECT * FROM `glyph`)",
65+
"ELSEIF `id` = 2 THEN",
66+
"'42'",
67+
"END IF"
68+
]
69+
.join("\n")
70+
)
71+
}
72+
73+
#[test]
74+
fn if_with_elseif_and_else() {
75+
let query = Query::select().column(Asterisk).from(Glyph::Table).take();
76+
let then = SimpleExpr::SubQuery(None, Box::new(query.into_sub_query_statement()));
77+
let if_statement = IfElseStatement::new(
78+
Expr::col(Glyph::Id).eq(1),
79+
then,
80+
Some(SimpleExpr::IfElse(Box::new(IfElseStatement::new(
81+
Expr::col(Glyph::Id).eq(2),
82+
Expr::val("42").into(),
83+
Some(Expr::val("9000").into()),
84+
)))),
85+
);
86+
assert_eq!(
87+
if_statement.to_string(MysqlQueryBuilder),
88+
[
89+
"IF `id` = 1 THEN",
90+
"(SELECT * FROM `glyph`)",
91+
"ELSEIF `id` = 2 THEN",
92+
"'42'",
93+
"ELSE",
94+
"'9000'",
95+
"END IF"
96+
]
97+
.join("\n")
98+
);
99+
}

tests/postgres/if_else.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use super::*;
2+
use pretty_assertions::assert_eq;
3+
4+
#[test]
5+
#[rustfmt::skip]
6+
fn if_without_else() {
7+
let query = Query::select().column(Asterisk).from(Glyph::Table).take();
8+
let then = SimpleExpr::SubQuery(None, Box::new(query.into_sub_query_statement()));
9+
let if_statement = IfElseStatement::new(
10+
Expr::col(Glyph::Id).eq(1),
11+
then,
12+
None
13+
);
14+
assert_eq!(
15+
if_statement.to_string(MysqlQueryBuilder),
16+
[
17+
"IF `id` = 1 THEN",
18+
"(SELECT * FROM `glyph`)",
19+
"END IF"
20+
].join("\n")
21+
)
22+
}
23+
24+
#[test]
25+
#[rustfmt::skip]
26+
fn if_with_else() {
27+
let query = Query::select().column(Asterisk).from(Glyph::Table).take();
28+
let then = SimpleExpr::SubQuery(None, Box::new(query.into_sub_query_statement()));
29+
let if_statement = IfElseStatement::new(
30+
Expr::col(Glyph::Id).eq(1),
31+
then,
32+
Some(Expr::val("23").into())
33+
);
34+
assert_eq!(
35+
if_statement.to_string(PostgresQueryBuilder),
36+
[
37+
"IF \"id\" = 1 THEN",
38+
"(SELECT * FROM \"glyph\")",
39+
"ELSE",
40+
"'23'",
41+
"END IF"
42+
].join("\n")
43+
)
44+
}
45+
46+
#[test]
47+
#[rustfmt::skip]
48+
fn if_with_elseif() {
49+
let query = Query::select().column(Asterisk).from(Glyph::Table).take();
50+
let then = SimpleExpr::SubQuery(None, Box::new(query.into_sub_query_statement()));
51+
let if_statement = IfElseStatement::new(
52+
Expr::col(Glyph::Id).eq(1),
53+
then,
54+
Some(SimpleExpr::IfElse(Box::new(IfElseStatement::new(
55+
Expr::col(Glyph::Id).eq(2),
56+
Expr::val("123").into(),
57+
None
58+
))))
59+
);
60+
assert_eq!(
61+
if_statement.to_string(PostgresQueryBuilder),
62+
[
63+
"IF \"id\" = 1 THEN",
64+
"(SELECT * FROM \"glyph\")",
65+
"ELSIF \"id\" = 2 THEN",
66+
"'123'",
67+
"END IF"
68+
].join("\n")
69+
)
70+
}

tests/postgres/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use sea_query::{tests_cfg::*, *};
22

33
mod foreign_key;
4+
mod if_else;
45
mod index;
56
mod query;
67
mod table;

tests/sqlite/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod foreign_key;
44
mod index;
55
mod query;
66
mod table;
7+
mod unsupported;
78

89
#[path = "../common.rs"]
910
mod common;

tests/sqlite/unsupported.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use super::*;
2+
3+
#[test]
4+
#[should_panic]
5+
#[rustfmt::skip]
6+
fn if_else_statement_is_unsupported() {
7+
let if_statement = IfElseStatement::new(
8+
Expr::col(Glyph::Id).eq(1),
9+
Expr::val("23").into(),
10+
None
11+
);
12+
if_statement.to_string(SqliteQueryBuilder);
13+
}

0 commit comments

Comments
 (0)