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, table::hooks::Hooks,
10 traits::table_source::TableSource, traits::table_source_spec::TableSourceSpec,
11};
12
13mod accessors;
14mod computed;
15mod relations;
16
17pub type ExpressionFn<T> =
20 Arc<dyn Fn(&Table<T, EmptyEntity>) -> Expression<<T as TableSource>::Value> + Send + Sync>;
21
22pub type LazyExpressionFn<T> = Arc<
26 dyn Fn(
27 &vantage_types::Record<<T as TableSource>::Value>,
28 ) -> std::pin::Pin<
29 Box<
30 dyn std::future::Future<Output = vantage_core::Result<<T as TableSource>::Value>>
31 + Send,
32 >,
33 > + Send
34 + Sync,
35>;
36
37#[derive(Clone)]
38pub struct Table<T, E>
39where
40 T: TableSource,
41 E: Entity<T::Value>,
42{
43 pub(super) data_source: T,
44 pub(super) _phantom: PhantomData<E>,
45 pub(super) source: T::Source,
46 pub(super) columns: IndexMap<String, T::Column<T::AnyType>>,
47 pub(super) conditions: IndexMap<i64, T::Condition>,
48 pub(super) next_condition_id: i64,
49 pub(super) order_by: IndexMap<i64, (T::Condition, SortDirection)>,
50 pub(super) next_order_id: i64,
51 pub(super) refs: Option<IndexMap<String, Arc<dyn Reference>>>,
52 pub(super) contained: Vec<crate::references::ContainedRelation<T>>,
53 pub(super) expressions: IndexMap<String, ExpressionFn<T>>,
54 pub(super) lazy_expressions: IndexMap<String, LazyExpressionFn<T>>,
55 pub(super) computed_columns: IndexMap<String, (usize, vantage_vista::Column)>,
58 pub(super) active_columns: Option<indexmap::IndexSet<String>>,
61 pub(super) imported_columns: indexmap::IndexSet<String>,
65 pub(super) pagination: Option<Pagination>,
66 pub(super) title_field: Option<String>,
67 pub(super) title_fields: Vec<String>,
68 pub(super) id_field: Option<String>,
69 pub(super) id_text: bool,
71 pub(super) id_auto: bool,
73 pub(super) invariants: IndexMap<String, T::Value>,
75 pub(super) hooks: Hooks<T>,
76 pub(super) lock: bool,
78}
79
80impl<T: TableSource, E: Entity<T::Value>> Table<T, E> {
81 pub fn new(table_name: impl Into<String>, data_source: T) -> Self {
83 Self {
84 data_source,
85 _phantom: PhantomData,
86 source: T::Source::from_name(table_name.into()),
87 columns: IndexMap::new(),
88 conditions: IndexMap::new(),
89 next_condition_id: 1,
90 order_by: IndexMap::new(),
91 next_order_id: 1,
92 refs: None,
93 contained: Vec::new(),
94 expressions: IndexMap::new(),
95 lazy_expressions: IndexMap::new(),
96 computed_columns: IndexMap::new(),
97 active_columns: None,
98 imported_columns: indexmap::IndexSet::new(),
99 pagination: None,
100 title_field: None,
101 title_fields: Vec::new(),
102 id_field: None,
103 id_text: false,
104 id_auto: false,
105 invariants: IndexMap::new(),
106 hooks: Hooks::default(),
107 lock: false,
108 }
109 }
110
111 pub fn into_entity<E2: Entity<T::Value>>(self) -> Table<T, E2> {
117 Table {
118 data_source: self.data_source,
119 _phantom: PhantomData,
120 source: self.source,
121 columns: self.columns,
122 conditions: self.conditions,
123 next_condition_id: self.next_condition_id,
124 order_by: self.order_by,
125 next_order_id: self.next_order_id,
126 refs: self.refs,
127 contained: self.contained,
128 expressions: self.expressions,
129 lazy_expressions: self.lazy_expressions,
130 computed_columns: self.computed_columns,
131 active_columns: self.active_columns,
132 imported_columns: self.imported_columns,
133 pagination: self.pagination,
134 title_field: self.title_field,
135 title_fields: self.title_fields,
136 id_field: self.id_field,
137 id_text: self.id_text,
138 id_auto: self.id_auto,
139 invariants: self.invariants,
140 hooks: self.hooks,
141 lock: self.lock,
142 }
143 }
144
145 pub(crate) fn as_entity_erased(&self) -> &Table<T, EmptyEntity> {
152 unsafe { &*(self as *const Table<T, E> as *const Table<T, EmptyEntity>) }
155 }
156}
157
158impl<T: TableSource, E: Entity<T::Value>> std::ops::Index<&str> for Table<T, E> {
159 type Output = T::Column<T::AnyType>;
160
161 fn index(&self, index: &str) -> &Self::Output {
162 &self.columns[index]
163 }
164}
165
166impl<T: TableSource, E: Entity<T::Value>> std::fmt::Debug for Table<T, E> {
167 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168 f.debug_struct("Table")
169 .field("table_name", &self.table_name())
170 .field("columns", &self.columns.keys().collect::<Vec<_>>())
171 .field("conditions_count", &self.conditions.len())
172 .field(
173 "refs_count",
174 &self.refs.as_ref().map(|r| r.len()).unwrap_or(0),
175 )
176 .field("expressions_count", &self.expressions.len())
177 .finish()
178 }
179}