1#[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
2use super::compare::{JsonCompare, JsonType};
3use crate::ast::*;
4use query::SelectQuery;
5use std::borrow::Cow;
6
7#[derive(Debug, Clone, PartialEq)]
10pub struct Expression<'a> {
11 pub(crate) kind: ExpressionKind<'a>,
12 pub(crate) alias: Option<Cow<'a, str>>,
13}
14
15impl<'a> Expression<'a> {
16 pub fn kind(&self) -> &ExpressionKind<'a> {
18 &self.kind
19 }
20
21 pub fn alias(&self) -> Option<&str> {
23 self.alias.as_ref().map(|s| s.as_ref())
24 }
25
26 #[allow(dead_code)]
27 pub(crate) fn row(row: Row<'a>) -> Self {
28 Self {
29 kind: ExpressionKind::Row(row),
30 alias: None,
31 }
32 }
33
34 pub(crate) fn union(union: Union<'a>) -> Self {
35 Self::selection(SelectQuery::Union(Box::new(union)))
36 }
37
38 #[allow(dead_code)]
39 pub(crate) fn selection(selection: SelectQuery<'a>) -> Self {
40 Self {
41 kind: ExpressionKind::Selection(selection),
42 alias: None,
43 }
44 }
45
46 #[cfg(feature = "json")]
47 pub(crate) fn is_json_expr(&self) -> bool {
48 match &self.kind {
49 #[cfg(feature = "json")]
50 ExpressionKind::Parameterized(Value::Json(_)) => true,
51 #[cfg(feature = "json")]
52 ExpressionKind::Value(expr) => expr.is_json_value(),
53 #[cfg(feature = "json")]
54 ExpressionKind::Function(fun) => fun.returns_json(),
55 _ => false,
56 }
57 }
58
59 #[allow(dead_code)]
60 #[cfg(feature = "json")]
61 pub(crate) fn is_json_value(&self) -> bool {
62 match &self.kind {
63 #[cfg(feature = "json")]
64 ExpressionKind::Parameterized(Value::Json(_)) => true,
65 #[cfg(feature = "json")]
66 ExpressionKind::Value(expr) => expr.is_json_value(),
67 _ => false,
68 }
69 }
70
71 #[allow(dead_code)]
72 #[cfg(feature = "json")]
73 pub(crate) fn into_json_value(self) -> Option<serde_json::Value> {
74 match self.kind {
75 #[cfg(feature = "json")]
76 ExpressionKind::Parameterized(Value::Json(json_val)) => json_val,
77 #[cfg(feature = "json")]
78 ExpressionKind::Value(expr) => expr.into_json_value(),
79 _ => None,
80 }
81 }
82
83 #[allow(dead_code)]
84 pub(crate) fn is_fun_retuning_json(&self) -> bool {
85 match &self.kind {
86 ExpressionKind::Function(f) => f.returns_json(),
87 _ => false,
88 }
89 }
90
91 #[allow(dead_code)]
92 pub(crate) fn is_xml_value(&self) -> bool {
93 self.kind.is_xml_value()
94 }
95
96 #[allow(dead_code)]
97 pub fn is_asterisk(&self) -> bool {
98 matches!(self.kind, ExpressionKind::Asterisk(_))
99 }
100
101 #[allow(dead_code)]
102 pub(crate) fn is_row(&self) -> bool {
103 matches!(self.kind, ExpressionKind::Row(_))
104 }
105
106 #[allow(dead_code)]
107 pub(crate) fn into_row(self) -> Option<Row<'a>> {
108 match self.kind {
109 ExpressionKind::Row(row) => Some(row),
110 _ => None,
111 }
112 }
113
114 #[allow(dead_code)]
115 pub(crate) fn into_selection(self) -> Option<SelectQuery<'a>> {
116 match self.kind {
117 ExpressionKind::Selection(selection) => Some(selection),
118 _ => None,
119 }
120 }
121
122 #[allow(dead_code)]
123 pub(crate) fn into_column(self) -> Option<Column<'a>> {
124 match self.kind {
125 ExpressionKind::Column(column) => Some(*column),
126 _ => None,
127 }
128 }
129
130 #[allow(dead_code)]
131 pub(crate) fn is_selection(&self) -> bool {
132 matches!(self.kind, ExpressionKind::Selection(_))
133 }
134
135 #[allow(dead_code)]
136 pub(crate) fn is_column(&self) -> bool {
137 matches!(self.kind, ExpressionKind::Column(_))
138 }
139
140 #[cfg(feature = "mssql")]
143 pub(crate) fn convert_tuple_selects_to_ctes(self, level: &mut usize) -> (Self, Vec<CommonTableExpression<'a>>) {
144 match self.kind {
145 ExpressionKind::Selection(s) => {
146 let (selection, ctes) = s.convert_tuple_selects_to_ctes(level);
147
148 let expr = Expression {
149 kind: ExpressionKind::Selection(selection),
150 alias: self.alias,
151 };
152
153 (expr, ctes)
154 }
155 ExpressionKind::Compare(compare) => match compare.convert_tuple_select_to_cte(level) {
156 either::Either::Left(compare) => {
158 let expr = Expression {
159 kind: ExpressionKind::Compare(compare),
160 alias: self.alias,
161 };
162
163 (expr, Vec::new())
164 }
165 either::Either::Right((comp, ctes)) => {
167 let expr = Expression {
168 kind: ExpressionKind::Compare(comp),
169 alias: self.alias,
170 };
171
172 (expr, ctes)
173 }
174 },
175 ExpressionKind::ConditionTree(tree) => {
176 let (tree, ctes) = tree.convert_tuple_selects_to_ctes(level);
177
178 let expr = Expression {
179 kind: ExpressionKind::ConditionTree(tree),
180 alias: self.alias,
181 };
182
183 (expr, ctes)
184 }
185 _ => (self, Vec::new()),
186 }
187 }
188}
189
190#[derive(Debug, Clone, PartialEq)]
192pub enum ExpressionKind<'a> {
193 Parameterized(Value<'a>),
195 RawValue(Raw<'a>),
197 Column(Box<Column<'a>>),
199 Row(Row<'a>),
201 Selection(SelectQuery<'a>),
203 Function(Box<Function<'a>>),
205 Asterisk(Option<Box<Table<'a>>>),
207 Op(Box<SqlOp<'a>>),
209 Values(Box<Values<'a>>),
211 ConditionTree(ConditionTree<'a>),
213 Compare(Compare<'a>),
215 Value(Box<Expression<'a>>),
217 Default,
219}
220
221impl<'a> ExpressionKind<'a> {
222 pub(crate) fn is_xml_value(&self) -> bool {
223 match self {
224 Self::Parameterized(Value::Xml(_)) => true,
225 Self::Value(expr) => expr.is_xml_value(),
226 _ => false,
227 }
228 }
229}
230
231pub fn asterisk() -> Expression<'static> {
233 Expression {
234 kind: ExpressionKind::Asterisk(None),
235 alias: None,
236 }
237}
238
239pub fn default_value() -> Expression<'static> {
241 Expression {
242 kind: ExpressionKind::Default,
243 alias: None,
244 }
245}
246
247expression!(Row, Row);
248
249impl<'a> From<Function<'a>> for Expression<'a> {
250 fn from(f: Function<'a>) -> Self {
251 Expression {
252 kind: ExpressionKind::Function(Box::new(f)),
253 alias: None,
254 }
255 }
256}
257
258impl<'a> From<Raw<'a>> for Expression<'a> {
259 fn from(r: Raw<'a>) -> Self {
260 Expression {
261 kind: ExpressionKind::RawValue(r),
262 alias: None,
263 }
264 }
265}
266
267impl<'a> From<Values<'a>> for Expression<'a> {
268 fn from(p: Values<'a>) -> Self {
269 Expression {
270 kind: ExpressionKind::Values(Box::new(p)),
271 alias: None,
272 }
273 }
274}
275
276impl<'a> From<SqlOp<'a>> for Expression<'a> {
277 fn from(p: SqlOp<'a>) -> Self {
278 Expression {
279 kind: ExpressionKind::Op(Box::new(p)),
280 alias: None,
281 }
282 }
283}
284
285impl<'a, T> From<T> for Expression<'a>
286where
287 T: Into<Value<'a>>,
288{
289 fn from(p: T) -> Self {
290 Expression {
291 kind: ExpressionKind::Parameterized(p.into()),
292 alias: None,
293 }
294 }
295}
296
297impl<'a, T> From<Vec<T>> for Expression<'a>
298where
299 T: Into<Expression<'a>>,
300{
301 fn from(v: Vec<T>) -> Self {
302 let row: Row<'a> = v.into();
303 row.into()
304 }
305}
306
307impl<'a> From<ExpressionKind<'a>> for Expression<'a> {
308 fn from(kind: ExpressionKind<'a>) -> Self {
309 Self { kind, alias: None }
310 }
311}
312
313impl<'a> Aliasable<'a> for Expression<'a> {
314 type Target = Expression<'a>;
315
316 fn alias<T>(mut self, alias: T) -> Self::Target
317 where
318 T: Into<Cow<'a, str>>,
319 {
320 self.alias = Some(alias.into());
321 self
322 }
323}
324
325impl<'a> Comparable<'a> for Expression<'a> {
326 fn equals<T>(self, comparison: T) -> Compare<'a>
327 where
328 T: Into<Expression<'a>>,
329 {
330 Compare::Equals(Box::new(self), Box::new(comparison.into()))
331 }
332
333 fn not_equals<T>(self, comparison: T) -> Compare<'a>
334 where
335 T: Into<Expression<'a>>,
336 {
337 Compare::NotEquals(Box::new(self), Box::new(comparison.into()))
338 }
339
340 fn less_than<T>(self, comparison: T) -> Compare<'a>
341 where
342 T: Into<Expression<'a>>,
343 {
344 Compare::LessThan(Box::new(self), Box::new(comparison.into()))
345 }
346
347 fn less_than_or_equals<T>(self, comparison: T) -> Compare<'a>
348 where
349 T: Into<Expression<'a>>,
350 {
351 Compare::LessThanOrEquals(Box::new(self), Box::new(comparison.into()))
352 }
353
354 fn greater_than<T>(self, comparison: T) -> Compare<'a>
355 where
356 T: Into<Expression<'a>>,
357 {
358 Compare::GreaterThan(Box::new(self), Box::new(comparison.into()))
359 }
360
361 fn greater_than_or_equals<T>(self, comparison: T) -> Compare<'a>
362 where
363 T: Into<Expression<'a>>,
364 {
365 Compare::GreaterThanOrEquals(Box::new(self), Box::new(comparison.into()))
366 }
367
368 fn in_selection<T>(self, selection: T) -> Compare<'a>
369 where
370 T: Into<Expression<'a>>,
371 {
372 Compare::In(Box::new(self), Box::new(selection.into()))
373 }
374
375 fn not_in_selection<T>(self, selection: T) -> Compare<'a>
376 where
377 T: Into<Expression<'a>>,
378 {
379 Compare::NotIn(Box::new(self), Box::new(selection.into()))
380 }
381
382 fn like<T>(self, pattern: T) -> Compare<'a>
383 where
384 T: Into<Expression<'a>>,
385 {
386 Compare::Like(Box::new(self), Box::new(pattern.into()))
387 }
388
389 fn not_like<T>(self, pattern: T) -> Compare<'a>
390 where
391 T: Into<Expression<'a>>,
392 {
393 Compare::NotLike(Box::new(self), Box::new(pattern.into()))
394 }
395
396 #[allow(clippy::wrong_self_convention)]
397 fn is_null(self) -> Compare<'a> {
398 Compare::Null(Box::new(self))
399 }
400
401 #[allow(clippy::wrong_self_convention)]
402 fn is_not_null(self) -> Compare<'a> {
403 Compare::NotNull(Box::new(self))
404 }
405
406 fn between<T, V>(self, left: T, right: V) -> Compare<'a>
407 where
408 T: Into<Expression<'a>>,
409 V: Into<Expression<'a>>,
410 {
411 Compare::Between(Box::new(self), Box::new(left.into()), Box::new(right.into()))
412 }
413
414 fn not_between<T, V>(self, left: T, right: V) -> Compare<'a>
415 where
416 T: Into<Expression<'a>>,
417 V: Into<Expression<'a>>,
418 {
419 Compare::NotBetween(Box::new(self), Box::new(left.into()), Box::new(right.into()))
420 }
421
422 fn compare_raw<T, V>(self, raw_comparator: T, right: V) -> Compare<'a>
423 where
424 T: Into<Cow<'a, str>>,
425 V: Into<Expression<'a>>,
426 {
427 Compare::Raw(Box::new(self), raw_comparator.into(), Box::new(right.into()))
428 }
429
430 #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
431 fn json_array_contains<T>(self, item: T) -> Compare<'a>
432 where
433 T: Into<Expression<'a>>,
434 {
435 Compare::JsonCompare(JsonCompare::ArrayContains(Box::new(self), Box::new(item.into())))
436 }
437
438 #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
439 fn json_array_not_contains<T>(self, item: T) -> Compare<'a>
440 where
441 T: Into<Expression<'a>>,
442 {
443 Compare::JsonCompare(JsonCompare::ArrayNotContains(Box::new(self), Box::new(item.into())))
444 }
445
446 #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
447 fn json_array_begins_with<T>(self, item: T) -> Compare<'a>
448 where
449 T: Into<Expression<'a>>,
450 {
451 let array_starts_with: Expression = json_extract_first_array_elem(self).into();
452
453 Compare::Equals(Box::new(array_starts_with), Box::new(item.into()))
454 }
455
456 #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
457 fn json_array_not_begins_with<T>(self, item: T) -> Compare<'a>
458 where
459 T: Into<Expression<'a>>,
460 {
461 let array_starts_with: Expression = json_extract_first_array_elem(self).into();
462
463 Compare::NotEquals(Box::new(array_starts_with), Box::new(item.into()))
464 }
465
466 #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
467 fn json_array_ends_into<T>(self, item: T) -> Compare<'a>
468 where
469 T: Into<Expression<'a>>,
470 {
471 let array_ends_into: Expression = json_extract_last_array_elem(self).into();
472
473 Compare::Equals(Box::new(array_ends_into), Box::new(item.into()))
474 }
475
476 #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
477 fn json_array_not_ends_into<T>(self, item: T) -> Compare<'a>
478 where
479 T: Into<Expression<'a>>,
480 {
481 let array_ends_into: Expression = json_extract_last_array_elem(self).into();
482
483 Compare::NotEquals(Box::new(array_ends_into), Box::new(item.into()))
484 }
485
486 #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
487 fn json_type_equals<T>(self, json_type: T) -> Compare<'a>
488 where
489 T: Into<JsonType<'a>>,
490 {
491 Compare::JsonCompare(JsonCompare::TypeEquals(Box::new(self), json_type.into()))
492 }
493
494 #[cfg(all(feature = "json", any(feature = "postgresql", feature = "mysql")))]
495 fn json_type_not_equals<T>(self, json_type: T) -> Compare<'a>
496 where
497 T: Into<JsonType<'a>>,
498 {
499 Compare::JsonCompare(JsonCompare::TypeNotEquals(Box::new(self), json_type.into()))
500 }
501
502 #[cfg(feature = "postgresql")]
503 fn matches<T>(self, query: T) -> Compare<'a>
504 where
505 T: Into<Cow<'a, str>>,
506 {
507 Compare::Matches(Box::new(self), query.into())
508 }
509
510 #[cfg(feature = "postgresql")]
511 fn not_matches<T>(self, query: T) -> Compare<'a>
512 where
513 T: Into<Cow<'a, str>>,
514 {
515 Compare::NotMatches(Box::new(self), query.into())
516 }
517
518 #[cfg(feature = "postgresql")]
519 fn any(self) -> Compare<'a> {
520 Compare::Any(Box::new(self))
521 }
522
523 #[cfg(feature = "postgresql")]
524 fn all(self) -> Compare<'a> {
525 Compare::All(Box::new(self))
526 }
527}