use serde::{Deserialize, Serialize};
use crate::identifier::Identifier;
use crate::ir::difference::Difference;
use crate::ir::eq::{Equiv, field_difference};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Schema {
pub name: Identifier,
pub comment: Option<String>,
pub owner: Option<Identifier>,
pub grants: Vec<crate::ir::grant::Grant>,
}
impl Equiv for Schema {
fn differences(&self, other: &Self) -> Vec<Difference> {
let Self {
name: _,
comment: _,
owner: _,
grants: _,
} = self;
let mut out = Vec::new();
out.extend(field_difference("name", &self.name, &other.name));
out.extend(field_difference(
"comment",
&format!("{:?}", self.comment),
&format!("{:?}", other.comment),
));
out.extend(field_difference(
"owner",
&format!("{:?}", self.owner),
&format!("{:?}", other.owner),
));
out.extend(field_difference(
"grants",
&format!("{:?}", self.grants),
&format!("{:?}", other.grants),
));
out
}
}
impl Schema {
pub const fn new(name: Identifier) -> Self {
Self {
name,
comment: None,
owner: None,
grants: Vec::new(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::identifier::Identifier;
use crate::ir::eq::Equiv;
fn id(s: &str) -> Identifier {
Identifier::from_unquoted(s).unwrap()
}
fn base() -> Schema {
Schema::new(id("app"))
}
#[test]
fn equal_schemas_have_no_diff() {
assert!(base().canonical_eq(&base()));
}
#[test]
fn different_names_diff() {
let a = base();
let b = Schema::new(id("billing"));
let d = a.differences(&b);
assert_eq!(d.len(), 1);
assert_eq!(d[0].path, "name");
}
#[test]
fn comment_diffs() {
let mut b = base();
b.comment = Some("v2".into());
let d = base().differences(&b);
assert_eq!(d.len(), 1);
assert_eq!(d[0].path, "comment");
}
#[test]
fn owner_change_diffs() {
let mut b = base();
b.owner = Some(id("new_owner"));
assert!(base().differences(&b).iter().any(|x| x.path == "owner"));
}
#[test]
fn grants_change_diffs() {
let mut b = base();
b.grants.push(crate::ir::grant::Grant {
grantee: crate::ir::grant::GrantTarget::Public,
privilege: crate::ir::grant::Privilege::Usage,
with_grant_option: false,
columns: None,
});
assert!(base().differences(&b).iter().any(|x| x.path == "grants"));
}
}