1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Type {
    Check,
    Foreign,
    PrimaryKey,
    Trigger,
    Unique,
    Exclusion,
}

impl crate::ToText for Type {
    fn to_text(&self) -> crate::Result<String> {
        let s = match self {
            Type::Check => "c",
            Type::Foreign => "f",
            Type::PrimaryKey => "p",
            Type::Trigger => "t",
            Type::Unique => "u",
            Type::Exclusion => "x",
        };

        Ok(s.to_string())
    }
}

impl crate::FromText for Type {
    fn from_text(raw: &str) -> crate::Result<Self> {
        let ty = match raw {
            "c" => Self::Check,
            "f" => Self::Foreign,
            "p" => Self::PrimaryKey,
            "t" => Self::Trigger,
            "u" => Self::Unique,
            "x" => Self::Exclusion,
            _ => return Err(Self::error(raw)),
        };

        Ok(ty)
    }
}

#[derive(Clone, Debug, Eq, PartialEq, elephantry_derive::Entity, elephantry_derive::Composite)]
#[elephantry(internal)]
pub struct Constraint {
    pub oid: crate::pq::Oid,
    pub ty: Type,
    pub name: String,
    pub definition: String,
}

/**
 * Retreive constraints.
 */
pub fn constraints(
    connection: &crate::Connection,
    oid: crate::pq::Oid,
) -> crate::Result<Vec<Constraint>> {
    connection
        .query(
            "
select oid, contype as ty, conname as name, pg_get_constraintdef(oid) as definition
    from pg_catalog.pg_constraint
    where contypid = $1
        or conrelid = $1;
",
            &[&oid],
        )
        .map(Iterator::collect)
}

#[derive(Clone, Debug, Eq, PartialEq, elephantry_derive::Entity, elephantry_derive::Composite)]
#[elephantry(internal)]
pub struct Index {
    pub oid: crate::pq::Oid,
    pub name: String,
    pub definition: String,
}

/**
 * Retreive relation indexes.
 */
pub fn indexes(
    connection: &crate::Connection,
    relation: &crate::inspect::Relation,
) -> crate::Result<Vec<Index>> {
    connection
        .query(
            r#"
select i.indexrelid as oid, c.relname as name, pg_get_indexdef(c.oid) as definition
    from pg_index i
    join pg_class c on c.oid = i.indexrelid
    left join pg_constraint x on x.conindid = c.oid
    where i.indrelid = $1
        and x.oid is null;
"#,
            &[&relation.oid],
        )
        .map(Iterator::collect)
}