1use std::{marker::PhantomData, ops::Deref};
6
7use sea_query::TableCreateStatement;
8
9use crate::value::{EqTyp, MyTyp};
10
11#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
12pub enum ColumnType {
13 Integer = 0,
14 Float = 1,
15 String = 2,
16 Blob = 3,
17}
18
19impl ColumnType {
20 pub fn sea_type(&self) -> sea_query::ColumnType {
21 use sea_query::ColumnType as T;
22 match self {
23 ColumnType::Integer => T::Integer,
24 ColumnType::Float => T::custom("REAL"),
25 ColumnType::String => T::Text,
26 ColumnType::Blob => T::Blob,
27 }
28 }
29}
30
31#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
32pub struct Column {
33 pub name: String,
34 pub typ: ColumnType,
35 pub nullable: bool,
36 pub fk: Option<(String, String)>,
37}
38
39#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Default)]
40pub struct Unique {
41 pub columns: MyVec<String>,
42}
43
44#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Default)]
45pub struct Table {
46 pub columns: MyVec<Column>,
47 pub uniques: MyVec<Unique>,
48}
49
50#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
52pub struct MyVec<T> {
53 inner: Vec<T>,
54}
55
56impl<T> Default for MyVec<T> {
57 fn default() -> Self {
58 Self {
59 inner: Default::default(),
60 }
61 }
62}
63
64impl<T: Ord> MyVec<T> {
65 pub fn insert(&mut self, item: T) {
66 let index = self.inner.partition_point(|x| x < &item);
67 self.inner.insert(index, item);
68 }
69}
70
71impl<T> Deref for MyVec<T> {
72 type Target = [T];
73
74 fn deref(&self) -> &Self::Target {
75 &self.inner
76 }
77}
78
79impl Table {
80 pub fn create(&self) -> TableCreateStatement {
81 use sea_query::*;
82 let mut create = Table::create();
83 for col in &*self.columns {
84 let name = Alias::new(&col.name);
85 let mut def = ColumnDef::new_with_type(name.clone(), col.typ.sea_type());
86 if col.nullable {
87 def.null();
88 } else {
89 def.not_null();
90 }
91 create.col(&mut def);
92 if let Some((table, fk)) = &col.fk {
93 create.foreign_key(
94 ForeignKey::create()
95 .to(Alias::new(table), Alias::new(fk))
96 .from_col(name),
97 );
98 }
99 }
100 for unique in &*self.uniques {
101 let mut index = sea_query::Index::create().unique().take();
102 for col in &*unique.columns {
103 index.col(Alias::new(col));
104 }
105 create.index(&mut index);
106 }
107 create
108 }
109}
110
111#[derive(Debug, Hash, Default, PartialEq, Eq)]
112pub struct Schema {
113 pub tables: MyVec<(String, Table)>,
114}
115
116#[cfg(feature = "dev")]
117pub mod dev {
118 use std::{
119 hash::{Hash, Hasher},
120 io::{Read, Write},
121 };
122
123 use k12::{
124 KangarooTwelve, KangarooTwelveCore,
125 digest::{ExtendableOutput, core_api::CoreWrapper},
126 };
127
128 pub struct KangarooHasher {
129 inner: CoreWrapper<KangarooTwelveCore<'static>>,
130 }
131
132 impl Default for KangarooHasher {
133 fn default() -> Self {
134 let core = KangarooTwelveCore::new(&[]);
135 let hasher = KangarooTwelve::from_core(core);
136 Self { inner: hasher }
137 }
138 }
139
140 impl Hasher for KangarooHasher {
141 fn finish(&self) -> u64 {
142 let mut xof = self.inner.clone().finalize_xof();
143 let mut buf = [0; 8];
144 xof.read_exact(&mut buf).unwrap();
145 u64::from_le_bytes(buf)
146 }
147
148 fn write(&mut self, bytes: &[u8]) {
149 self.inner.write_all(bytes).unwrap();
150 }
151 }
152
153 pub fn hash_schema<S: crate::migrate::Schema>() -> String {
154 let mut b = crate::migrate::TableTypBuilder::default();
155 S::typs(&mut b);
156 let mut hasher = KangarooHasher::default();
157 b.ast.hash(&mut hasher);
158 format!("{:x}", hasher.finish())
159 }
160}
161
162pub struct TypBuilder<S> {
163 pub(crate) ast: Table,
164 _p: PhantomData<S>,
165}
166
167impl<S> Default for TypBuilder<S> {
168 fn default() -> Self {
169 Self {
170 ast: Default::default(),
171 _p: Default::default(),
172 }
173 }
174}
175
176impl<S> TypBuilder<S> {
177 pub fn col<T: SchemaType<S>>(&mut self, name: &'static str) {
178 let mut item = Column {
179 name: name.to_owned(),
180 typ: T::TYP,
181 nullable: T::NULLABLE,
182 fk: None,
183 };
184 if let Some((table, fk)) = T::FK {
185 item.fk = Some((table.to_owned(), fk.to_owned()))
186 }
187 self.ast.columns.insert(item)
188 }
189
190 pub fn unique(&mut self, cols: &[&'static str]) {
191 let mut unique = Unique::default();
192 for &col in cols {
193 unique.columns.insert(col.to_owned());
194 }
195 self.ast.uniques.insert(unique);
196 }
197
198 pub fn check_unique_compatible<T: EqTyp>(&mut self) {}
199}
200
201struct Null;
202struct NotNull;
203
204#[diagnostic::on_unimplemented(
207 message = "Can not use `{Self}` as a column type in schema `{S}`",
208 note = "Table names can be used as schema column types as long as they are not #[no_reference]"
209)]
210trait SchemaType<S>: MyTyp {
211 type N;
212}
213
214impl<S> SchemaType<S> for String {
215 type N = NotNull;
216}
217impl<S> SchemaType<S> for Vec<u8> {
218 type N = NotNull;
219}
220impl<S> SchemaType<S> for i64 {
221 type N = NotNull;
222}
223impl<S> SchemaType<S> for f64 {
224 type N = NotNull;
225}
226impl<S, T: SchemaType<S, N = NotNull>> SchemaType<S> for Option<T> {
227 type N = Null;
228}
229#[diagnostic::do_not_recommend]
231impl<T: crate::Table<Referer = ()>> SchemaType<T::Schema> for T {
232 type N = NotNull;
233}