wasm_dbms_api/dbms/table/
record.rs1use crate::dbms::table::{ColumnDef, TableSchema};
2use crate::dbms::value::Value;
3use crate::error::DbmsResult;
4use crate::prelude::Filter;
5
6pub type TableColumns = Vec<(ValuesSource, Vec<(ColumnDef, Value)>)>;
7
8pub fn flatten_table_columns(rows: Vec<TableColumns>) -> Vec<Vec<(ColumnDef, Value)>> {
13 rows.into_iter()
14 .map(|row| {
15 row.into_iter()
16 .filter(|(source, _)| *source == ValuesSource::This)
17 .flat_map(|(_, cols)| cols)
18 .collect()
19 })
20 .collect()
21}
22
23#[derive(Debug, Clone, PartialEq, Eq, Hash)]
25pub enum ValuesSource {
26 This,
28 Foreign { table: String, column: String },
30}
31
32pub trait TableRecord: Clone {
34 type Schema: TableSchema<Record = Self>;
36
37 fn from_values(values: TableColumns) -> Self;
39
40 fn to_values(&self) -> Vec<(ColumnDef, Value)>;
42}
43
44pub trait InsertRecord: Sized + Clone {
46 type Record: TableRecord;
48 type Schema: TableSchema<Record = Self::Record>;
50
51 fn from_values(values: &[(ColumnDef, Value)]) -> DbmsResult<Self>;
53
54 fn into_values(self) -> Vec<(ColumnDef, Value)>;
56
57 fn into_record(self) -> Self::Schema;
59}
60
61pub trait UpdateRecord: Sized + Clone {
63 type Record: TableRecord;
65 type Schema: TableSchema<Record = Self::Record>;
67
68 fn from_values(values: &[(ColumnDef, Value)], where_clause: Option<Filter>) -> Self;
70
71 fn update_values(&self) -> Vec<(ColumnDef, Value)>;
73
74 fn where_clause(&self) -> Option<Filter>;
76}
77
78#[cfg(test)]
79mod test {
80
81 use super::*;
82
83 #[test]
84 fn test_should_create_values_source_this() {
85 let source = ValuesSource::This;
86 assert_eq!(source, ValuesSource::This);
87 }
88
89 #[test]
90 fn test_should_create_values_source_foreign() {
91 let source = ValuesSource::Foreign {
92 table: "users".to_string(),
93 column: "id".to_string(),
94 };
95
96 if let ValuesSource::Foreign { table, column } = source {
97 assert_eq!(table, "users");
98 assert_eq!(column, "id");
99 } else {
100 panic!("expected ValuesSource::Foreign");
101 }
102 }
103
104 #[test]
105 fn test_should_clone_values_source() {
106 let source = ValuesSource::Foreign {
107 table: "posts".to_string(),
108 column: "author_id".to_string(),
109 };
110
111 let cloned = source.clone();
112 assert_eq!(source, cloned);
113 }
114
115 #[test]
116 fn test_should_compare_values_sources() {
117 let source1 = ValuesSource::This;
118 let source2 = ValuesSource::This;
119 let source3 = ValuesSource::Foreign {
120 table: "users".to_string(),
121 column: "id".to_string(),
122 };
123 let source4 = ValuesSource::Foreign {
124 table: "users".to_string(),
125 column: "id".to_string(),
126 };
127 let source5 = ValuesSource::Foreign {
128 table: "posts".to_string(),
129 column: "id".to_string(),
130 };
131
132 assert_eq!(source1, source2);
133 assert_eq!(source3, source4);
134 assert_ne!(source1, source3);
135 assert_ne!(source3, source5);
136 }
137
138 #[test]
139 fn test_should_hash_values_source() {
140 use std::collections::HashSet;
141
142 let mut set = HashSet::new();
143 set.insert(ValuesSource::This);
144 set.insert(ValuesSource::Foreign {
145 table: "users".to_string(),
146 column: "id".to_string(),
147 });
148
149 assert!(set.contains(&ValuesSource::This));
150 assert!(set.contains(&ValuesSource::Foreign {
151 table: "users".to_string(),
152 column: "id".to_string(),
153 }));
154 assert!(!set.contains(&ValuesSource::Foreign {
155 table: "posts".to_string(),
156 column: "id".to_string(),
157 }));
158 }
159
160 #[test]
161 fn test_should_debug_values_source() {
162 let source = ValuesSource::This;
163 let debug_str = format!("{:?}", source);
164 assert_eq!(debug_str, "This");
165
166 let foreign = ValuesSource::Foreign {
167 table: "users".to_string(),
168 column: "id".to_string(),
169 };
170 let foreign_debug = format!("{:?}", foreign);
171 assert!(foreign_debug.contains("Foreign"));
172 assert!(foreign_debug.contains("users"));
173 assert!(foreign_debug.contains("id"));
174 }
175}