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, PartialEq)]
126pub enum Expr {
127 Column(ColumnRef),
128 Value(SqlValue),
129 Binary {
130 left: Box<Expr>,
131 op: BinaryOp,
132 right: Box<Expr>,
133 },
134 Unary {
135 op: UnaryOp,
136 expr: Box<Expr>,
137 },
138 Function {
139 name: String,
140 args: Vec<Expr>,
141 },
142}
143
144impl Expr {
145 pub fn column<E: Entity>(column: EntityColumn<E>) -> Self {
146 Self::Column(column.into())
147 }
148
149 pub fn column_as<E: Entity>(column: EntityColumn<E>, alias: &'static str) -> Self {
150 Self::Column(ColumnRef::for_entity_column_as(column, alias))
151 }
152
153 pub const fn value(value: SqlValue) -> Self {
154 Self::Value(value)
155 }
156
157 pub fn binary(left: Expr, op: BinaryOp, right: Expr) -> Self {
158 Self::Binary {
159 left: Box::new(left),
160 op,
161 right: Box::new(right),
162 }
163 }
164
165 pub fn unary(op: UnaryOp, expr: Expr) -> Self {
166 Self::Unary {
167 op,
168 expr: Box::new(expr),
169 }
170 }
171
172 pub fn function(name: impl Into<String>, args: Vec<Expr>) -> Self {
173 Self::Function {
174 name: name.into(),
175 args,
176 }
177 }
178}
179
180impl<E: Entity> From<EntityColumn<E>> for Expr {
181 fn from(value: EntityColumn<E>) -> Self {
182 Self::column(value)
183 }
184}
185
186impl From<SqlValue> for Expr {
187 fn from(value: SqlValue) -> Self {
188 Self::Value(value)
189 }
190}