1use crate::types::{BinOper, ColumnRef, DynIden, UnOper, WindowStatement};
8use crate::value::Value;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum SubQueryOper {
15 Exists,
17 NotExists,
19 In,
21 NotIn,
23 All,
25 Any,
27 Some,
29}
30
31#[derive(Debug, Clone)]
55#[non_exhaustive]
56pub enum SimpleExpr {
57 Column(ColumnRef),
59
60 TableColumn(DynIden, DynIden),
62
63 Value(Value),
65
66 Unary(UnOper, Box<SimpleExpr>),
68
69 Binary(Box<SimpleExpr>, BinOper, Box<SimpleExpr>),
71
72 FunctionCall(DynIden, Vec<SimpleExpr>),
74
75 SubQuery(Option<SubQueryOper>, Box<crate::query::SelectStatement>),
81
82 Tuple(Vec<SimpleExpr>),
84
85 Custom(String),
92
93 CustomWithExpr(String, Vec<SimpleExpr>),
95
96 Constant(Keyword),
98
99 Asterisk,
101
102 Case(Box<CaseStatement>),
104
105 AsEnum(DynIden, Box<SimpleExpr>),
107
108 ExprAlias(Box<SimpleExpr>, DynIden),
110
111 Cast(Box<SimpleExpr>, DynIden),
113
114 Window {
121 func: Box<SimpleExpr>,
123 window: WindowStatement,
125 },
126
127 WindowNamed {
135 func: Box<SimpleExpr>,
137 name: DynIden,
139 },
140}
141
142#[derive(Debug, Clone, Copy, PartialEq, Eq)]
144pub enum Keyword {
145 Null,
147 True,
149 False,
151 Default,
153 CurrentTimestamp,
155 CurrentDate,
157 CurrentTime,
159}
160
161impl Keyword {
162 #[must_use]
164 pub fn as_str(&self) -> &'static str {
165 match self {
166 Self::Null => "NULL",
167 Self::True => "TRUE",
168 Self::False => "FALSE",
169 Self::Default => "DEFAULT",
170 Self::CurrentTimestamp => "CURRENT_TIMESTAMP",
171 Self::CurrentDate => "CURRENT_DATE",
172 Self::CurrentTime => "CURRENT_TIME",
173 }
174 }
175}
176
177#[derive(Debug, Clone, Default)]
188pub struct CaseStatement {
189 pub when_clauses: Vec<(SimpleExpr, SimpleExpr)>,
191 pub else_clause: Option<SimpleExpr>,
193}
194
195impl CaseStatement {
196 pub fn new() -> Self {
198 Self::default()
199 }
200
201 #[must_use]
203 pub fn when<C, R>(mut self, condition: C, result: R) -> Self
204 where
205 C: Into<SimpleExpr>,
206 R: Into<SimpleExpr>,
207 {
208 self.when_clauses.push((condition.into(), result.into()));
209 self
210 }
211
212 #[must_use]
214 pub fn else_result<E>(mut self, result: E) -> Self
215 where
216 E: Into<SimpleExpr>,
217 {
218 self.else_clause = Some(result.into());
219 self
220 }
221}
222
223impl SimpleExpr {
224 pub fn binary(self, op: crate::types::BinOper, right: SimpleExpr) -> Self {
226 Self::Binary(Box::new(self), op, Box::new(right))
227 }
228}
229
230impl From<Value> for SimpleExpr {
233 fn from(v: Value) -> Self {
234 Self::Value(v)
235 }
236}
237
238impl From<ColumnRef> for SimpleExpr {
239 fn from(c: ColumnRef) -> Self {
240 Self::Column(c)
241 }
242}
243
244impl From<bool> for SimpleExpr {
245 fn from(b: bool) -> Self {
246 Self::Value(Value::Bool(Some(b)))
247 }
248}
249
250impl From<i32> for SimpleExpr {
251 fn from(i: i32) -> Self {
252 Self::Value(Value::Int(Some(i)))
253 }
254}
255
256impl From<i64> for SimpleExpr {
257 fn from(i: i64) -> Self {
258 Self::Value(Value::BigInt(Some(i)))
259 }
260}
261
262impl From<f32> for SimpleExpr {
263 fn from(f: f32) -> Self {
264 Self::Value(Value::Float(Some(f)))
265 }
266}
267
268impl From<f64> for SimpleExpr {
269 fn from(f: f64) -> Self {
270 Self::Value(Value::Double(Some(f)))
271 }
272}
273
274impl From<&str> for SimpleExpr {
275 fn from(s: &str) -> Self {
276 Self::Value(Value::String(Some(Box::new(s.to_string()))))
277 }
278}
279
280impl From<String> for SimpleExpr {
281 fn from(s: String) -> Self {
282 Self::Value(Value::String(Some(Box::new(s))))
283 }
284}
285
286impl From<Keyword> for SimpleExpr {
287 fn from(k: Keyword) -> Self {
288 Self::Constant(k)
289 }
290}
291
292impl From<CaseStatement> for SimpleExpr {
293 fn from(case: CaseStatement) -> Self {
294 Self::Case(Box::new(case))
295 }
296}
297
298#[cfg(test)]
299mod tests {
300 use super::*;
301 use rstest::rstest;
302
303 #[rstest]
304 fn test_simple_expr_from_value() {
305 let expr: SimpleExpr = Value::Int(Some(42)).into();
306 assert!(matches!(expr, SimpleExpr::Value(Value::Int(Some(42)))));
307 }
308
309 #[rstest]
310 fn test_simple_expr_from_bool() {
311 let expr: SimpleExpr = true.into();
312 assert!(matches!(expr, SimpleExpr::Value(Value::Bool(Some(true)))));
313 }
314
315 #[rstest]
316 fn test_simple_expr_from_i32() {
317 let expr: SimpleExpr = 42i32.into();
318 assert!(matches!(expr, SimpleExpr::Value(Value::Int(Some(42)))));
319 }
320
321 #[rstest]
322 fn test_simple_expr_from_str() {
323 let expr: SimpleExpr = "hello".into();
324 if let SimpleExpr::Value(Value::String(Some(s))) = expr {
325 assert_eq!(*s, "hello");
326 } else {
327 panic!("Expected String value");
328 }
329 }
330
331 #[rstest]
332 fn test_simple_expr_column() {
333 let col = ColumnRef::column("name");
334 let expr: SimpleExpr = col.into();
335 assert!(matches!(expr, SimpleExpr::Column(_)));
336 }
337
338 #[rstest]
339 fn test_keyword_as_str() {
340 assert_eq!(Keyword::Null.as_str(), "NULL");
341 assert_eq!(Keyword::True.as_str(), "TRUE");
342 assert_eq!(Keyword::False.as_str(), "FALSE");
343 assert_eq!(Keyword::CurrentTimestamp.as_str(), "CURRENT_TIMESTAMP");
344 }
345
346 #[rstest]
347 fn test_case_statement_builder() {
348 let case = CaseStatement::new()
349 .when(true, 1i32)
350 .when(false, 0i32)
351 .else_result(-1i32);
352
353 assert_eq!(case.when_clauses.len(), 2);
354 assert!(case.else_clause.is_some());
355 }
356
357 #[rstest]
358 fn test_simple_expr_binary() {
359 let left = SimpleExpr::Column(ColumnRef::column("age"));
360 let right = SimpleExpr::Value(Value::Int(Some(18)));
361 let binary =
362 SimpleExpr::Binary(Box::new(left), BinOper::GreaterThanOrEqual, Box::new(right));
363
364 assert!(matches!(
365 binary,
366 SimpleExpr::Binary(_, BinOper::GreaterThanOrEqual, _)
367 ));
368 }
369
370 #[rstest]
371 fn test_simple_expr_unary() {
372 let inner = SimpleExpr::Value(Value::Bool(Some(true)));
373 let unary = SimpleExpr::Unary(UnOper::Not, Box::new(inner));
374
375 assert!(matches!(unary, SimpleExpr::Unary(UnOper::Not, _)));
376 }
377}