1use std::marker::PhantomData;
2
3use crate::value::{IntoSqlValue, Value};
4
5mod comparison {
6 pub trait Sealed<Rhs> {}
7
8 impl<T> Sealed<T> for T {}
9 impl<T> Sealed<Option<T>> for T {}
10 impl<T> Sealed<T> for Option<T> {}
11}
12
13mod numeric {
14 pub trait Sealed {}
15
16 macro_rules! numeric_types {
17 ($($value:ty),+ $(,)?) => {
18 $(impl Sealed for $value {})+
19 };
20 }
21
22 numeric_types!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64);
23
24 #[cfg(feature = "decimal")]
25 impl Sealed for rust_decimal::Decimal {}
26
27 impl<T: Sealed> Sealed for Option<T> {}
28}
29
30pub trait SqlComparable<Rhs>: comparison::Sealed<Rhs> {}
33
34impl<T> SqlComparable<T> for T {}
35impl<T> SqlComparable<Option<T>> for T {}
36impl<T> SqlComparable<T> for Option<T> {}
37
38pub trait SqlNumeric: numeric::Sealed {}
40
41macro_rules! numeric_types {
42 ($($value:ty),+ $(,)?) => {
43 $(impl SqlNumeric for $value {})+
44 };
45}
46
47numeric_types!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64);
48
49#[cfg(feature = "decimal")]
50impl SqlNumeric for rust_decimal::Decimal {}
51
52impl<T: SqlNumeric> SqlNumeric for Option<T> {}
53
54#[derive(Clone, Debug)]
55pub struct SelectSubquery(pub(crate) Box<crate::ast::SelectNode>);
56
57#[derive(Clone, Debug)]
58pub enum Expression {
59 Column {
60 table: &'static str,
61 name: &'static str,
62 },
63 Value(Value),
64 Subquery(SelectSubquery),
65 Function {
66 name: &'static str,
67 arguments: Vec<Expression>,
68 },
69 Coalesce(Vec<Expression>),
70 Least(Vec<Expression>),
71 Cast {
72 expression: Box<Expression>,
73 sql_type: &'static str,
74 },
75 Alias {
76 expression: Box<Expression>,
77 alias: &'static str,
78 },
79 Wildcard,
80 Window {
81 expression: Box<Expression>,
82 partition_by: Vec<Expression>,
83 order_by: Vec<(Expression, OrderDirection)>,
84 frame: Option<WindowFrame>,
85 },
86 Binary {
87 left: Box<Expression>,
88 operator: BinaryOperator,
89 right: Box<Expression>,
90 },
91 Unary {
92 operator: UnaryOperator,
93 expression: Box<Expression>,
94 },
95 And(Vec<Expression>),
96 Or(Vec<Expression>),
97}
98
99impl Expression {
100 pub fn and(self, other: Expression) -> Self {
101 match self {
102 Self::And(mut expressions) => {
103 expressions.push(other);
104 Self::And(expressions)
105 }
106 expression => Self::And(vec![expression, other]),
107 }
108 }
109
110 pub fn or(self, other: Expression) -> Self {
111 match self {
112 Self::Or(mut expressions) => {
113 expressions.push(other);
114 Self::Or(expressions)
115 }
116 expression => Self::Or(vec![expression, other]),
117 }
118 }
119}
120
121pub fn not(expression: Expression) -> Expression {
123 Expression::Unary {
124 operator: UnaryOperator::Not,
125 expression: Box::new(expression),
126 }
127}
128
129#[derive(Clone, Copy, Debug)]
130pub enum BinaryOperator {
131 Eq,
132 NotEq,
133 GreaterThan,
134 GreaterThanOrEq,
135 LessThan,
136 LessThanOrEq,
137 Like,
138 In,
139 Is,
140 IsNot,
141 Add,
142}
143
144#[derive(Clone, Copy, Debug)]
145pub enum UnaryOperator {
146 IsNull,
147 IsNotNull,
148 Not,
149 Exists,
150}
151
152#[derive(Clone, Copy, Debug, PartialEq, Eq)]
153pub enum OrderDirection {
154 Asc,
155 Desc,
156}
157
158#[derive(Clone, Copy, Debug, PartialEq, Eq)]
159pub enum WindowFrameUnits {
160 Rows,
161 Range,
162 Groups,
163}
164
165#[derive(Clone, Copy, Debug, PartialEq, Eq)]
166pub enum WindowBoundary {
167 UnboundedPreceding,
168 Preceding(u64),
169 CurrentRow,
170 Following(u64),
171 UnboundedFollowing,
172}
173
174#[derive(Clone, Copy, Debug, PartialEq, Eq)]
175pub struct WindowFrame {
176 pub units: WindowFrameUnits,
177 pub start: WindowBoundary,
178 pub end: WindowBoundary,
179}
180
181#[derive(Debug)]
182pub struct Column<T, V> {
183 table: &'static str,
184 name: &'static str,
185 marker: PhantomData<fn() -> (T, V)>,
186}
187
188impl<T, V> Clone for Column<T, V> {
189 fn clone(&self) -> Self {
190 *self
191 }
192}
193
194impl<T, V> Copy for Column<T, V> {}
195
196impl<T, V> Column<T, V> {
197 pub const fn new(table: &'static str, name: &'static str) -> Self {
198 Self {
199 table,
200 name,
201 marker: PhantomData,
202 }
203 }
204
205 pub const fn table_name(self) -> &'static str {
206 self.table
207 }
208
209 pub const fn name(self) -> &'static str {
210 self.name
211 }
212
213 pub fn expression(self) -> Expression {
214 Expression::Column {
215 table: self.table,
216 name: self.name,
217 }
218 }
219
220 pub fn eq(self, value: impl IntoSqlValue<V>) -> Expression {
221 self.compare(
222 BinaryOperator::Eq,
223 Expression::Value(value.into_sql_value()),
224 )
225 }
226
227 pub fn ne(self, value: impl IntoSqlValue<V>) -> Expression {
228 self.compare(
229 BinaryOperator::NotEq,
230 Expression::Value(value.into_sql_value()),
231 )
232 }
233
234 pub fn gt(self, value: impl IntoSqlValue<V>) -> Expression {
235 self.compare(
236 BinaryOperator::GreaterThan,
237 Expression::Value(value.into_sql_value()),
238 )
239 }
240
241 pub fn gte(self, value: impl IntoSqlValue<V>) -> Expression {
242 self.compare(
243 BinaryOperator::GreaterThanOrEq,
244 Expression::Value(value.into_sql_value()),
245 )
246 }
247
248 pub fn lt(self, value: impl IntoSqlValue<V>) -> Expression {
249 self.compare(
250 BinaryOperator::LessThan,
251 Expression::Value(value.into_sql_value()),
252 )
253 }
254
255 pub fn lte(self, value: impl IntoSqlValue<V>) -> Expression {
256 self.compare(
257 BinaryOperator::LessThanOrEq,
258 Expression::Value(value.into_sql_value()),
259 )
260 }
261
262 pub fn like(self, value: impl IntoSqlValue<V>) -> Expression {
263 self.compare(
264 BinaryOperator::Like,
265 Expression::Value(value.into_sql_value()),
266 )
267 }
268
269 pub fn eq_column<OtherTable, OtherValue>(
270 self,
271 other: Column<OtherTable, OtherValue>,
272 ) -> Expression
273 where
274 V: SqlComparable<OtherValue>,
275 {
276 self.compare(BinaryOperator::Eq, other.expression())
277 }
278
279 pub fn ne_column<OtherTable, OtherValue>(
280 self,
281 other: Column<OtherTable, OtherValue>,
282 ) -> Expression
283 where
284 V: SqlComparable<OtherValue>,
285 {
286 self.compare(BinaryOperator::NotEq, other.expression())
287 }
288
289 pub fn gt_column<OtherTable, OtherValue>(
290 self,
291 other: Column<OtherTable, OtherValue>,
292 ) -> Expression
293 where
294 V: SqlComparable<OtherValue>,
295 {
296 self.compare(BinaryOperator::GreaterThan, other.expression())
297 }
298
299 pub fn gte_column<OtherTable, OtherValue>(
300 self,
301 other: Column<OtherTable, OtherValue>,
302 ) -> Expression
303 where
304 V: SqlComparable<OtherValue>,
305 {
306 self.compare(BinaryOperator::GreaterThanOrEq, other.expression())
307 }
308
309 pub fn lt_column<OtherTable, OtherValue>(
310 self,
311 other: Column<OtherTable, OtherValue>,
312 ) -> Expression
313 where
314 V: SqlComparable<OtherValue>,
315 {
316 self.compare(BinaryOperator::LessThan, other.expression())
317 }
318
319 pub fn lte_column<OtherTable, OtherValue>(
320 self,
321 other: Column<OtherTable, OtherValue>,
322 ) -> Expression
323 where
324 V: SqlComparable<OtherValue>,
325 {
326 self.compare(BinaryOperator::LessThanOrEq, other.expression())
327 }
328
329 pub fn eq_subquery<Source: crate::Table>(
330 self,
331 query: crate::query::SelectQuery<Source, V>,
332 ) -> Expression {
333 self.compare(
334 BinaryOperator::Eq,
335 Expression::Subquery(SelectSubquery(Box::new(query.into_node()))),
336 )
337 }
338
339 pub fn in_subquery<Source: crate::Table>(
340 self,
341 query: crate::query::SelectQuery<Source, V>,
342 ) -> Expression {
343 self.compare(
344 BinaryOperator::In,
345 Expression::Subquery(SelectSubquery(Box::new(query.into_node()))),
346 )
347 }
348
349 pub fn is_null(self) -> Expression {
350 Expression::Unary {
351 operator: UnaryOperator::IsNull,
352 expression: Box::new(self.expression()),
353 }
354 }
355
356 pub fn is_not_null(self) -> Expression {
357 Expression::Unary {
358 operator: UnaryOperator::IsNotNull,
359 expression: Box::new(self.expression()),
360 }
361 }
362
363 fn compare(self, operator: BinaryOperator, right: Expression) -> Expression {
364 Expression::Binary {
365 left: Box::new(self.expression()),
366 operator,
367 right: Box::new(right),
368 }
369 }
370}
371
372impl<T, V, Rhs> std::ops::Add<Rhs> for Column<T, V>
373where
374 V: SqlNumeric,
375 Rhs: IntoSqlValue<V>,
376{
377 type Output = crate::TypedExpression<V>;
378
379 fn add(self, value: Rhs) -> Self::Output {
380 crate::TypedExpression::new(Expression::Binary {
381 left: Box::new(self.expression()),
382 operator: BinaryOperator::Add,
383 right: Box::new(Expression::Value(value.into_sql_value())),
384 })
385 }
386}
387
388pub fn exists<Source: crate::Table, Output>(
389 query: crate::query::SelectQuery<Source, Output>,
390) -> Expression {
391 Expression::Unary {
392 operator: UnaryOperator::Exists,
393 expression: Box::new(Expression::Subquery(SelectSubquery(Box::new(
394 query.into_node(),
395 )))),
396 }
397}
398
399pub trait Selection {
400 type Output;
401 fn expressions(self) -> Vec<Expression>;
402}
403
404pub struct AliasedSelection<S> {
405 selection: S,
406 alias: &'static str,
407}
408
409pub trait SelectionExt: Selection + Sized {
410 fn alias(self, alias: &'static str) -> AliasedSelection<Self> {
411 AliasedSelection {
412 selection: self,
413 alias,
414 }
415 }
416}
417
418impl<T, V> SelectionExt for Column<T, V> {}
419
420impl<S: Selection> Selection for AliasedSelection<S> {
421 type Output = S::Output;
422
423 fn expressions(self) -> Vec<Expression> {
424 self.selection
425 .expressions()
426 .into_iter()
427 .map(|expression| Expression::Alias {
428 expression: Box::new(expression),
429 alias: self.alias,
430 })
431 .collect()
432 }
433}
434
435impl<T, V> Selection for Column<T, V> {
436 type Output = V;
437
438 fn expressions(self) -> Vec<Expression> {
439 vec![self.expression()]
440 }
441}
442
443macro_rules! tuple_selection {
444 ($($name:ident),+ $(,)?) => {
445 impl<$($name),+> Selection for ($($name,)+)
446 where
447 $($name: Selection,)+
448 {
449 type Output = ($($name::Output,)+);
450
451 #[allow(non_snake_case)]
452 fn expressions(self) -> Vec<Expression> {
453 let ($($name,)+) = self;
454 let mut expressions = Vec::new();
455 $(expressions.extend($name.expressions());)+
456 expressions
457 }
458 }
459 };
460}
461
462tuple_selection!(A, B);
463tuple_selection!(A, B, C);
464tuple_selection!(A, B, C, D);
465tuple_selection!(A, B, C, D, E);
466tuple_selection!(A, B, C, D, E, F);
467tuple_selection!(A, B, C, D, E, F, G);
468tuple_selection!(A, B, C, D, E, F, G, H);