vantage_table/table/
base.rs1use std::marker::PhantomData;
2use std::sync::Arc;
3
4use indexmap::IndexMap;
5use vantage_expressions::Expression;
6use vantage_types::Entity;
7
8use crate::{
9 pagination::Pagination, references::Reference, sorting::SortDirection,
10 traits::table_source::TableSource,
11};
12
13pub type ExpressionFn<T, E> =
15 Arc<dyn Fn(&Table<T, E>) -> Expression<<T as TableSource>::Value> + Send + Sync>;
16
17#[derive(Clone)]
18pub struct Table<T, E>
19where
20 T: TableSource,
21 E: Entity<T::Value>,
22{
23 pub(super) data_source: T,
24 pub(super) _phantom: PhantomData<E>,
25 pub(super) table_name: String,
26 pub(super) columns: IndexMap<String, T::Column<T::AnyType>>,
27 pub(super) conditions: IndexMap<i64, T::Condition>,
28 pub(super) next_condition_id: i64,
29 pub(super) order_by: IndexMap<i64, (T::Condition, SortDirection)>,
30 pub(super) next_order_id: i64,
31 pub(super) refs: Option<IndexMap<String, Arc<dyn Reference>>>,
32 pub(super) expressions: IndexMap<String, ExpressionFn<T, E>>,
33 pub(super) pagination: Option<Pagination>,
34 pub(super) title_field: Option<String>,
35 pub(super) title_fields: Vec<String>,
36 pub(super) id_field: Option<String>,
37}
38
39impl<T: TableSource, E: Entity<T::Value>> Table<T, E> {
40 pub fn new(table_name: impl Into<String>, data_source: T) -> Self {
42 Self {
43 data_source,
44 _phantom: PhantomData,
45 table_name: table_name.into(),
46 columns: IndexMap::new(),
47 conditions: IndexMap::new(),
48 next_condition_id: 1,
49 order_by: IndexMap::new(),
50 next_order_id: 1,
51 refs: None,
52 expressions: IndexMap::new(),
53 pagination: None,
54 title_field: None,
55 title_fields: Vec::new(),
56 id_field: None,
57 }
58 }
59
60 pub fn into_entity<E2: Entity<T::Value>>(self) -> Table<T, E2> {
62 Table {
63 data_source: self.data_source,
64 _phantom: PhantomData,
65 table_name: self.table_name,
66 columns: self.columns,
67 conditions: self.conditions,
68 next_condition_id: self.next_condition_id,
69 order_by: self.order_by,
70 next_order_id: self.next_order_id,
71 refs: self.refs,
72 expressions: IndexMap::new(),
73 pagination: self.pagination,
74 title_field: self.title_field,
75 title_fields: self.title_fields,
76 id_field: self.id_field,
77 }
78 }
79
80 pub fn vista_references(&self) -> Vec<vantage_vista::Reference> {
85 self.refs
86 .as_ref()
87 .map(|refs| {
88 refs.iter()
89 .map(|(name, r)| {
90 vantage_vista::Reference::new(
91 name.clone(),
92 r.target_type_name().to_string(),
93 r.cardinality(),
94 r.foreign_key().to_string(),
95 )
96 })
97 .collect()
98 })
99 .unwrap_or_default()
100 }
101
102 pub fn with<F>(mut self, func: F) -> Self
104 where
105 F: FnOnce(&mut Self),
106 {
107 func(&mut self);
108 self
109 }
110
111 pub fn table_name(&self) -> &str {
113 &self.table_name
114 }
115
116 pub fn set_table_name(&mut self, name: impl Into<String>) {
120 self.table_name = name.into();
121 }
122
123 pub fn data_source(&self) -> &T {
125 &self.data_source
126 }
127
128 pub(crate) fn conditions_mut(&mut self) -> &mut IndexMap<i64, T::Condition> {
130 &mut self.conditions
131 }
132
133 pub(crate) fn next_condition_id_mut(&mut self) -> &mut i64 {
135 &mut self.next_condition_id
136 }
137
138 pub fn title_field(&self) -> Option<&T::Column<T::AnyType>> {
140 self.title_field
141 .as_ref()
142 .and_then(|name| self.columns.get(name))
143 }
144
145 pub fn title_fields(&self) -> &[String] {
149 &self.title_fields
150 }
151
152 pub fn id_field(&self) -> Option<&T::Column<T::AnyType>> {
154 self.id_field
155 .as_ref()
156 .and_then(|name| self.columns.get(name))
157 }
158
159 pub fn set_id_field(&mut self, name: impl Into<String>) {
166 self.id_field = Some(name.into());
167 }
168
169 pub fn add_title_field(&mut self, name: impl Into<String>) {
173 let name = name.into();
174 if !self.title_fields.contains(&name) {
175 self.title_fields.push(name.clone());
176 }
177 if self.title_field.is_none() {
178 self.title_field = Some(name);
179 }
180 }
181
182 pub fn pagination(&self) -> Option<&Pagination> {
184 self.pagination.as_ref()
185 }
186}
187
188impl<T: TableSource, E: Entity<T::Value>> std::ops::Index<&str> for Table<T, E> {
189 type Output = T::Column<T::AnyType>;
190
191 fn index(&self, index: &str) -> &Self::Output {
192 &self.columns[index]
193 }
194}
195
196impl<T: TableSource, E: Entity<T::Value>> std::fmt::Debug for Table<T, E> {
197 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
198 f.debug_struct("Table")
199 .field("table_name", &self.table_name)
200 .field("columns", &self.columns.keys().collect::<Vec<_>>())
201 .field("conditions_count", &self.conditions.len())
202 .field(
203 "refs_count",
204 &self.refs.as_ref().map(|r| r.len()).unwrap_or(0),
205 )
206 .field("expressions_count", &self.expressions.len())
207 .finish()
208 }
209}