wasm_dbms_api/dbms/table/
schema.rs1pub mod snapshot;
2
3use xxhash_rust::xxh3::xxh3_64;
4
5pub use self::snapshot::{
6 ColumnSnapshot, CustomDataTypeSnapshot, DataTypeSnapshot, ForeignKeySnapshot, IndexSnapshot,
7 OnDeleteSnapshot, TableSchemaSnapshot, WireSize,
8};
9use crate::dbms::foreign_fetcher::ForeignFetcher;
10use crate::dbms::table::column_def::{ColumnDef, IndexDef};
11use crate::dbms::table::{InsertRecord, TableRecord, UpdateRecord};
12use crate::dbms::types::DataTypeKind;
13use crate::memory::Encode;
14use crate::prelude::{Sanitize, Validate};
15
16pub type TableFingerprint = u64;
18
19fn data_type_to_snapshot(kind: &DataTypeKind) -> DataTypeSnapshot {
21 match kind {
22 DataTypeKind::Blob => DataTypeSnapshot::Blob,
23 DataTypeKind::Boolean => DataTypeSnapshot::Boolean,
24 DataTypeKind::Date => DataTypeSnapshot::Date,
25 DataTypeKind::DateTime => DataTypeSnapshot::Datetime,
26 DataTypeKind::Decimal => DataTypeSnapshot::Decimal,
27 DataTypeKind::Int8 => DataTypeSnapshot::Int8,
28 DataTypeKind::Int16 => DataTypeSnapshot::Int16,
29 DataTypeKind::Int32 => DataTypeSnapshot::Int32,
30 DataTypeKind::Int64 => DataTypeSnapshot::Int64,
31 DataTypeKind::Json => DataTypeSnapshot::Json,
32 DataTypeKind::Text => DataTypeSnapshot::Text,
33 DataTypeKind::Uint8 => DataTypeSnapshot::Uint8,
34 DataTypeKind::Uint16 => DataTypeSnapshot::Uint16,
35 DataTypeKind::Uint32 => DataTypeSnapshot::Uint32,
36 DataTypeKind::Uint64 => DataTypeSnapshot::Uint64,
37 DataTypeKind::Uuid => DataTypeSnapshot::Uuid,
38 DataTypeKind::Custom { tag, wire_size } => {
39 DataTypeSnapshot::Custom(Box::new(CustomDataTypeSnapshot {
40 tag: (*tag).to_string(),
41 wire_size: *wire_size,
42 }))
43 }
44 }
45}
46
47pub trait TableSchema
51where
52 Self: Encode + 'static,
53{
54 type Record: TableRecord<Schema = Self>;
57 type Insert: InsertRecord<Schema = Self>;
59 type Update: UpdateRecord<Schema = Self>;
61 type ForeignFetcher: ForeignFetcher;
63
64 fn table_name() -> &'static str;
66
67 fn columns() -> &'static [ColumnDef];
69
70 fn primary_key() -> &'static str;
72
73 fn indexes() -> &'static [IndexDef] {
76 &[]
77 }
78
79 fn to_values(self) -> Vec<(ColumnDef, crate::dbms::value::Value)>;
81
82 fn sanitizer(column_name: &'static str) -> Option<Box<dyn Sanitize>>;
84
85 fn validator(column_name: &'static str) -> Option<Box<dyn Validate>>;
87
88 fn foreign_fetcher() -> Self::ForeignFetcher {
90 Default::default()
91 }
92
93 fn schema_snapshot() -> TableSchemaSnapshot {
106 let columns = Self::columns()
107 .iter()
108 .map(|c| ColumnSnapshot {
109 name: c.name.to_string(),
110 data_type: data_type_to_snapshot(&c.data_type),
111 nullable: c.nullable,
112 auto_increment: c.auto_increment,
113 unique: c.unique,
114 primary_key: c.primary_key,
115 foreign_key: c.foreign_key.as_ref().map(|fk| ForeignKeySnapshot {
116 table: fk.foreign_table.to_string(),
117 column: fk.foreign_column.to_string(),
118 on_delete: OnDeleteSnapshot::Restrict,
119 }),
120 default: c.default.map(|f| f()),
121 })
122 .collect();
123
124 let indexes = Self::indexes()
125 .iter()
126 .map(|idx| {
127 let cols = idx.columns();
128 let unique = match cols {
129 [single] => Self::columns()
130 .iter()
131 .find(|c| c.name == *single)
132 .is_some_and(|c| c.unique || c.primary_key),
133 _ => false,
134 };
135 IndexSnapshot {
136 columns: cols.iter().map(|c| (*c).to_string()).collect(),
137 unique,
138 }
139 })
140 .collect();
141
142 TableSchemaSnapshot {
143 version: TableSchemaSnapshot::latest_version(),
144 name: Self::table_name().to_string(),
145 primary_key: Self::primary_key().to_string(),
146 alignment: <Self as Encode>::ALIGNMENT as u32,
147 columns,
148 indexes,
149 }
150 }
151
152 fn fingerprint() -> TableFingerprint {
159 fingerprint_for_name(Self::table_name())
160 }
161}
162
163pub fn fingerprint_for_name(name: &str) -> TableFingerprint {
170 xxh3_64(name.as_bytes())
171}