pgevolve_core/ir/
aggregate.rs1use serde::{Deserialize, Serialize};
5
6use crate::identifier::{Identifier, QualifiedName};
7use crate::ir::column_type::ColumnType;
8use crate::ir::difference::Difference;
9use crate::ir::eq::{Equiv, field_difference};
10
11#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13pub struct Aggregate {
14 pub qname: QualifiedName,
16 pub arg_types: Vec<ColumnType>,
18 pub state_type: ColumnType,
20 pub sfunc: QualifiedName,
22 pub finalfunc: Option<QualifiedName>,
24 pub initcond: Option<String>,
26 pub owner: Option<Identifier>,
28 pub comment: Option<String>,
30}
31
32impl Equiv for Aggregate {
33 fn differences(&self, other: &Self) -> Vec<Difference> {
34 let Self {
37 qname: _,
38 arg_types: _,
39 state_type: _,
40 sfunc: _,
41 finalfunc: _,
42 initcond: _,
43 owner: _,
44 comment: _,
45 } = self;
46 let mut out = Vec::new();
47 out.extend(field_difference("qname", &self.qname, &other.qname));
48 out.extend(field_difference(
49 "arg_types",
50 &format!("{:?}", self.arg_types),
51 &format!("{:?}", other.arg_types),
52 ));
53 out.extend(field_difference(
54 "state_type",
55 &format!("{:?}", self.state_type),
56 &format!("{:?}", other.state_type),
57 ));
58 out.extend(field_difference("sfunc", &self.sfunc, &other.sfunc));
59 out.extend(field_difference(
60 "finalfunc",
61 &format!("{:?}", self.finalfunc),
62 &format!("{:?}", other.finalfunc),
63 ));
64 out.extend(field_difference(
65 "initcond",
66 &format!("{:?}", self.initcond),
67 &format!("{:?}", other.initcond),
68 ));
69 out.extend(field_difference(
70 "owner",
71 &format!("{:?}", self.owner),
72 &format!("{:?}", other.owner),
73 ));
74 out.extend(field_difference(
75 "comment",
76 &format!("{:?}", self.comment),
77 &format!("{:?}", other.comment),
78 ));
79 out
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 fn id(s: &str) -> Identifier {
88 Identifier::from_unquoted(s).unwrap()
89 }
90
91 fn qname(schema: &str, name: &str) -> QualifiedName {
92 QualifiedName::new(id(schema), id(name))
93 }
94
95 fn sample_aggregate() -> Aggregate {
96 Aggregate {
97 qname: qname("app", "my_sum"),
98 arg_types: vec![ColumnType::Integer],
99 state_type: ColumnType::BigInt,
100 sfunc: qname("app", "my_sum_sfunc"),
101 finalfunc: Some(qname("app", "my_sum_final")),
102 initcond: Some("0".to_string()),
103 owner: Some(id("app_owner")),
104 comment: Some("A custom sum aggregate.".to_string()),
105 }
106 }
107
108 #[test]
109 fn aggregate_serde_round_trip() {
110 let agg = sample_aggregate();
111 let json = serde_json::to_string(&agg).unwrap();
112 let back: Aggregate = serde_json::from_str(&json).unwrap();
113 assert_eq!(agg, back);
114 }
115}