siderite_orm/expr/
functions.rs1use super::Expr;
11use crate::types::SqlType;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum Function {
16 Lower,
18 Upper,
20 Length,
22 Coalesce,
24 Concat,
26 Substr,
28 Replace,
30 Trim,
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40pub enum DatePart {
41 Year,
43 Month,
45 Day,
47 Week,
49 Quarter,
51 Hour,
53 Minute,
55 Second,
57 Date,
59}
60
61fn call(func: Function, args: impl IntoIterator<Item = Expr>) -> Expr {
62 Expr::Func {
63 func,
64 args: args.into_iter().collect(),
65 }
66}
67
68pub fn lower(expr: impl Into<Expr>) -> Expr {
70 call(Function::Lower, [expr.into()])
71}
72
73pub fn upper(expr: impl Into<Expr>) -> Expr {
75 call(Function::Upper, [expr.into()])
76}
77
78pub fn length(expr: impl Into<Expr>) -> Expr {
80 call(Function::Length, [expr.into()])
81}
82
83pub fn coalesce<E: Into<Expr>>(exprs: impl IntoIterator<Item = E>) -> Expr {
85 call(Function::Coalesce, exprs.into_iter().map(Into::into))
86}
87
88pub fn concat<E: Into<Expr>>(exprs: impl IntoIterator<Item = E>) -> Expr {
90 call(Function::Concat, exprs.into_iter().map(Into::into))
91}
92
93pub fn substr(expr: impl Into<Expr>, start: i64, length: Option<i64>) -> Expr {
95 let mut args = vec![expr.into(), Expr::val(start)];
96 args.extend(length.map(Expr::val));
97 call(Function::Substr, args)
98}
99
100pub fn replace(expr: impl Into<Expr>, from: impl Into<String>, to: impl Into<String>) -> Expr {
102 call(
103 Function::Replace,
104 [expr.into(), Expr::val(from.into()), Expr::val(to.into())],
105 )
106}
107
108pub fn trim(expr: impl Into<Expr>) -> Expr {
110 call(Function::Trim, [expr.into()])
111}
112
113pub fn cast(expr: impl Into<Expr>, ty: SqlType) -> Expr {
115 expr.into().cast(ty)
116}
117
118pub fn case() -> CaseBuilder {
120 CaseBuilder::default()
121}
122
123#[derive(Debug, Clone, Default)]
125pub struct CaseBuilder {
126 branches: Vec<(Expr, Expr)>,
127}
128
129impl CaseBuilder {
130 #[must_use]
132 pub fn when(mut self, condition: Expr, result: impl Into<Expr>) -> Self {
133 self.branches.push((condition, result.into()));
134 self
135 }
136
137 pub fn otherwise(self, fallback: impl Into<Expr>) -> Expr {
139 Expr::Case {
140 branches: self.branches,
141 otherwise: Some(Box::new(fallback.into())),
142 }
143 }
144
145 pub fn end(self) -> Expr {
147 Expr::Case {
148 branches: self.branches,
149 otherwise: None,
150 }
151 }
152}
153
154macro_rules! date_parts {
155 ($($method:ident => $part:ident),* $(,)?) => {
156 impl Expr {$(
157 #[doc = concat!("The `", stringify!($part), "` component of a temporal expression.")]
158 pub fn $method(self) -> Expr {
159 self.date_part(DatePart::$part)
160 }
161 )*}
162 };
163}
164date_parts!(
165 year => Year, month => Month, day => Day, week => Week, quarter => Quarter,
166 hour => Hour, minute => Minute, second => Second, date => Date,
167);