Skip to main content

pgevolve_core/ir/
aggregate.rs

1//! `AGGREGATE` IR — a schema-scoped object. Ordinary aggregates only
2//! (state function + state type + optional final function / initcond).
3
4use serde::{Deserialize, Serialize};
5
6use crate::identifier::{Identifier, QualifiedName};
7use crate::ir::column_type::ColumnType;
8
9/// A `CREATE AGGREGATE` object. Identity is `(qname, arg_types)`.
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
11pub struct Aggregate {
12    /// Schema-qualified aggregate name.
13    pub qname: QualifiedName,
14    /// Aggregate argument types (part of identity; aggregates are overloadable).
15    pub arg_types: Vec<ColumnType>,
16    /// State type (`STYPE`).
17    pub state_type: ColumnType,
18    /// State transition function (`SFUNC`) — a managed function name.
19    pub sfunc: QualifiedName,
20    /// Optional final function (`FINALFUNC`).
21    pub finalfunc: Option<QualifiedName>,
22    /// Optional initial condition (`INITCOND`), as text.
23    pub initcond: Option<String>,
24    /// Lenient owner (`None` = unmanaged).
25    pub owner: Option<Identifier>,
26    /// Optional comment.
27    pub comment: Option<String>,
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33
34    fn id(s: &str) -> Identifier {
35        Identifier::from_unquoted(s).unwrap()
36    }
37
38    fn qname(schema: &str, name: &str) -> QualifiedName {
39        QualifiedName::new(id(schema), id(name))
40    }
41
42    fn sample_aggregate() -> Aggregate {
43        Aggregate {
44            qname: qname("app", "my_sum"),
45            arg_types: vec![ColumnType::Integer],
46            state_type: ColumnType::BigInt,
47            sfunc: qname("app", "my_sum_sfunc"),
48            finalfunc: Some(qname("app", "my_sum_final")),
49            initcond: Some("0".to_string()),
50            owner: Some(id("app_owner")),
51            comment: Some("A custom sum aggregate.".to_string()),
52        }
53    }
54
55    #[test]
56    fn aggregate_serde_round_trip() {
57        let agg = sample_aggregate();
58        let json = serde_json::to_string(&agg).unwrap();
59        let back: Aggregate = serde_json::from_str(&json).unwrap();
60        assert_eq!(agg, back);
61    }
62}