1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use indexmap::IndexMap;
use crate::{
column::Column,
reference::{ContainedSpec, Reference},
};
/// Schema a `Vista` is built around.
///
/// Driver factories produce one of these by inspecting a typed
/// `Table<DriverSource, E>`; the universal YAML loader produces one by
/// parsing config. End-user code typically doesn't construct this directly.
///
/// Title columns are derived from column flags at runtime — see
/// `Vista::get_title_columns`.
#[derive(Debug, Clone, Default)]
pub struct VistaMetadata {
pub columns: IndexMap<String, Column>,
pub references: IndexMap<String, Reference>,
/// Contained (embedded-in-row) relations, keyed by relation name. Kept
/// apart from `references` because their data lives in a column of the
/// parent row, not in a joined table.
pub contained: IndexMap<String, ContainedSpec>,
pub id_column: Option<String>,
}
impl VistaMetadata {
pub fn new() -> Self {
Self::default()
}
pub fn with_column(mut self, column: Column) -> Self {
self.columns.insert(column.name.clone(), column);
self
}
/// [`with_column`](Self::with_column) at position `index` (clamped to the
/// end), shifting later columns along.
pub fn with_column_at(mut self, index: usize, column: Column) -> Self {
let index = index.min(self.columns.len());
self.columns
.shift_insert(index, column.name.clone(), column);
self
}
/// [`with_column_at`](Self::with_column_at) for each `(position, column)`,
/// in order — the shape of `Table::computed_columns`.
pub fn with_columns_at<'a>(
self,
columns: impl IntoIterator<Item = (usize, &'a Column)>,
) -> Self {
columns.into_iter().fold(self, |metadata, (at, column)| {
metadata.with_column_at(at, column.clone())
})
}
pub fn with_reference(mut self, reference: Reference) -> Self {
self.references.insert(reference.name.clone(), reference);
self
}
pub fn with_contained(mut self, spec: ContainedSpec) -> Self {
self.contained.insert(spec.name.clone(), spec);
self
}
pub fn with_id_column(mut self, name: impl Into<String>) -> Self {
self.id_column = Some(name.into());
self
}
}