use serde::{Deserialize, Serialize};
use crate::identifier::Identifier;
use crate::ir::grant::GrantTarget;
use super::change::{Change, ChangeEntry};
use super::destructiveness::Destructiveness;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UnmanagedGrantObservation {
pub object_label: String,
pub privilege_label: String,
pub role_name: Identifier,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct RevokeWithOwnerObservation {
pub object_label: String,
pub privilege_label: String,
pub grantee: GrantTarget,
pub owner: Identifier,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct ChangeSet {
pub entries: Vec<ChangeEntry>,
#[serde(default)]
pub unmanaged_grants: Vec<UnmanagedGrantObservation>,
#[serde(default)]
pub revokes_with_owner: Vec<RevokeWithOwnerObservation>,
}
impl ChangeSet {
pub const fn new() -> Self {
Self {
entries: Vec::new(),
unmanaged_grants: Vec::new(),
revokes_with_owner: Vec::new(),
}
}
pub fn push(&mut self, change: Change, destructiveness: Destructiveness) {
self.entries.push(ChangeEntry {
change,
destructiveness,
});
}
pub const fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub const fn len(&self) -> usize {
self.entries.len()
}
pub fn iter(&self) -> impl Iterator<Item = &ChangeEntry> {
self.entries.iter()
}
pub fn extend(&mut self, other: Self) {
self.entries.extend(other.entries);
self.unmanaged_grants.extend(other.unmanaged_grants);
self.revokes_with_owner.extend(other.revokes_with_owner);
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::identifier::Identifier;
fn id(s: &str) -> Identifier {
Identifier::from_unquoted(s).unwrap()
}
#[test]
fn new_is_empty() {
let cs = ChangeSet::new();
assert!(cs.is_empty());
assert_eq!(cs.len(), 0);
assert!(cs.iter().next().is_none());
}
#[test]
fn push_then_len_is_one() {
let mut cs = ChangeSet::new();
cs.push(
Change::DropSchema(id("old")),
Destructiveness::RequiresApproval {
reason: "drops schema".into(),
},
);
assert!(!cs.is_empty());
assert_eq!(cs.len(), 1);
}
#[test]
fn extend_concatenates() {
let mut a = ChangeSet::new();
a.push(
Change::DropSchema(id("a")),
Destructiveness::RequiresApproval { reason: "x".into() },
);
let mut b = ChangeSet::new();
b.push(
Change::DropSchema(id("b")),
Destructiveness::RequiresApproval { reason: "x".into() },
);
a.extend(b);
assert_eq!(a.len(), 2);
}
}