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::Default.as_str(), "DEFAULT");
344 assert_eq!(Keyword::CurrentTimestamp.as_str(), "CURRENT_TIMESTAMP");
345 assert_eq!(Keyword::CurrentDate.as_str(), "CURRENT_DATE");
346 assert_eq!(Keyword::CurrentTime.as_str(), "CURRENT_TIME");
347 }
348
349 #[rstest]
350 fn test_simple_expr_from_float_and_keyword() {
351 let float: SimpleExpr = 1.5f32.into();
352 assert!(
353 matches!(float, SimpleExpr::Value(Value::Float(Some(value))) if (value - 1.5).abs() < f32::EPSILON)
354 );
355 let double: SimpleExpr = 2.5f64.into();
356 assert!(
357 matches!(double, SimpleExpr::Value(Value::Double(Some(value))) if (value - 2.5).abs() < f64::EPSILON)
358 );
359 let keyword: SimpleExpr = Keyword::Default.into();
360 assert!(matches!(keyword, SimpleExpr::Constant(Keyword::Default)));
361 }
362
363 #[rstest]
364 fn test_case_statement_builder() {
365 let case = CaseStatement::new()
366 .when(true, 1i32)
367 .when(false, 0i32)
368 .else_result(-1i32);
369
370 assert_eq!(case.when_clauses.len(), 2);
371 assert!(case.else_clause.is_some());
372 }
373
374 #[rstest]
375 fn test_simple_expr_binary() {
376 let left = SimpleExpr::Column(ColumnRef::column("age"));
377 let right = SimpleExpr::Value(Value::Int(Some(18)));
378 let binary =
379 SimpleExpr::Binary(Box::new(left), BinOper::GreaterThanOrEqual, Box::new(right));
380
381 assert!(matches!(
382 binary,
383 SimpleExpr::Binary(_, BinOper::GreaterThanOrEqual, _)
384 ));
385 }
386
387 #[rstest]
388 fn test_simple_expr_unary() {
389 let inner = SimpleExpr::Value(Value::Bool(Some(true)));
390 let unary = SimpleExpr::Unary(UnOper::Not, Box::new(inner));
391
392 assert!(matches!(unary, SimpleExpr::Unary(UnOper::Not, _)));
393 }
394}