pgevolve_core/ir/
statistic.rs1use serde::{Deserialize, Serialize};
11
12use crate::identifier::{Identifier, QualifiedName};
13use crate::ir::default_expr::NormalizedExpr;
14use crate::ir::difference::Difference;
15use crate::ir::eq::{Equiv, field_difference};
16
17#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19pub struct Statistic {
20 pub qname: QualifiedName,
22 pub target: QualifiedName,
24 pub kinds: StatisticKinds,
26 pub columns: Vec<StatisticColumn>,
28 pub statistics_target: Option<i32>,
31 pub owner: Option<Identifier>,
33 pub comment: Option<String>,
35}
36
37impl Equiv for Statistic {
38 fn differences(&self, other: &Self) -> Vec<Difference> {
39 let Self {
42 qname: _,
43 target: _,
44 kinds: _,
45 columns: _,
46 statistics_target: _,
47 owner: _,
48 comment: _,
49 } = self;
50 let mut out = Vec::new();
51 out.extend(field_difference("qname", &self.qname, &other.qname));
52 out.extend(field_difference("target", &self.target, &other.target));
53 out.extend(field_difference(
54 "kinds",
55 &format!("{:?}", self.kinds),
56 &format!("{:?}", other.kinds),
57 ));
58 out.extend(field_difference(
59 "columns",
60 &format!("{:?}", self.columns),
61 &format!("{:?}", other.columns),
62 ));
63 out.extend(field_difference(
64 "statistics_target",
65 &format!("{:?}", self.statistics_target),
66 &format!("{:?}", other.statistics_target),
67 ));
68 out.extend(field_difference(
69 "owner",
70 &format!("{:?}", self.owner),
71 &format!("{:?}", other.owner),
72 ));
73 out.extend(field_difference(
74 "comment",
75 &format!("{:?}", self.comment),
76 &format!("{:?}", other.comment),
77 ));
78 out
79 }
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
84pub struct StatisticKinds {
85 pub ndistinct: bool,
87 pub dependencies: bool,
89 pub mcv: bool,
91}
92
93impl StatisticKinds {
94 #[must_use]
96 pub const fn pg_default() -> Self {
97 Self {
98 ndistinct: true,
99 dependencies: true,
100 mcv: true,
101 }
102 }
103
104 #[must_use]
107 pub const fn is_empty(&self) -> bool {
108 !self.ndistinct && !self.dependencies && !self.mcv
109 }
110}
111
112#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
114pub enum StatisticColumn {
115 Column(Identifier),
117 Expression(NormalizedExpr),
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
127 fn kinds_default_is_all_true() {
128 let k = StatisticKinds::pg_default();
129 assert!(k.ndistinct && k.dependencies && k.mcv);
130 assert!(!k.is_empty());
131 }
132
133 #[test]
134 fn kinds_empty_when_all_false() {
135 let k = StatisticKinds {
136 ndistinct: false,
137 dependencies: false,
138 mcv: false,
139 };
140 assert!(k.is_empty());
141 }
142
143 #[test]
144 fn column_form_does_not_equal_expression_form() {
145 let c = StatisticColumn::Column(Identifier::from_unquoted("a").unwrap());
146 let e = StatisticColumn::Expression(NormalizedExpr::from_text("lower(a)"));
147 assert_ne!(c, e);
148 }
149}