Skip to main content

schema_model/model/
aggregation.rs

1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2pub enum AggregationType {
3    Sum,
4    Count,
5}
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub enum AggregationFrequency {
9    Daily,
10    Weekly,
11    Monthly,
12    Yearly,
13}
14
15#[derive(Debug, Clone)]
16pub struct AggregationGroup {
17    source: String,
18    destination: String,
19    source_derived_from: Option<String>,
20}
21
22impl AggregationGroup {
23    pub fn new<S: Into<String>>(source: S, destination: S, source_derived_from: Option<S>) -> Self {
24        Self {
25            source: source.into(),
26            destination: destination.into(),
27            source_derived_from: source_derived_from.map(|s| s.into()),
28        }
29    }
30
31    pub fn source(&self) -> &str {
32        &self.source
33    }
34
35    pub fn destination(&self) -> &str {
36        &self.destination
37    }
38
39    pub fn source_derived_from(&self) -> Option<&str> {
40        self.source_derived_from.as_deref()
41    }
42}
43
44#[derive(Debug, Clone)]
45pub struct AggregationColumn {
46    aggregation_type: AggregationType,
47    source_column: String,
48    destination_column: String,
49}
50
51impl AggregationColumn {
52    pub fn new<S: Into<String>>(
53        aggregation_type: AggregationType,
54        source_column: S,
55        destination_column: S,
56    ) -> Self {
57        Self {
58            aggregation_type,
59            source_column: source_column.into(),
60            destination_column: destination_column.into(),
61        }
62    }
63
64    pub fn aggregation_type(&self) -> AggregationType {
65        self.aggregation_type
66    }
67    pub fn source_column(&self) -> &str {
68        &self.source_column
69    }
70    pub fn destination_column(&self) -> &str {
71        &self.destination_column
72    }
73}
74
75#[derive(Debug, Clone)]
76pub struct Aggregation {
77    destination_table: String,
78    date_column: String,
79    criteria: Option<String>,
80    time_stamp_column: String,
81    aggregation_frequency: AggregationFrequency,
82    aggregation_columns: Vec<AggregationColumn>,
83    aggregation_groups: Vec<AggregationGroup>,
84}
85
86impl Aggregation {
87    #[allow(clippy::too_many_arguments)]
88    pub fn new<S: Into<String>>(
89        destination_table: S,
90        date_column: S,
91        criteria: Option<S>,
92        time_stamp_column: S,
93        aggregation_frequency: AggregationFrequency,
94        aggregation_columns: Vec<AggregationColumn>,
95        aggregation_groups: Vec<AggregationGroup>,
96    ) -> Self {
97        Self {
98            destination_table: destination_table.into(),
99            date_column: date_column.into(),
100            criteria: criteria.map(|s| s.into()),
101            time_stamp_column: time_stamp_column.into(),
102            aggregation_frequency,
103            aggregation_columns,
104            aggregation_groups,
105        }
106    }
107
108    pub fn destination_table(&self) -> &str {
109        &self.destination_table
110    }
111
112    pub fn date_column(&self) -> &str {
113        &self.date_column
114    }
115
116    pub fn criteria(&self) -> Option<&str> {
117        self.criteria.as_deref()
118    }
119
120    pub fn time_stamp_column(&self) -> &str {
121        &self.time_stamp_column
122    }
123
124    pub fn aggregation_frequency(&self) -> AggregationFrequency {
125        self.aggregation_frequency
126    }
127
128    pub fn aggregation_groups(&self) -> &Vec<AggregationGroup> {
129        &self.aggregation_groups
130    }
131
132    pub fn aggregation_columns(&self) -> &Vec<AggregationColumn> {
133        &self.aggregation_columns
134    }
135}
136
137#[cfg(test)]
138mod tests {
139    use super::*;
140
141    #[test]
142    fn aggregation_group_new_and_getters() {
143        let g = AggregationGroup::new("src", "dest", Some("derived"));
144        assert_eq!(g.source(), "src");
145        assert_eq!(g.destination(), "dest");
146        assert_eq!(g.source_derived_from().unwrap(), "derived");
147    }
148
149    #[test]
150    fn aggregation_column_new_and_getters() {
151        let c = AggregationColumn::new(AggregationType::Sum, "s_col", "d_col");
152        assert_eq!(c.aggregation_type(), AggregationType::Sum);
153        assert_eq!(c.source_column(), "s_col");
154        assert_eq!(c.destination_column(), "d_col");
155    }
156
157    #[test]
158    fn aggregation_new_and_getters() {
159        let cols = vec![
160            AggregationColumn::new(AggregationType::Sum, "a", "a_sum"),
161            AggregationColumn::new(AggregationType::Count, "b", "b_cnt"),
162        ];
163        let groups = vec![
164            AggregationGroup::new("src1", "dst1", Some("from1")),
165            AggregationGroup::new("src2", "dst2", Some("from2")),
166        ];
167        let aggr = Aggregation::new(
168            "dest_table",
169            "date_col",
170            Some("criteria"),
171            "ts_col",
172            AggregationFrequency::Monthly,
173            cols.clone(),
174            groups.clone(),
175        );
176
177        assert_eq!(aggr.destination_table(), "dest_table");
178        assert_eq!(aggr.date_column(), "date_col");
179        assert_eq!(aggr.criteria().unwrap(), "criteria");
180        assert_eq!(aggr.time_stamp_column(), "ts_col");
181        assert_eq!(aggr.aggregation_frequency(), AggregationFrequency::Monthly);
182        assert_eq!(aggr.aggregation_columns().len(), 2);
183        assert_eq!(aggr.aggregation_groups().len(), 2);
184
185        // Spot-check preserved content
186        assert_eq!(aggr.aggregation_columns()[0].source_column(), "a");
187        assert_eq!(
188            aggr.aggregation_columns()[1].aggregation_type(),
189            AggregationType::Count
190        );
191        assert_eq!(aggr.aggregation_groups()[0].destination(), "dst1");
192        assert_eq!(aggr.aggregation_groups()[1].source_derived_from().unwrap(), "from2");
193
194        // Ensure vectors returned are the same size as provided (by value semantics they were moved in)
195        assert_eq!(aggr.aggregation_columns().len(), cols.len());
196        assert_eq!(aggr.aggregation_groups().len(), groups.len());
197    }
198}