vantage_table/table/impls/
columns.rs1use indexmap::IndexMap;
2use vantage_expressions::{Expression, Expressive, traits::datasource::ExprDataSource};
3use vantage_types::Entity;
4
5use crate::{
6 column::core::ColumnType, prelude::ColumnLike, table::Table, traits::table_source::TableSource,
7};
8
9impl<T: TableSource, E: Entity<T::Value>> Table<T, E> {
10 pub fn add_column<NewColumnType>(&mut self, column: T::Column<NewColumnType>)
12 where
13 NewColumnType: ColumnType,
14 {
15 let name = column.name().to_string();
16
17 if self.columns.contains_key(&name) {
18 panic!("Duplicate column: {}", name);
19 }
20
21 let any_column = self.data_source.to_any_column(column);
23 self.columns.insert(name, any_column);
24 }
25
26 pub fn with_column<NewColumnType>(mut self, column: T::Column<NewColumnType>) -> Self
28 where
29 NewColumnType: ColumnType,
30 {
31 self.add_column(column);
32 self
33 }
34
35 pub fn add_column_of<NewColumnType>(&mut self, name: impl Into<String>)
37 where
38 NewColumnType: ColumnType,
39 {
40 let column = self
41 .data_source
42 .create_column::<NewColumnType>(&name.into());
43 self.add_column(column);
44 }
45
46 pub fn with_id_column(mut self, name: impl Into<String>) -> Self
48 where
49 T::Id: ColumnType,
50 {
51 let name = name.into();
52 self.id_field = Some(name.clone());
53 let column = self.data_source.create_column::<T::Id>(&name);
54 self.add_column(column);
55 self
56 }
57
58 pub fn with_title_column_of<NewColumnType>(mut self, name: impl Into<String>) -> Self
64 where
65 NewColumnType: ColumnType,
66 {
67 let name = name.into();
68 if !self.title_fields.contains(&name) {
69 self.title_fields.push(name.clone());
70 }
71 if self.title_field.is_none() {
72 self.title_field = Some(name.clone());
73 }
74 let column = self.data_source.create_column::<NewColumnType>(&name);
75 self.add_column(column);
76 self
77 }
78
79 pub fn with_column_of<NewColumnType>(self, name: impl Into<String>) -> Self
81 where
82 NewColumnType: ColumnType,
83 {
84 let column = self
85 .data_source
86 .create_column::<NewColumnType>(&name.into());
87 self.with_column(column)
88 }
89
90 pub fn columns(&self) -> &IndexMap<String, T::Column<T::AnyType>> {
92 &self.columns
93 }
94
95 pub fn get_column<Type>(&self, name: &str) -> Option<T::Column<Type>>
97 where
98 Type: ColumnType,
99 {
100 let any_column = self.columns.get(name)?;
101 self.data_source
102 .convert_any_column::<Type>(any_column.clone())
103 }
104
105 pub fn get_column_expr(&self, name: &str) -> Option<vantage_expressions::Expression<T::Value>>
111 where
112 T::Column<T::AnyType>: vantage_expressions::Expressive<T::Value>,
113 {
114 if let Some(expr_fn) = self.expressions.get(name) {
115 Some(expr_fn(self))
116 } else {
117 use vantage_expressions::Expressive;
118 self.columns.get(name).map(|c| c.expr())
119 }
120 }
121}
122
123impl<T, E> Table<T, E>
124where
125 T: TableSource + ExprDataSource<T::Value>,
126 E: Entity<T::Value> + 'static,
127{
128 pub fn column_values_expr(&self, column_name: &str) -> Expression<T::Value> {
141 let col = self
142 .get_column::<T::AnyType>(column_name)
143 .unwrap_or_else(|| panic!("column {column_name:?} not found on table"));
144 self.data_source.column_table_values_expr(self, &col).expr()
145 }
146}
147
148#[cfg(test)]
149mod tests {
150 use super::*;
151 use crate::mocks::mock_column::MockColumn;
152 use crate::prelude::MockTableSource;
153 use serde_json::Value;
154 use vantage_types::EmptyEntity;
155
156 #[test]
157 fn test_add_column() {
158 let ds = MockTableSource::new();
159 let mut table = Table::<MockTableSource, EmptyEntity>::new("test", ds);
160
161 table.add_column(MockColumn::<String>::new("name"));
162
163 assert!(table.columns().contains_key("name"));
164 assert_eq!(table.columns().len(), 1);
165 }
166
167 #[test]
168 fn test_with_column() {
169 let ds = MockTableSource::new();
170 let table = Table::<MockTableSource, EmptyEntity>::new("test", ds)
171 .with_column(MockColumn::<Value>::new("name"))
172 .with_column(MockColumn::<i32>::new("email"));
173
174 assert!(table.columns().contains_key("name"));
175 assert!(table.columns().contains_key("email"));
176 assert_eq!(table.columns().len(), 2);
177 }
178
179 #[test]
180 #[should_panic(expected = "Duplicate column")]
181 fn test_duplicate_column_panics() {
182 let ds = MockTableSource::new();
183 let mut table = Table::<MockTableSource, EmptyEntity>::new("test", ds);
184
185 table.add_column(MockColumn::<String>::new("name"));
186 table.add_column(MockColumn::<String>::new("name")); }
188
189 #[test]
190 fn test_with_column_of() {
191 let ds = MockTableSource::new();
192 let table = Table::<MockTableSource, EmptyEntity>::new("test", ds)
193 .with_column_of::<String>("name")
194 .with_column_of::<i64>("age")
195 .with_column_of::<bool>("active");
196
197 assert!(table.columns().contains_key("name"));
198 assert!(table.columns().contains_key("age"));
199 assert!(table.columns().contains_key("active"));
200 assert_eq!(table.columns().len(), 3);
201 }
202
203 #[test]
204 fn test_add_column_of() {
205 let ds = MockTableSource::new();
206 let mut table = Table::<MockTableSource, EmptyEntity>::new("test", ds);
207
208 table.add_column_of::<String>("email");
209 table.add_column_of::<i64>("balance");
210
211 assert!(table.columns().contains_key("email"));
212 assert!(table.columns().contains_key("balance"));
213 assert_eq!(table.columns().len(), 2);
214 }
215
216 #[test]
217 fn test_columns_access() {
218 let ds = MockTableSource::new();
219 let table = Table::<MockTableSource, EmptyEntity>::new("test", ds)
220 .with_column_of::<String>("name")
221 .with_column_of::<i64>("age");
222
223 let columns = table.columns();
224 assert!(columns.contains_key("name"));
225 assert!(columns.contains_key("age"));
226 assert_eq!(columns.len(), 2);
227
228 let name_column = table.columns().get("name");
229 assert!(name_column.is_some());
230 assert_eq!(name_column.unwrap().name(), "name");
231
232 let missing_column = table.columns().get("missing");
233 assert!(missing_column.is_none());
234 }
235}