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}
77
78impl<T: TableSource, E: Entity<T::Value>> Table<T, E> {
79 pub fn new(table_name: impl Into<String>, data_source: T) -> Self {
81 Self {
82 data_source,
83 _phantom: PhantomData,
84 source: T::Source::from_name(table_name.into()),
85 columns: IndexMap::new(),
86 conditions: IndexMap::new(),
87 next_condition_id: 1,
88 order_by: IndexMap::new(),
89 next_order_id: 1,
90 refs: None,
91 contained: Vec::new(),
92 expressions: IndexMap::new(),
93 lazy_expressions: IndexMap::new(),
94 computed_columns: IndexMap::new(),
95 active_columns: None,
96 imported_columns: indexmap::IndexSet::new(),
97 pagination: None,
98 title_field: None,
99 title_fields: Vec::new(),
100 id_field: None,
101 id_text: false,
102 id_auto: false,
103 invariants: IndexMap::new(),
104 hooks: Hooks::default(),
105 }
106 }
107
108 pub fn into_entity<E2: Entity<T::Value>>(self) -> Table<T, E2> {
114 Table {
115 data_source: self.data_source,
116 _phantom: PhantomData,
117 source: self.source,
118 columns: self.columns,
119 conditions: self.conditions,
120 next_condition_id: self.next_condition_id,
121 order_by: self.order_by,
122 next_order_id: self.next_order_id,
123 refs: self.refs,
124 contained: self.contained,
125 expressions: self.expressions,
126 lazy_expressions: self.lazy_expressions,
127 computed_columns: self.computed_columns,
128 active_columns: self.active_columns,
129 imported_columns: self.imported_columns,
130 pagination: self.pagination,
131 title_field: self.title_field,
132 title_fields: self.title_fields,
133 id_field: self.id_field,
134 id_text: self.id_text,
135 id_auto: self.id_auto,
136 invariants: self.invariants,
137 hooks: self.hooks,
138 }
139 }
140
141 pub(crate) fn as_entity_erased(&self) -> &Table<T, EmptyEntity> {
148 unsafe { &*(self as *const Table<T, E> as *const Table<T, EmptyEntity>) }
151 }
152}
153
154impl<T: TableSource, E: Entity<T::Value>> std::ops::Index<&str> for Table<T, E> {
155 type Output = T::Column<T::AnyType>;
156
157 fn index(&self, index: &str) -> &Self::Output {
158 &self.columns[index]
159 }
160}
161
162impl<T: TableSource, E: Entity<T::Value>> std::fmt::Debug for Table<T, E> {
163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164 f.debug_struct("Table")
165 .field("table_name", &self.table_name())
166 .field("columns", &self.columns.keys().collect::<Vec<_>>())
167 .field("conditions_count", &self.conditions.len())
168 .field(
169 "refs_count",
170 &self.refs.as_ref().map(|r| r.len()).unwrap_or(0),
171 )
172 .field("expressions_count", &self.expressions.len())
173 .finish()
174 }
175}