Skip to content

Commit 59f612d

Browse files
committed
elseif support in IfElseStatement
1 parent 55ada32 commit 59f612d

File tree

9 files changed

+164
-4
lines changed

9 files changed

+164
-4
lines changed

src/backend/mysql/query.rs

+6
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,12 @@ 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+
}
155+
150156
}
151157

152158
impl MysqlQueryBuilder {

src/backend/postgres/query.rs

+5
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

+16-4
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

+4
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

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

tests/postgres/if_else.rs

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

tests/postgres/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod index;
55
mod query;
66
mod table;
77
mod types;
8+
mod if_else;
89

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

tests/sqlite/mod.rs

+1
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

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

0 commit comments

Comments
 (0)