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>)
78 -> DbmsResult<Self>;
79
80 fn update_values(&self) -> Vec<(ColumnDef, Value)>;
82
83 fn where_clause(&self) -> Option<Filter>;
85}
86
87#[cfg(test)]
88mod test {
89
90 use super::*;
91
92 #[test]
93 fn test_should_create_values_source_this() {
94 let source = ValuesSource::This;
95 assert_eq!(source, ValuesSource::This);
96 }
97
98 #[test]
99 fn test_should_create_values_source_foreign() {
100 let source = ValuesSource::Foreign {
101 table: "users".to_string(),
102 column: "id".to_string(),
103 };
104
105 if let ValuesSource::Foreign { table, column } = source {
106 assert_eq!(table, "users");
107 assert_eq!(column, "id");
108 } else {
109 panic!("expected ValuesSource::Foreign");
110 }
111 }
112
113 #[test]
114 fn test_should_clone_values_source() {
115 let source = ValuesSource::Foreign {
116 table: "posts".to_string(),
117 column: "author_id".to_string(),
118 };
119
120 let cloned = source.clone();
121 assert_eq!(source, cloned);
122 }
123
124 #[test]
125 fn test_should_compare_values_sources() {
126 let source1 = ValuesSource::This;
127 let source2 = ValuesSource::This;
128 let source3 = ValuesSource::Foreign {
129 table: "users".to_string(),
130 column: "id".to_string(),
131 };
132 let source4 = ValuesSource::Foreign {
133 table: "users".to_string(),
134 column: "id".to_string(),
135 };
136 let source5 = ValuesSource::Foreign {
137 table: "posts".to_string(),
138 column: "id".to_string(),
139 };
140
141 assert_eq!(source1, source2);
142 assert_eq!(source3, source4);
143 assert_ne!(source1, source3);
144 assert_ne!(source3, source5);
145 }
146
147 #[test]
148 fn test_should_hash_values_source() {
149 use std::collections::HashSet;
150
151 let mut set = HashSet::new();
152 set.insert(ValuesSource::This);
153 set.insert(ValuesSource::Foreign {
154 table: "users".to_string(),
155 column: "id".to_string(),
156 });
157
158 assert!(set.contains(&ValuesSource::This));
159 assert!(set.contains(&ValuesSource::Foreign {
160 table: "users".to_string(),
161 column: "id".to_string(),
162 }));
163 assert!(!set.contains(&ValuesSource::Foreign {
164 table: "posts".to_string(),
165 column: "id".to_string(),
166 }));
167 }
168
169 #[test]
170 fn test_should_debug_values_source() {
171 let source = ValuesSource::This;
172 let debug_str = format!("{:?}", source);
173 assert_eq!(debug_str, "This");
174
175 let foreign = ValuesSource::Foreign {
176 table: "users".to_string(),
177 column: "id".to_string(),
178 };
179 let foreign_debug = format!("{:?}", foreign);
180 assert!(foreign_debug.contains("Foreign"));
181 assert!(foreign_debug.contains("users"));
182 assert!(foreign_debug.contains("id"));
183 }
184}