1use std::{fmt::Debug, marker::PhantomData, ops::Deref};
2
3use ref_cast::RefCast;
4use sea_query::{Alias, SimpleExpr};
5
6use crate::{
7 Expr, IntoExpr, LocalClient, Table,
8 alias::{Field, MyAlias},
9 value::{MyTyp, Typed, ValueBuilder},
10};
11
12pub struct Col<T, X> {
13 pub(crate) _p: PhantomData<T>,
14 pub(crate) field: Field,
15 pub(crate) inner: X,
16}
17
18impl<T, X: Clone> Clone for Col<T, X> {
19 fn clone(&self) -> Self {
20 Self {
21 _p: self._p,
22 field: self.field,
23 inner: self.inner.clone(),
24 }
25 }
26}
27
28impl<T, X: Copy> Copy for Col<T, X> {}
29
30impl<T, X> Col<T, X> {
31 pub fn new(key: &'static str, x: X) -> Self {
32 Self {
33 _p: PhantomData,
34 field: Field::Str(key),
35 inner: x,
36 }
37 }
38}
39
40impl<T: MyTyp, P: Typed<Typ: Table>> Typed for Col<T, P> {
41 type Typ = T;
42 fn build_expr(&self, b: ValueBuilder) -> SimpleExpr {
43 sea_query::Expr::col((self.inner.build_table(b), self.field)).into()
44 }
45}
46
47pub(crate) struct Join<T> {
51 pub(crate) table: MyAlias,
52 pub(crate) _p: PhantomData<T>,
53}
54
55impl<T> Join<T> {
56 pub(crate) fn new(table: MyAlias) -> Self {
57 Self {
58 table,
59 _p: PhantomData,
60 }
61 }
62}
63
64impl<T> Clone for Join<T> {
65 fn clone(&self) -> Self {
66 *self
67 }
68}
69
70impl<T> Copy for Join<T> {}
71
72impl<T: Table> Typed for Join<T> {
73 type Typ = T;
74 fn build_expr(&self, b: ValueBuilder) -> SimpleExpr {
75 sea_query::Expr::col((self.build_table(b), Alias::new(T::ID))).into()
76 }
77 fn build_table(&self, _: ValueBuilder) -> MyAlias {
78 self.table
79 }
80}
81
82pub struct TableRow<'t, T> {
93 pub(crate) _p: PhantomData<&'t ()>,
94 pub(crate) _local: PhantomData<LocalClient>,
95 pub(crate) inner: TableRowInner<T>,
96}
97impl<'t, T> TableRow<'t, T> {
98 pub(crate) fn new(idx: i64) -> Self {
99 Self {
100 _p: PhantomData,
101 _local: PhantomData,
102 inner: TableRowInner {
103 _p: PhantomData,
104 idx,
105 },
106 }
107 }
108}
109
110impl<'t, T> Eq for TableRow<'t, T> {}
111
112impl<'t, T> PartialOrd for TableRow<'t, T> {
113 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
114 self.inner.idx.partial_cmp(&other.inner.idx)
115 }
116}
117
118impl<'t, T> Ord for TableRow<'t, T> {
119 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
120 self.inner.idx.cmp(&other.inner.idx)
121 }
122}
123
124pub(crate) struct TableRowInner<T> {
125 pub(crate) _p: PhantomData<T>,
126 pub(crate) idx: i64,
127}
128
129impl<'t, T> PartialEq for TableRow<'t, T> {
130 fn eq(&self, other: &Self) -> bool {
131 self.inner.idx == other.inner.idx
132 }
133}
134
135impl<T> Debug for TableRow<'_, T> {
136 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137 write!(f, "db_{}", self.inner.idx)
138 }
139}
140
141impl<T> Clone for TableRow<'_, T> {
142 fn clone(&self) -> Self {
143 *self
144 }
145}
146impl<T> Copy for TableRow<'_, T> {}
147
148impl<T> Clone for TableRowInner<T> {
149 fn clone(&self) -> Self {
150 *self
151 }
152}
153impl<T> Copy for TableRowInner<T> {}
154
155impl<T: Table> Deref for TableRow<'_, T> {
156 type Target = T::Ext<Self>;
157
158 fn deref(&self) -> &Self::Target {
159 RefCast::ref_cast(self)
160 }
161}
162
163impl<'t, T> From<TableRow<'t, T>> for sea_query::Value {
164 fn from(value: TableRow<T>) -> Self {
165 value.inner.idx.into()
166 }
167}
168
169impl<T: Table> Typed for TableRowInner<T> {
170 type Typ = T;
171 fn build_expr(&self, _: ValueBuilder) -> SimpleExpr {
172 sea_query::Expr::val(self.idx).into()
173 }
174}
175
176impl<'t, S, T: Table> IntoExpr<'t, S> for TableRow<'t, T> {
177 type Typ = T;
178 fn into_expr(self) -> Expr<'t, S, Self::Typ> {
179 Expr::new(self.inner)
180 }
181}
182
183impl<T> rusqlite::ToSql for TableRow<'_, T> {
186 fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
187 self.inner.idx.to_sql()
188 }
189}
190
191#[cfg(test)]
192#[allow(unused)]
193mod tests {
194 use std::convert::Infallible;
195
196 use crate::{IntoSelectExt, Select, private::Reader};
197
198 use super::*;
199 struct Admin;
200
201 impl Table for Admin {
202 type MigrateFrom = Self;
203 type Ext<T> = AdminSelect<T>;
204
205 type Schema = ();
206 type Referer = ();
207 fn get_referer_unchecked() -> Self::Referer {}
208
209 fn typs(_: &mut crate::hash::TypBuilder<Self::Schema>) {}
210
211 type Conflict<'t> = Infallible;
212 type UpdateOk<'t> = ();
213 type Update<'t> = ();
214 type Insert<'t> = ();
215
216 fn read<'t>(val: &Self::Insert<'t>, f: &Reader<'t, Self::Schema>) {
217 todo!()
218 }
219
220 fn get_conflict_unchecked<'t>(val: &Self::Insert<'t>) -> Self::Conflict<'t> {
221 todo!()
222 }
223
224 fn update_into_try_update<'t>(val: Self::UpdateOk<'t>) -> Self::Update<'t> {
225 todo!()
226 }
227
228 fn apply_try_update<'t>(
229 val: Self::Update<'t>,
230 old: Expr<'t, Self::Schema, Self>,
231 ) -> Self::Insert<'t> {
232 todo!()
233 }
234
235 const ID: &'static str = "";
236 const NAME: &'static str = "";
237 }
238
239 #[repr(transparent)]
240 #[derive(RefCast)]
241 struct AdminSelect<X>(X);
242
243 impl<X: Clone> AdminSelect<X> {
244 fn a(&self) -> Col<Admin, X> {
245 Col::new("a", self.0.clone())
246 }
247 fn b(&self) -> Col<Admin, X> {
248 Col::new("b", self.0.clone())
249 }
250 }
251}