Skip to main content

pgevolve_core/ir/
schema.rs

1//! `Schema` — a Postgres namespace.
2
3use serde::{Deserialize, Serialize};
4
5use crate::identifier::Identifier;
6use crate::ir::eq::DiffMacro;
7
8/// A Postgres schema (namespace).
9#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, DiffMacro)]
10pub struct Schema {
11    /// Schema name.
12    pub name: Identifier,
13    /// Optional comment.
14    #[diff(via_debug)]
15    pub comment: Option<String>,
16    /// Object owner. `None` = unmanaged (the differ ignores ownership).
17    /// `Some(role)` = managed: diff emits `ALTER SCHEMA ... OWNER TO role`.
18    #[diff(via_debug)]
19    pub owner: Option<Identifier>,
20    /// Grants on this object. Empty = no grants. Canonicalized.
21    #[diff(via_debug)]
22    pub grants: Vec<crate::ir::grant::Grant>,
23}
24
25impl Schema {
26    /// Construct a `Schema`.
27    pub const fn new(name: Identifier) -> Self {
28        Self {
29            name,
30            comment: None,
31            owner: None,
32            grants: Vec::new(),
33        }
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40    use crate::identifier::Identifier;
41    use crate::ir::eq::Diff;
42
43    fn id(s: &str) -> Identifier {
44        Identifier::from_unquoted(s).unwrap()
45    }
46
47    fn base() -> Schema {
48        Schema::new(id("app"))
49    }
50
51    #[test]
52    fn equal_schemas_have_no_diff() {
53        assert!(base().canonical_eq(&base()));
54    }
55
56    #[test]
57    fn different_names_diff() {
58        let a = base();
59        let b = Schema::new(id("billing"));
60        let d = a.diff(&b);
61        assert_eq!(d.len(), 1);
62        assert_eq!(d[0].path, "name");
63    }
64
65    #[test]
66    fn comment_diffs() {
67        let mut b = base();
68        b.comment = Some("v2".into());
69        let d = base().diff(&b);
70        assert_eq!(d.len(), 1);
71        assert_eq!(d[0].path, "comment");
72    }
73
74    #[test]
75    fn owner_change_diffs() {
76        let mut b = base();
77        b.owner = Some(id("new_owner"));
78        assert!(base().diff(&b).iter().any(|x| x.path == "owner"));
79    }
80
81    #[test]
82    fn grants_change_diffs() {
83        let mut b = base();
84        b.grants.push(crate::ir::grant::Grant {
85            grantee: crate::ir::grant::GrantTarget::Public,
86            privilege: crate::ir::grant::Privilege::Usage,
87            with_grant_option: false,
88            columns: None,
89        });
90        assert!(base().diff(&b).iter().any(|x| x.path == "grants"));
91    }
92}