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