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 with<F>(mut self, func: F) -> Self
82 where
83 F: FnOnce(&mut Self),
84 {
85 func(&mut self);
86 self
87 }
88
89 pub fn table_name(&self) -> &str {
91 &self.table_name
92 }
93
94 pub fn data_source(&self) -> &T {
96 &self.data_source
97 }
98
99 pub(crate) fn conditions_mut(&mut self) -> &mut IndexMap<i64, T::Condition> {
101 &mut self.conditions
102 }
103
104 pub(crate) fn next_condition_id_mut(&mut self) -> &mut i64 {
106 &mut self.next_condition_id
107 }
108
109 pub fn title_field(&self) -> Option<&T::Column<T::AnyType>> {
111 self.title_field
112 .as_ref()
113 .and_then(|name| self.columns.get(name))
114 }
115
116 pub fn title_fields(&self) -> &[String] {
120 &self.title_fields
121 }
122
123 pub fn id_field(&self) -> Option<&T::Column<T::AnyType>> {
125 self.id_field
126 .as_ref()
127 .and_then(|name| self.columns.get(name))
128 }
129
130 pub fn pagination(&self) -> Option<&Pagination> {
132 self.pagination.as_ref()
133 }
134}
135
136impl<T: TableSource, E: Entity<T::Value>> std::ops::Index<&str> for Table<T, E> {
137 type Output = T::Column<T::AnyType>;
138
139 fn index(&self, index: &str) -> &Self::Output {
140 &self.columns[index]
141 }
142}
143
144impl<T: TableSource, E: Entity<T::Value>> std::fmt::Debug for Table<T, E> {
145 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146 f.debug_struct("Table")
147 .field("table_name", &self.table_name)
148 .field("columns", &self.columns.keys().collect::<Vec<_>>())
149 .field("conditions_count", &self.conditions.len())
150 .field(
151 "refs_count",
152 &self.refs.as_ref().map(|r| r.len()).unwrap_or(0),
153 )
154 .field("expressions_count", &self.expressions.len())
155 .finish()
156 }
157}