wasm_dbms/transaction/
overlay.rs1mod reader;
6mod table;
7
8use std::collections::HashMap;
9
10use wasm_dbms_api::prelude::{ColumnDef, DbmsError, DbmsResult, QueryError, TableSchema, Value};
11use wasm_dbms_memory::prelude::{MemoryAccess, TableReader};
12
13pub use self::reader::DatabaseOverlayReader;
14pub use self::table::IndexOverlay;
15pub(crate) use self::table::TableOverlay;
16
17#[derive(Debug, Default, Clone)]
22pub struct DatabaseOverlay {
23 tables: HashMap<String, TableOverlay>,
24}
25
26impl DatabaseOverlay {
27 pub fn reader<'a, T, MA>(
29 &'a mut self,
30 table_reader: TableReader<'a, T, MA>,
31 ) -> DatabaseOverlayReader<'a, T, MA>
32 where
33 T: TableSchema,
34 MA: MemoryAccess,
35 {
36 let table_name = T::table_name();
37 let table_overlay = self
38 .tables
39 .entry(table_name.to_string())
40 .or_insert_with(|| TableOverlay::new(T::indexes()));
41 DatabaseOverlayReader::new(table_overlay, table_reader)
42 }
43
44 pub fn insert<T>(&mut self, values: Vec<(ColumnDef, Value)>) -> DbmsResult<()>
46 where
47 T: TableSchema,
48 {
49 let table_name = T::table_name();
50 let pk = T::primary_key();
51 let pk = Self::primary_key(pk, &values)?;
52 let overlay = self
53 .tables
54 .entry(table_name.to_string())
55 .or_insert_with(|| TableOverlay::new(T::indexes()));
56 overlay.insert(pk, values);
57
58 Ok(())
59 }
60
61 pub fn update<T>(
65 &mut self,
66 pk: Value,
67 updates: Vec<(&'static str, Value)>,
68 current_row: &[(ColumnDef, Value)],
69 ) where
70 T: TableSchema,
71 {
72 let table_name = T::table_name();
73 let overlay = self
74 .tables
75 .entry(table_name.to_string())
76 .or_insert_with(|| TableOverlay::new(T::indexes()));
77 overlay.update(pk, updates, current_row);
78 }
79
80 pub fn delete<T>(&mut self, pk: Value, current_row: &[(ColumnDef, Value)])
84 where
85 T: TableSchema,
86 {
87 let table_name = T::table_name();
88 let overlay = self
89 .tables
90 .entry(table_name.to_string())
91 .or_insert_with(|| TableOverlay::new(T::indexes()));
92 overlay.delete(pk, current_row);
93 }
94
95 pub fn index_overlay(&self, table: &str) -> Option<&IndexOverlay> {
97 self.tables.get(table).map(|t| &t.index_overlay)
98 }
99
100 pub(crate) fn table_overlay(&self, table: &str) -> Option<&TableOverlay> {
102 self.tables.get(table)
103 }
104
105 fn primary_key(pk: &'static str, values: &[(ColumnDef, Value)]) -> DbmsResult<Value> {
106 for (col_def, value) in values {
107 if col_def.name == pk {
108 return Ok(value.clone());
109 }
110 }
111 Err(DbmsError::Query(QueryError::MissingNonNullableField(
112 pk.to_string(),
113 )))
114 }
115}