Skip to main content

sql_orm_query/
expr.rs

1use sql_orm_core::{Entity, EntityColumn, SqlValue};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub struct TableRef {
5    pub schema: &'static str,
6    pub table: &'static str,
7    pub alias: Option<&'static str>,
8}
9
10impl TableRef {
11    pub const fn new(schema: &'static str, table: &'static str) -> Self {
12        Self {
13            schema,
14            table,
15            alias: None,
16        }
17    }
18
19    pub const fn with_alias(
20        schema: &'static str,
21        table: &'static str,
22        alias: &'static str,
23    ) -> Self {
24        Self {
25            schema,
26            table,
27            alias: Some(alias),
28        }
29    }
30
31    pub fn for_entity<E: Entity>() -> Self {
32        let metadata = E::metadata();
33        Self::new(metadata.schema, metadata.table)
34    }
35
36    pub fn for_entity_as<E: Entity>(alias: &'static str) -> Self {
37        let metadata = E::metadata();
38        Self::with_alias(metadata.schema, metadata.table, alias)
39    }
40
41    pub const fn as_alias(self, alias: &'static str) -> Self {
42        Self {
43            schema: self.schema,
44            table: self.table,
45            alias: Some(alias),
46        }
47    }
48
49    pub const fn without_alias(self) -> Self {
50        Self {
51            schema: self.schema,
52            table: self.table,
53            alias: None,
54        }
55    }
56
57    pub const fn reference_name(&self) -> &'static str {
58        match self.alias {
59            Some(alias) => alias,
60            None => self.table,
61        }
62    }
63}
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq)]
66pub struct ColumnRef {
67    pub table: TableRef,
68    pub rust_field: &'static str,
69    pub column_name: &'static str,
70}
71
72impl ColumnRef {
73    pub const fn new(table: TableRef, rust_field: &'static str, column_name: &'static str) -> Self {
74        Self {
75            table,
76            rust_field,
77            column_name,
78        }
79    }
80
81    pub fn for_entity_column<E: Entity>(column: EntityColumn<E>) -> Self {
82        Self::new(
83            TableRef::for_entity::<E>(),
84            column.rust_field(),
85            column.column_name(),
86        )
87    }
88
89    pub fn for_entity_column_as<E: Entity>(column: EntityColumn<E>, alias: &'static str) -> Self {
90        Self::new(
91            TableRef::for_entity_as::<E>(alias),
92            column.rust_field(),
93            column.column_name(),
94        )
95    }
96
97    pub const fn with_table_alias(self, alias: &'static str) -> Self {
98        Self {
99            table: self.table.as_alias(alias),
100            rust_field: self.rust_field,
101            column_name: self.column_name,
102        }
103    }
104}
105
106impl<E: Entity> From<EntityColumn<E>> for ColumnRef {
107    fn from(value: EntityColumn<E>) -> Self {
108        Self::for_entity_column(value)
109    }
110}
111
112#[derive(Debug, Clone, Copy, PartialEq, Eq)]
113pub enum BinaryOp {
114    Add,
115    Subtract,
116    Multiply,
117    Divide,
118}
119
120#[derive(Debug, Clone, Copy, PartialEq, Eq)]
121pub enum UnaryOp {
122    Negate,
123}
124
125#[derive(Debug, Clone, Copy, PartialEq, Eq)]
126pub enum SqlFunction {
127    Lower,
128    Upper,
129    Year,
130    Month,
131    Day,
132    Len,
133    Trim,
134}
135
136impl SqlFunction {
137    pub const fn sql_name(self) -> &'static str {
138        match self {
139            Self::Lower => "LOWER",
140            Self::Upper => "UPPER",
141            Self::Year => "YEAR",
142            Self::Month => "MONTH",
143            Self::Day => "DAY",
144            Self::Len => "LEN",
145            Self::Trim => "TRIM",
146        }
147    }
148}
149
150#[derive(Debug, Clone, PartialEq)]
151pub enum Expr {
152    Column(ColumnRef),
153    Value(SqlValue),
154    Binary {
155        left: Box<Expr>,
156        op: BinaryOp,
157        right: Box<Expr>,
158    },
159    Unary {
160        op: UnaryOp,
161        expr: Box<Expr>,
162    },
163    Function {
164        function: SqlFunction,
165        args: Vec<Expr>,
166    },
167    UnsafeFunction {
168        name: String,
169        args: Vec<Expr>,
170    },
171}
172
173impl Expr {
174    pub fn column<E: Entity>(column: EntityColumn<E>) -> Self {
175        Self::Column(column.into())
176    }
177
178    pub fn column_as<E: Entity>(column: EntityColumn<E>, alias: &'static str) -> Self {
179        Self::Column(ColumnRef::for_entity_column_as(column, alias))
180    }
181
182    pub const fn value(value: SqlValue) -> Self {
183        Self::Value(value)
184    }
185
186    pub fn binary(left: Expr, op: BinaryOp, right: Expr) -> Self {
187        Self::Binary {
188            left: Box::new(left),
189            op,
190            right: Box::new(right),
191        }
192    }
193
194    pub fn unary(op: UnaryOp, expr: Expr) -> Self {
195        Self::Unary {
196            op,
197            expr: Box::new(expr),
198        }
199    }
200
201    pub fn function(function: SqlFunction, args: Vec<Expr>) -> Self {
202        Self::Function { function, args }
203    }
204
205    pub fn unsafe_function(name: impl Into<String>, args: Vec<Expr>) -> Self {
206        Self::UnsafeFunction {
207            name: name.into(),
208            args,
209        }
210    }
211}
212
213impl<E: Entity> From<EntityColumn<E>> for Expr {
214    fn from(value: EntityColumn<E>) -> Self {
215        Self::column(value)
216    }
217}
218
219impl From<SqlValue> for Expr {
220    fn from(value: SqlValue) -> Self {
221        Self::Value(value)
222    }
223}