1use sqlx::{Database, Encode, FromRow, Type};
9
10mod create;
11mod delete;
12mod read;
13mod update;
14
15pub use create::Create;
16pub use delete::Delete;
17pub use read::Read;
18pub use update::Update;
19
20pub use self::column::{Column, DataColumn, ForeignKey, PrimaryKey, TimestampColumn};
21
22pub trait Table
29where
30 Self: Sized + Send + for<'r> FromRow<'r, <crate::Driver as Database>::Row> + 'static,
31 Self::PrimaryKey: for<'q> Encode<'q, crate::Driver> + Type<crate::Driver> + Send,
32{
33 type PrimaryKey: Sync + Sized + 'static;
35
36 const SCHEMA: &'static str;
38 const TABLE: &'static str;
40
41 const PRIMARY_KEY: PrimaryKey<Self>;
43 const FOREIGN_KEYS: &'static [ForeignKey<Self>];
45 const DATA_COLUMNS: &'static [DataColumn<Self>];
47 const TIMESTAMP_COLUMNS: &'static [TimestampColumn<Self>];
49
50 fn pk(&self) -> &Self::PrimaryKey;
52}
53
54pub trait Entity: Create + Read + Update + Delete {}
61
62impl<E: Create + Read + Update + Delete> Entity for E {}
63
64pub mod column {
70 use crate::Table;
71 use std::marker::PhantomData;
72
73 #[derive(Copy, Debug, PartialEq, Eq)]
75 pub enum Column<T: Table> {
76 PrimaryKey(&'static PrimaryKey<T>),
78 ForeignKey(&'static ForeignKey<T>),
80 Data(&'static DataColumn<T>),
82 Timestamp(&'static TimestampColumn<T>),
84 }
85
86 impl<T: Table> Clone for Column<T> {
87 fn clone(&self) -> Self {
88 match self {
89 Self::PrimaryKey(pk) => Self::PrimaryKey(*pk),
90 Self::ForeignKey(fk) => Self::ForeignKey(*fk),
91 Self::Data(data) => Self::Data(*data),
92 Self::Timestamp(ts) => Self::Timestamp(*ts),
93 }
94 }
95 }
96
97 impl<T: Table> Column<T> {
98 pub const fn field(&self) -> &'static str {
99 match self {
100 Self::PrimaryKey(pk) => pk.field,
101 Self::ForeignKey(fk) => fk.field,
102 Self::Data(data) => data.field,
103 Self::Timestamp(ts) => ts.field,
104 }
105 }
106
107 pub const fn sql(&self) -> &'static str {
108 match self {
109 Self::PrimaryKey(pk) => pk.sql,
110 Self::ForeignKey(fk) => fk.sql,
111 Self::Data(data) => data.sql,
112 Self::Timestamp(ts) => ts.sql,
113 }
114 }
115 }
116
117 #[derive(Copy, Debug, PartialEq, Eq)]
119 pub struct PrimaryKey<T: Table> {
120 pub field: &'static str,
121 pub sql: &'static str,
122 table: PhantomData<T>,
123 }
124
125 impl<T: Table> PrimaryKey<T> {
126 pub const fn new(field: &'static str, sql: &'static str) -> Self {
127 Self {
128 field,
129 sql,
130 table: PhantomData,
131 }
132 }
133
134 pub const fn as_col(&'static self) -> Column<T> {
135 Column::PrimaryKey(self)
136 }
137 }
138
139 impl<T: Table> Clone for PrimaryKey<T> {
140 fn clone(&self) -> Self {
141 Self {
142 field: self.field,
143 sql: self.sql,
144 table: PhantomData,
145 }
146 }
147 }
148
149 #[derive(Copy, Debug, PartialEq, Eq)]
151 pub struct ForeignKey<T: Table> {
152 pub field: &'static str,
154 pub sql: &'static str,
156 table: PhantomData<T>,
157 }
158
159 impl<T: Table> ForeignKey<T> {
160 pub const fn new(field: &'static str, sql: &'static str) -> Self {
161 Self {
162 field,
163 sql,
164 table: PhantomData,
165 }
166 }
167
168 pub const fn as_col(&'static self) -> Column<T> {
169 Column::ForeignKey(self)
170 }
171
172 pub const unsafe fn transmute<I: Table>(&'static self) -> &'static ForeignKey<I> {
178 unsafe { std::mem::transmute(self) }
179 }
180 }
181
182 impl<T: Table> Clone for ForeignKey<T> {
183 fn clone(&self) -> Self {
184 Self {
185 field: self.field,
186 sql: self.sql,
187 table: PhantomData,
188 }
189 }
190 }
191
192 #[derive(Copy, Debug, PartialEq, Eq)]
194 pub struct DataColumn<T: Table> {
195 pub field: &'static str,
197 pub sql: &'static str,
199 table: PhantomData<T>,
200 }
201
202 impl<T: Table> DataColumn<T> {
203 pub const fn new(field: &'static str, sql: &'static str) -> Self {
204 Self {
205 field,
206 sql,
207 table: PhantomData,
208 }
209 }
210
211 pub const fn as_col(&'static self) -> Column<T> {
212 Column::Data(self)
213 }
214 }
215
216 impl<T: Table> Clone for DataColumn<T> {
217 fn clone(&self) -> Self {
218 Self {
219 field: self.field,
220 sql: self.sql,
221 table: PhantomData,
222 }
223 }
224 }
225
226 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
228 pub enum TimestampKind {
229 Created,
230 Updated,
231 Deleted,
232 }
233
234 #[derive(Copy, Debug, PartialEq, Eq)]
236 pub struct TimestampColumn<T: Table> {
237 pub kind: TimestampKind,
239 pub field: &'static str,
241 pub sql: &'static str,
243 table: PhantomData<T>,
244 }
245
246 impl<T: Table> TimestampColumn<T> {
247 pub const fn new(kind: TimestampKind, field: &'static str, sql: &'static str) -> Self {
248 Self {
249 kind,
250 field,
251 sql,
252 table: PhantomData,
253 }
254 }
255 }
256
257 impl<T: Table> Clone for TimestampColumn<T> {
258 fn clone(&self) -> Self {
259 Self {
260 kind: self.kind,
261 field: self.field,
262 sql: self.sql,
263 table: PhantomData,
264 }
265 }
266 }
267}