use serde::{Deserialize, Serialize};
use crate::identifier::{Identifier, QualifiedName};
use crate::ir::column_type::ColumnType;
use crate::ir::difference::Difference;
use crate::ir::eq::{Equiv, field_difference};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Aggregate {
pub qname: QualifiedName,
pub arg_types: Vec<ColumnType>,
pub state_type: ColumnType,
pub sfunc: QualifiedName,
pub finalfunc: Option<QualifiedName>,
pub initcond: Option<String>,
pub owner: Option<Identifier>,
pub comment: Option<String>,
}
impl Equiv for Aggregate {
fn differences(&self, other: &Self) -> Vec<Difference> {
let Self {
qname: _,
arg_types: _,
state_type: _,
sfunc: _,
finalfunc: _,
initcond: _,
owner: _,
comment: _,
} = self;
let mut out = Vec::new();
out.extend(field_difference("qname", &self.qname, &other.qname));
out.extend(field_difference(
"arg_types",
&format!("{:?}", self.arg_types),
&format!("{:?}", other.arg_types),
));
out.extend(field_difference(
"state_type",
&format!("{:?}", self.state_type),
&format!("{:?}", other.state_type),
));
out.extend(field_difference("sfunc", &self.sfunc, &other.sfunc));
out.extend(field_difference(
"finalfunc",
&format!("{:?}", self.finalfunc),
&format!("{:?}", other.finalfunc),
));
out.extend(field_difference(
"initcond",
&format!("{:?}", self.initcond),
&format!("{:?}", other.initcond),
));
out.extend(field_difference(
"owner",
&format!("{:?}", self.owner),
&format!("{:?}", other.owner),
));
out.extend(field_difference(
"comment",
&format!("{:?}", self.comment),
&format!("{:?}", other.comment),
));
out
}
}
#[cfg(test)]
mod tests {
use super::*;
fn id(s: &str) -> Identifier {
Identifier::from_unquoted(s).unwrap()
}
fn qname(schema: &str, name: &str) -> QualifiedName {
QualifiedName::new(id(schema), id(name))
}
fn sample_aggregate() -> Aggregate {
Aggregate {
qname: qname("app", "my_sum"),
arg_types: vec![ColumnType::Integer],
state_type: ColumnType::BigInt,
sfunc: qname("app", "my_sum_sfunc"),
finalfunc: Some(qname("app", "my_sum_final")),
initcond: Some("0".to_string()),
owner: Some(id("app_owner")),
comment: Some("A custom sum aggregate.".to_string()),
}
}
#[test]
fn aggregate_serde_round_trip() {
let agg = sample_aggregate();
let json = serde_json::to_string(&agg).unwrap();
let back: Aggregate = serde_json::from_str(&json).unwrap();
assert_eq!(agg, back);
}
}