1use std::{fmt::Debug, marker::PhantomData, ops::Deref};
2
3use ref_cast::RefCast;
4use sea_query::{Alias, Expr, SimpleExpr};
5
6use crate::{
7 alias::{Field, MyAlias},
8 value::{MyTyp, Typed, ValueBuilder},
9 IntoColumn, LocalClient, Table,
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: Table, X: Clone> Deref for Col<T, X> {
41 type Target = T::Ext<Self>;
42
43 fn deref(&self) -> &Self::Target {
44 RefCast::ref_cast(self)
45 }
46}
47
48impl<T: MyTyp, P: Typed<Typ: Table>> Typed for Col<T, P> {
49 type Typ = T;
50 fn build_expr(&self, b: ValueBuilder) -> SimpleExpr {
51 Expr::col((self.inner.build_table(b), self.field)).into()
52 }
53}
54impl<'t, S, T: MyTyp, P: IntoColumn<'t, S, Typ: Table>> IntoColumn<'t, S> for Col<T, P> {
55 type Owned = Col<T, P::Owned>;
56
57 fn into_owned(self) -> Self::Owned {
58 Col {
59 _p: PhantomData,
60 field: self.field,
61 inner: self.inner.into_owned(),
62 }
63 }
64}
65
66pub(crate) struct Join<'t, T> {
70 pub(crate) table: MyAlias,
71 pub(crate) _p: PhantomData<fn(&'t T) -> &'t T>,
72}
73
74impl<'t, T> Join<'t, T> {
75 pub(crate) fn new(table: MyAlias) -> Self {
76 Self {
77 table,
78 _p: PhantomData,
79 }
80 }
81}
82
83impl<'t, T> Clone for Join<'t, T> {
84 fn clone(&self) -> Self {
85 *self
86 }
87}
88
89impl<'t, T> Copy for Join<'t, T> {}
90
91impl<'t, T: Table> Deref for Join<'t, T> {
92 type Target = T::Ext<Self>;
93
94 fn deref(&self) -> &Self::Target {
95 RefCast::ref_cast(self)
96 }
97}
98
99impl<T: Table> Typed for Join<'_, T> {
100 type Typ = T;
101 fn build_expr(&self, b: ValueBuilder) -> SimpleExpr {
102 Expr::col((self.build_table(b), Alias::new(T::ID))).into()
103 }
104 fn build_table(&self, _: ValueBuilder) -> MyAlias {
105 self.table
106 }
107}
108impl<'t, T: Table> IntoColumn<'t, T::Schema> for Join<'t, T> {
109 type Owned = Self;
110
111 fn into_owned(self) -> Self::Owned {
112 self
113 }
114}
115
116pub struct TableRow<'t, T> {
120 pub(crate) _p: PhantomData<&'t T>,
121 pub(crate) _local: PhantomData<LocalClient>,
122 pub(crate) idx: i64,
123}
124
125impl<'t, T> PartialEq for TableRow<'t, T> {
126 fn eq(&self, other: &Self) -> bool {
127 self.idx == other.idx
128 }
129}
130
131impl<T> Debug for TableRow<'_, T> {
132 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133 write!(f, "db_{}", self.idx)
134 }
135}
136
137impl<T> Clone for TableRow<'_, T> {
138 fn clone(&self) -> Self {
139 *self
140 }
141}
142impl<T> Copy for TableRow<'_, T> {}
143
144impl<T: Table> Deref for TableRow<'_, T> {
145 type Target = T::Ext<Self>;
146
147 fn deref(&self) -> &Self::Target {
148 RefCast::ref_cast(self)
149 }
150}
151
152impl<'t, T> From<TableRow<'t, T>> for sea_query::Value {
153 fn from(value: TableRow<T>) -> Self {
154 value.idx.into()
155 }
156}
157
158impl<T: Table> Typed for TableRow<'_, T> {
159 type Typ = T;
160 fn build_expr(&self, _: ValueBuilder) -> SimpleExpr {
161 Expr::val(self.idx).into()
162 }
163}
164
165impl<'t, T: Table> IntoColumn<'t, T::Schema> for TableRow<'t, T> {
166 type Owned = TableRow<'t, T>;
167
168 fn into_owned(self) -> Self::Owned {
169 self
170 }
171}
172
173#[cfg(feature = "unchecked_transaction")]
176impl<T> rusqlite::ToSql for TableRow<'_, T> {
177 fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
178 self.idx.to_sql()
179 }
180}
181
182#[cfg(test)]
183#[allow(unused)]
184mod tests {
185 use super::*;
186 struct Admin;
187
188 impl Table for Admin {
189 type Ext<T> = AdminDummy<T>;
190
191 type Schema = ();
192 type Referer = ();
193 fn get_referer_unchecked() -> Self::Referer {}
194
195 fn typs(_: &mut crate::hash::TypBuilder<Self::Schema>) {}
196
197 type Dummy<'t> = ();
198 fn dummy<'t>(_: impl IntoColumn<'t, Self::Schema, Typ = Self>) -> Self::Dummy<'t> {}
199 }
200
201 #[repr(transparent)]
202 #[derive(RefCast)]
203 struct AdminDummy<X>(X);
204
205 impl<X: Clone> AdminDummy<X> {
206 fn a(&self) -> Col<Admin, X> {
207 Col::new("a", self.0.clone())
208 }
209 fn b(&self) -> Col<Admin, X> {
210 Col::new("b", self.0.clone())
211 }
212 }
213
214 fn test(x: Join<Admin>) {
215 let _res = &x.a().b().a().a();
216 }
217}