sea_query/query/case.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
use crate::{Condition, IntoCondition, SimpleExpr};
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct CaseStatementCondition {
pub(crate) condition: Condition,
pub(crate) result: SimpleExpr,
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct CaseStatement {
pub(crate) when: Vec<CaseStatementCondition>,
pub(crate) r#else: Option<SimpleExpr>,
}
impl CaseStatement {
/// Creates a new case statement expression
///
/// # Examples
///
/// ```
/// use sea_query::{*, tests_cfg::*};
///
/// let query = Query::select()
/// .expr_as(
/// CaseStatement::new()
/// .case(Expr::col((Glyph::Table, Glyph::Aspect)).is_in([2, 4]), true)
/// .finally(false),
/// Alias::new("is_even")
/// )
/// .from(Glyph::Table)
/// .to_owned();
///
/// assert_eq!(
/// query.to_string(PostgresQueryBuilder),
/// r#"SELECT (CASE WHEN ("glyph"."aspect" IN (2, 4)) THEN TRUE ELSE FALSE END) AS "is_even" FROM "glyph""#
/// );
/// ```
pub fn new() -> Self {
Self::default()
}
/// Adds new `CASE WHEN` to existing case statement.
///
/// # Examples
///
/// ```
/// use sea_query::{*, tests_cfg::*};
///
/// let query = Query::select()
/// .expr_as(
/// Expr::case(
/// Expr::col((Glyph::Table, Glyph::Aspect)).gt(0),
/// "positive"
/// )
/// .case(
/// Expr::col((Glyph::Table, Glyph::Aspect)).lt(0),
/// "negative"
/// )
/// .finally("zero"),
/// Alias::new("polarity")
/// )
/// .from(Glyph::Table)
/// .to_owned();
///
/// assert_eq!(
/// query.to_string(PostgresQueryBuilder),
/// r#"SELECT (CASE WHEN ("glyph"."aspect" > 0) THEN 'positive' WHEN ("glyph"."aspect" < 0) THEN 'negative' ELSE 'zero' END) AS "polarity" FROM "glyph""#
/// );
/// ```
pub fn case<C, T>(mut self, cond: C, then: T) -> Self
where
C: IntoCondition,
T: Into<SimpleExpr>,
{
self.when.push(CaseStatementCondition {
condition: cond.into_condition(),
result: then.into(),
});
self
}
/// Ends the case statement with the final `ELSE` result.
///
/// # Examples
///
/// ```
/// use sea_query::{*, tests_cfg::*};
///
/// let query = Query::select()
/// .expr_as(
/// Expr::case(
/// Cond::any()
/// .add(Expr::col((Character::Table, Character::FontSize)).gt(48))
/// .add(Expr::col((Character::Table, Character::SizeW)).gt(500)),
/// "large"
/// )
/// .case(
/// Cond::any()
/// .add(Expr::col((Character::Table, Character::FontSize)).between(24,48))
/// .add(Expr::col((Character::Table, Character::SizeW)).between(300,500)),
/// "medium"
/// )
/// .finally("small"),
/// Alias::new("char_size"))
/// .from(Character::Table)
/// .to_owned();
///
/// assert_eq!(
/// query.to_string(PostgresQueryBuilder),
/// [
/// r#"SELECT"#,
/// r#"(CASE WHEN ("character"."font_size" > 48 OR "character"."size_w" > 500) THEN 'large'"#,
/// r#"WHEN (("character"."font_size" BETWEEN 24 AND 48) OR ("character"."size_w" BETWEEN 300 AND 500)) THEN 'medium'"#,
/// r#"ELSE 'small' END) AS "char_size""#,
/// r#"FROM "character""#
/// ]
/// .join(" ")
/// );
/// ```
pub fn finally<E>(mut self, r#else: E) -> Self
where
E: Into<SimpleExpr>,
{
self.r#else = Some(r#else.into());
self
}
}
#[allow(clippy::from_over_into)]
impl Into<SimpleExpr> for CaseStatement {
fn into(self) -> SimpleExpr {
SimpleExpr::Case(Box::new(self))
}
}
#[cfg(test)]
mod test {
use crate::*;
#[test]
#[cfg(feature = "backend-postgres")]
fn test_where_case_eq() {
let case_statement: SimpleExpr = Expr::case(
Expr::col(Alias::new("col")).lt(5),
Expr::col(Alias::new("othercol")),
)
.finally(Expr::col(Alias::new("finalcol")))
.into();
let result = Query::select()
.column(Asterisk)
.from(Alias::new("tbl"))
.and_where(case_statement.eq(10))
.to_string(PostgresQueryBuilder);
assert_eq!(
result,
r#"SELECT * FROM "tbl" WHERE (CASE WHEN ("col" < 5) THEN "othercol" ELSE "finalcol" END) = 10"#
);
}
}