vantage_table/table/impls/
selectable.rs1use vantage_core::Result;
2use vantage_expressions::traits::selectable::Selectable;
3use vantage_expressions::{Expression, Expressive, SelectableDataSource, expr_any};
4use vantage_types::Entity;
5
6use crate::{
7 column::core::ColumnType,
8 source::{SelectSeed, SelectSource},
9 table::Table,
10 traits::column_like::ColumnLike,
11 traits::table_source::TableSource,
12};
13
14impl<T, E> Table<T, E>
15where
16 T: SelectableDataSource<T::Value, T::Condition> + TableSource,
17 T::Source: SelectSeed<T::Select, T::Value, T::Condition>,
18 T::Value: From<String>, E: Entity<T::Value>,
20{
21 pub fn select_empty(&self) -> T::Select {
25 let mut select = self.data_source.select();
26 self.source.seed(&mut select);
27
28 for condition in self.conditions.values() {
29 select.add_where_condition(condition.clone());
30 }
31
32 for (expr, direction) in self.order_by.values() {
33 let order = match direction {
34 crate::sorting::SortDirection::Ascending => vantage_expressions::Order::Asc,
35 crate::sorting::SortDirection::Descending => vantage_expressions::Order::Desc,
36 };
37 select.add_order_by(expr.clone(), order);
38 }
39
40 if let Some(pagination) = &self.pagination {
41 select.set_limit(Some(pagination.limit()), Some(pagination.skip()));
42 }
43
44 select
45 }
46
47 pub fn select(&self) -> T::Select {
49 let mut select = self.select_empty();
50
51 for column in self.columns.values() {
53 if let Some(expr_fn) = self.expressions.get(column.name()) {
54 let expr = expr_fn(self);
55 self.data_source.add_select_column(
56 &mut select,
57 expr_any!("({})", (expr)),
58 Some(column.name()),
59 );
60 } else if let Some(alias) = column.alias() {
61 let expr = self.data_source.expr(column.name(), vec![]);
62 self.data_source
63 .add_select_column(&mut select, expr, Some(alias));
64 } else {
65 select.add_field(column.name());
66 }
67 }
68
69 for (name, expr_fn) in &self.expressions {
71 if !self.columns.contains_key(name) {
72 let expr = expr_fn(self);
73 self.data_source.add_select_column(
74 &mut select,
75 expr_any!("({})", (expr)),
76 Some(name),
77 );
78 }
79 }
80
81 select
82 }
83 pub async fn get_count(&self) -> Result<i64> {
85 self.data_source.get_table_count(self).await
86 }
87
88 pub async fn get_sum(&self, column: &T::Column<T::AnyType>) -> Result<T::Value> {
90 self.data_source.get_table_sum(self, column).await
91 }
92
93 pub async fn get_max(&self, column: &T::Column<T::AnyType>) -> Result<T::Value> {
95 self.data_source.get_table_max(self, column).await
96 }
97
98 pub async fn get_min(&self, column: &T::Column<T::AnyType>) -> Result<T::Value> {
100 self.data_source.get_table_min(self, column).await
101 }
102
103 pub fn get_count_query(&self) -> Expression<T::Value> {
106 expr_any!("({})", (self.select_empty().as_count()))
107 }
108
109 pub fn get_sum_query<Type>(&self, column: &T::Column<Type>) -> Expression<T::Value>
112 where
113 Type: ColumnType,
114 T::Column<Type>: Expressive<T::Value>,
115 {
116 expr_any!("({})", (self.select_empty().as_sum(column.expr())))
117 }
118
119 pub fn select_column(&self, field: &str) -> Expression<T::Value>
131 where
132 T::Column<T::AnyType>: Expressive<T::Value>,
133 T::Select: Expressive<T::Value>,
134 {
135 let expr = self.get_column_expr(field).unwrap();
136 let mut select = self.select_empty();
137 select.clear_fields();
138 select.clear_order_by();
139 select.add_expression(expr);
140 select.expr()
141 }
142}
143
144impl<T, E, V, C, S> Table<T, E>
149where
150 T: SelectableDataSource<V, C, Select = S>
151 + TableSource<Value = V, Condition = C, Source = SelectSource<S>>,
152 V: Clone + Send + Sync + 'static + From<String>,
153 C: Clone + Send + Sync + 'static,
154 S: Expressive<V> + Clone,
155 E: Entity<V>,
156{
157 pub fn from_select(data_source: T, alias: impl Into<String>, select: S) -> Self {
160 let alias = alias.into();
161 let mut table = Table::new(alias.clone(), data_source);
162 table.source = SelectSource::query(select, alias);
163 table
164 }
165
166 pub fn derive_from<E2: Entity<V> + 'static>(
175 source: &Table<T, E2>,
176 alias: impl Into<String>,
177 modifier: impl FnOnce(S) -> S,
178 columns: &[&str],
179 relations: &[&str],
180 ) -> Self
181 where
182 T: 'static,
183 E: 'static,
184 {
185 let alias = alias.into();
186 let select = modifier(source.select());
187 let mut table = Table::new(alias.clone(), source.data_source().clone());
188 table.source = SelectSource::query(select, alias);
189 table.copy_columns_from(source, Some(columns));
190 table.copy_relations_from(source, Some(relations));
191 table.id_field = source.id_field.clone();
192 table.title_field = source.title_field.clone();
193 table.title_fields = source.title_fields.clone();
194 table
195 }
196}
197
198impl<T, E> Table<T, E>
200where
201 T: SelectableDataSource<serde_json::Value, T::Condition>
202 + TableSource<Value = serde_json::Value>
203 + vantage_expressions::traits::datasource::ExprDataSource<serde_json::Value>,
204 T::Source: SelectSeed<T::Select, serde_json::Value, T::Condition>,
205 T::Value: From<String>,
206 E: Entity<serde_json::Value>,
207{
208 pub async fn get_count_via_query(&self) -> Result<i64> {
210 let count_query = self.get_count_query();
211 let result = self.data_source.execute(&count_query).await?;
212
213 if let Some(count) = result.get("count").and_then(|v| v.as_i64()) {
215 Ok(count)
216 } else if let Some(count) = result.as_i64() {
217 Ok(count)
218 } else {
219 Ok(0)
220 }
221 }
222}
223
224#[cfg(test)]
225mod tests {
226 use super::*;
227 use crate::mocks::mock_table_source::MockTableSource;
228 use serde_json::json;
229 use vantage_expressions::mocks::datasource::MockSelectableDataSource;
230 use vantage_expressions::traits::datasource::ExprDataSource;
231
232 #[tokio::test]
233 async fn test_selectable_functionality() {
234 let mock_select_source = MockSelectableDataSource::new(json!([
235 {"id": "1", "name": "Alice", "age": 30},
236 {"id": "2", "name": "Bob", "age": 25}
237 ]));
238
239 let mock_query_source = vantage_expressions::mocks::mock_builder::new()
240 .on_exact_select("(SELECT COUNT(*) FROM \"users\")", json!(42));
241
242 let table = MockTableSource::new()
243 .with_data(
244 "users",
245 vec![
246 json!({"id": "1", "name": "Alice", "age": 30}),
247 json!({"id": "2", "name": "Bob", "age": 25}),
248 ],
249 )
250 .await
251 .with_select_source(mock_select_source)
252 .with_query_source(mock_query_source);
253 let table = Table::<_, vantage_types::EmptyEntity>::new("users", table);
254
255 let select = table.select();
257 assert_eq!(select.source(), Some("users"));
258
259 let query_expr: vantage_expressions::Expression<serde_json::Value> = select.into();
261 assert_eq!(query_expr.preview(), "SELECT * FROM users");
262
263 let count_query = table.get_count_query();
265 assert_eq!(count_query.preview(), "(SELECT COUNT(*) FROM \"users\")");
266
267 let count = table.get_count_via_query().await.unwrap();
275 assert_eq!(count, 42);
276 }
277
278 #[tokio::test]
279 #[should_panic(expected = "MockTableSource select source not set")]
280 async fn test_panics_without_select_source() {
281 let table = Table::<_, vantage_types::EmptyEntity>::new("users", MockTableSource::new());
282 let _select = table.select();
283 }
284
285 #[tokio::test]
286 #[should_panic(expected = "MockTableSource query source not set")]
287 async fn test_panics_without_query_source() {
288 let table = Table::<_, vantage_types::EmptyEntity>::new("users", MockTableSource::new());
289 let query = table.data_source().expr("SELECT COUNT(*)", vec![]);
290 let _result = table.data_source().execute(&query).await;
291 }
292}