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 {
157 let mut b = crate::migrate::TableTypBuilder::default();
158 S::typs(&mut b);
159 let mut hasher = KangarooHasher::default();
160 b.ast.hash(&mut hasher);
161 format!("{:x}", hasher.finish())
162 }
163}
164
165pub struct TypBuilder<S> {
166 pub(crate) ast: Table,
167 _p: PhantomData<S>,
168}
169
170impl<S> Default for TypBuilder<S> {
171 fn default() -> Self {
172 Self {
173 ast: Default::default(),
174 _p: Default::default(),
175 }
176 }
177}
178
179impl<S> TypBuilder<S> {
180 pub fn col<T: SchemaType<S>>(&mut self, name: &'static str) {
181 let mut item = Column {
182 name: name.to_owned(),
183 typ: T::TYP,
184 nullable: T::NULLABLE,
185 fk: None,
186 };
187 if let Some((table, fk)) = T::FK {
188 item.fk = Some((table.to_owned(), fk.to_owned()))
189 }
190 self.ast.columns.insert(item)
191 }
192
193 pub fn unique(&mut self, cols: &[&'static str]) {
194 let mut unique = Unique::default();
195 for &col in cols {
196 unique.columns.insert(col.to_owned());
197 }
198 self.ast.uniques.insert(unique);
199 }
200
201 pub fn check_unique_compatible<T: EqTyp>(&mut self) {}
202}
203
204struct Null;
205struct NotNull;
206
207#[diagnostic::on_unimplemented(
210 message = "Can not use `{Self}` as a column type in schema `{S}`",
211 note = "Table names can be used as schema column types as long as they are not #[no_reference]"
212)]
213trait SchemaType<S>: MyTyp {
214 type N;
215}
216
217impl<S> SchemaType<S> for String {
218 type N = NotNull;
219}
220impl<S> SchemaType<S> for Vec<u8> {
221 type N = NotNull;
222}
223impl<S> SchemaType<S> for i64 {
224 type N = NotNull;
225}
226impl<S> SchemaType<S> for f64 {
227 type N = NotNull;
228}
229impl<S, T: SchemaType<S, N = NotNull>> SchemaType<S> for Option<T> {
230 type N = Null;
231}
232#[diagnostic::do_not_recommend]
234impl<T: crate::Table<Referer = ()>> SchemaType<T::Schema> for T {
235 type N = NotNull;
236}