1use std::marker::PhantomData;
2use std::sync::Arc;
3
4use indexmap::IndexMap;
5use vantage_expressions::Expression;
6use vantage_types::{EmptyEntity, Entity};
7
8use crate::{
9 pagination::Pagination, references::Reference, sorting::SortDirection,
10 traits::table_source::TableSource, traits::table_source_spec::TableSourceSpec,
11};
12
13pub type ExpressionFn<T> =
22 Arc<dyn Fn(&Table<T, EmptyEntity>) -> Expression<<T as TableSource>::Value> + Send + Sync>;
23
24#[derive(Clone)]
25pub struct Table<T, E>
26where
27 T: TableSource,
28 E: Entity<T::Value>,
29{
30 pub(super) data_source: T,
31 pub(super) _phantom: PhantomData<E>,
32 pub(super) source: T::Source,
33 pub(super) columns: IndexMap<String, T::Column<T::AnyType>>,
34 pub(super) conditions: IndexMap<i64, T::Condition>,
35 pub(super) next_condition_id: i64,
36 pub(super) order_by: IndexMap<i64, (T::Condition, SortDirection)>,
37 pub(super) next_order_id: i64,
38 pub(super) refs: Option<IndexMap<String, Arc<dyn Reference>>>,
39 pub(super) contained: Vec<crate::references::ContainedRelation<T>>,
40 pub(super) expressions: IndexMap<String, ExpressionFn<T>>,
41 pub(super) pagination: Option<Pagination>,
42 pub(super) title_field: Option<String>,
43 pub(super) title_fields: Vec<String>,
44 pub(super) id_field: Option<String>,
45}
46
47impl<T: TableSource, E: Entity<T::Value>> Table<T, E> {
48 pub fn new(table_name: impl Into<String>, data_source: T) -> Self {
50 Self {
51 data_source,
52 _phantom: PhantomData,
53 source: T::Source::from_name(table_name.into()),
54 columns: IndexMap::new(),
55 conditions: IndexMap::new(),
56 next_condition_id: 1,
57 order_by: IndexMap::new(),
58 next_order_id: 1,
59 refs: None,
60 contained: Vec::new(),
61 expressions: IndexMap::new(),
62 pagination: None,
63 title_field: None,
64 title_fields: Vec::new(),
65 id_field: None,
66 }
67 }
68
69 pub fn into_entity<E2: Entity<T::Value>>(self) -> Table<T, E2> {
75 Table {
76 data_source: self.data_source,
77 _phantom: PhantomData,
78 source: self.source,
79 columns: self.columns,
80 conditions: self.conditions,
81 next_condition_id: self.next_condition_id,
82 order_by: self.order_by,
83 next_order_id: self.next_order_id,
84 refs: self.refs,
85 contained: self.contained,
86 expressions: self.expressions,
87 pagination: self.pagination,
88 title_field: self.title_field,
89 title_fields: self.title_fields,
90 id_field: self.id_field,
91 }
92 }
93
94 pub(crate) fn as_entity_erased(&self) -> &Table<T, EmptyEntity> {
101 unsafe { &*(self as *const Table<T, E> as *const Table<T, EmptyEntity>) }
104 }
105
106 pub fn vista_references(&self) -> Vec<vantage_vista::Reference> {
111 self.refs
112 .as_ref()
113 .map(|refs| {
114 refs.iter()
115 .map(|(name, r)| {
116 vantage_vista::Reference::new(
117 name.clone(),
118 r.target_type_name().to_string(),
119 r.cardinality(),
120 r.foreign_key().to_string(),
121 )
122 })
123 .collect()
124 })
125 .unwrap_or_default()
126 }
127
128 pub fn vista_contained(&self) -> Vec<vantage_vista::ContainedSpec> {
133 self.contained.iter().map(|c| c.spec()).collect()
134 }
135
136 pub fn contained_relation(
138 &self,
139 name: &str,
140 ) -> Option<&crate::references::ContainedRelation<T>> {
141 self.contained.iter().find(|c| c.name() == name)
142 }
143
144 pub fn with<F>(mut self, func: F) -> Self
146 where
147 F: FnOnce(&mut Self),
148 {
149 func(&mut self);
150 self
151 }
152
153 pub fn table_name(&self) -> &str {
157 self.source.name()
158 }
159
160 pub fn source(&self) -> &T::Source {
162 &self.source
163 }
164
165 pub fn set_table_name(&mut self, name: impl Into<String>) {
172 self.source = T::Source::from_name(name.into());
173 }
174
175 pub fn data_source(&self) -> &T {
177 &self.data_source
178 }
179
180 pub fn title_field(&self) -> Option<&T::Column<T::AnyType>> {
182 self.title_field
183 .as_ref()
184 .and_then(|name| self.columns.get(name))
185 }
186
187 pub fn title_fields(&self) -> &[String] {
191 &self.title_fields
192 }
193
194 pub fn id_field(&self) -> Option<&T::Column<T::AnyType>> {
196 self.id_field
197 .as_ref()
198 .and_then(|name| self.columns.get(name))
199 }
200
201 pub fn set_id_field(&mut self, name: impl Into<String>) {
208 self.id_field = Some(name.into());
209 }
210
211 pub fn add_title_field(&mut self, name: impl Into<String>) {
215 let name = name.into();
216 if !self.title_fields.contains(&name) {
217 self.title_fields.push(name.clone());
218 }
219 if self.title_field.is_none() {
220 self.title_field = Some(name);
221 }
222 }
223
224 pub fn pagination(&self) -> Option<&Pagination> {
226 self.pagination.as_ref()
227 }
228}
229
230impl<T: TableSource, E: Entity<T::Value>> std::ops::Index<&str> for Table<T, E> {
231 type Output = T::Column<T::AnyType>;
232
233 fn index(&self, index: &str) -> &Self::Output {
234 &self.columns[index]
235 }
236}
237
238impl<T: TableSource, E: Entity<T::Value>> std::fmt::Debug for Table<T, E> {
239 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
240 f.debug_struct("Table")
241 .field("table_name", &self.table_name())
242 .field("columns", &self.columns.keys().collect::<Vec<_>>())
243 .field("conditions_count", &self.conditions.len())
244 .field(
245 "refs_count",
246 &self.refs.as_ref().map(|r| r.len()).unwrap_or(0),
247 )
248 .field("expressions_count", &self.expressions.len())
249 .finish()
250 }
251}