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);
22 self.columns.insert(name, any_column);
23 }
24
25 pub fn with_column<NewColumnType>(mut self, column: T::Column<NewColumnType>) -> Self
27 where
28 NewColumnType: ColumnType,
29 {
30 self.add_column(column);
31 self
32 }
33
34 pub fn copy_columns_from<E2: Entity<T::Value>>(
39 &mut self,
40 other: &Table<T, E2>,
41 names: Option<&[&str]>,
42 ) {
43 for col in other.columns().values() {
44 let name = col.name();
45 if names.is_some_and(|ns| !ns.contains(&name)) {
46 continue;
47 }
48 if !self.columns.contains_key(name) {
49 self.add_column(col.clone());
50 }
51 }
52 }
53
54 pub fn add_column_of<NewColumnType>(&mut self, name: impl Into<String>)
56 where
57 NewColumnType: ColumnType,
58 {
59 let column = self
60 .data_source
61 .create_column::<NewColumnType>(&name.into());
62 self.add_column(column);
63 }
64
65 pub fn with_id_column(mut self, name: impl Into<String>) -> Self
67 where
68 T::Id: ColumnType,
69 {
70 let name = name.into();
71 self.id_field = Some(name.clone());
72 let column = self.data_source.create_column::<T::Id>(&name);
73 self.add_column(column);
74 self
75 }
76
77 pub fn with_text_id(mut self) -> Self {
83 self.id_text = true;
84 self
85 }
86
87 pub fn id_is_text(&self) -> bool {
89 self.id_text
90 }
91
92 pub fn with_auto_id(mut self) -> Self {
96 self.id_auto = true;
97 self
98 }
99
100 pub fn has_auto_id(&self) -> bool {
102 self.id_auto
103 }
104
105 pub fn with_title_column_of<NewColumnType>(mut self, name: impl Into<String>) -> Self
111 where
112 NewColumnType: ColumnType,
113 {
114 let name = name.into();
115 if !self.title_fields.contains(&name) {
116 self.title_fields.push(name.clone());
117 }
118 if self.title_field.is_none() {
119 self.title_field = Some(name.clone());
120 }
121 let column = self.data_source.create_column::<NewColumnType>(&name);
122 self.add_column(column);
123 self
124 }
125
126 pub fn with_title_column<NewColumnType>(mut self, column: T::Column<NewColumnType>) -> Self
130 where
131 NewColumnType: ColumnType,
132 {
133 let name = column.name().to_string();
134 if !self.title_fields.contains(&name) {
135 self.title_fields.push(name.clone());
136 }
137 if self.title_field.is_none() {
138 self.title_field = Some(name);
139 }
140 self.add_column(column);
141 self
142 }
143
144 pub fn with_column_of<NewColumnType>(self, name: impl Into<String>) -> Self
146 where
147 NewColumnType: ColumnType,
148 {
149 let column = self
150 .data_source
151 .create_column::<NewColumnType>(&name.into());
152 self.with_column(column)
153 }
154
155 pub fn remove_column(&mut self, name: &str) -> vantage_core::Result<()> {
161 if name == self.id_field_name() {
162 return Err(vantage_core::error!(format!(
163 "`{name}` is the id column of `{}`; it can't be removed",
164 self.table_name()
165 )));
166 }
167 let mut found = false;
168 if let Some((stored_index, _, _)) = self.columns.shift_remove_full(name) {
169 found = true;
170 let removed = self.position_of_stored(stored_index);
171 for (at, _) in self.computed_columns.values_mut() {
172 if *at > removed {
173 *at -= 1;
174 }
175 }
176 }
177 if let Some((removed, _)) = self.computed_columns.shift_remove(name) {
178 found = true;
179 for (at, _) in self.computed_columns.values_mut() {
180 if *at > removed {
181 *at -= 1;
182 }
183 }
184 }
185 found |= self.expressions.shift_remove(name).is_some();
186 found |= self.lazy_expressions.shift_remove(name).is_some();
187 if !found {
188 return Err(vantage_core::error!(format!(
189 "no column `{name}` in `{}`",
190 self.table_name()
191 )));
192 }
193 self.imported_columns.shift_remove(name);
194 if let Some(active) = &mut self.active_columns {
195 active.shift_remove(name);
196 }
197 self.title_fields.retain(|title| title != name);
198 if self.title_field.as_deref() == Some(name) {
199 self.title_field = self.title_fields.first().cloned();
200 }
201 Ok(())
202 }
203
204 pub fn columns(&self) -> &IndexMap<String, T::Column<T::AnyType>> {
206 &self.columns
207 }
208
209 pub fn get_column<Type>(&self, name: &str) -> Option<T::Column<Type>>
211 where
212 Type: ColumnType,
213 {
214 let any_column = self.columns.get(name)?;
215 self.data_source
216 .convert_any_column::<Type>(any_column.clone())
217 }
218
219 pub fn get_column_expr(&self, name: &str) -> Option<vantage_expressions::Expression<T::Value>>
225 where
226 T::Column<T::AnyType>: vantage_expressions::Expressive<T::Value>,
227 {
228 if let Some(expr_fn) = self.expressions.get(name) {
229 Some(expr_fn(self.as_entity_erased()))
230 } else {
231 use vantage_expressions::Expressive;
232 self.columns.get(name).map(|c| c.expr())
233 }
234 }
235}
236
237impl<T, E> Table<T, E>
238where
239 T: TableSource + ExprDataSource<T::Value>,
240 E: Entity<T::Value> + 'static,
241{
242 pub fn column_values_expr(&self, column_name: &str) -> Expression<T::Value> {
255 let col = self
256 .get_column::<T::AnyType>(column_name)
257 .unwrap_or_else(|| panic!("column {column_name:?} not found on table"));
258 self.data_source.column_table_values_expr(self, &col).expr()
259 }
260}