sea_schema/postgres/parser/
table_constraints.rs

1use crate::postgres::{def::*, query::TableConstraintsQueryResult};
2use crate::Name;
3
4pub struct TableConstraintsQueryResultParser {
5    curr: Option<TableConstraintsQueryResult>,
6    results: Box<dyn Iterator<Item = TableConstraintsQueryResult>>,
7}
8
9/// Assumed to be ordered by table name, then constraint name, then ordinal position, then the
10/// constraint name of the foreign key, then the ordinal position of the foreign key
11pub fn parse_table_constraint_query_results(
12    results: Box<dyn Iterator<Item = TableConstraintsQueryResult>>,
13) -> impl Iterator<Item = Constraint> {
14    TableConstraintsQueryResultParser {
15        curr: None,
16        results,
17    }
18}
19
20impl Iterator for TableConstraintsQueryResultParser {
21    type Item = Constraint;
22
23    // FIXME/TODO: How to handle invalid input
24    fn next(&mut self) -> Option<Self::Item> {
25        let result = if let Some(result) = self.curr.take() {
26            result
27        } else {
28            self.results.next()?
29        };
30
31        let constraint_name = result.constraint_name;
32        match result.constraint_type.as_str() {
33            "CHECK" => {
34                match result.check_clause {
35                    Some(check_clause) => {
36                        Some(Constraint::Check(Check {
37                            name: constraint_name,
38                            expr: check_clause,
39                            // TODO: How to find?
40                            no_inherit: false,
41                        }))
42                    }
43                    None => self.next(),
44                }
45            }
46
47            "FOREIGN KEY" => {
48                let mut columns = Vec::new();
49                let mut foreign_columns = Vec::new();
50
51                columns.push(result.column_name.unwrap());
52                let table = result.referential_key_table_name.unwrap();
53                foreign_columns.push(result.referential_key_column_name.unwrap());
54                let on_update =
55                    ForeignKeyAction::from_str(&result.update_rule.clone().unwrap_or_default());
56                let on_delete =
57                    ForeignKeyAction::from_str(&result.delete_rule.clone().unwrap_or_default());
58
59                for result in self.results.by_ref() {
60                    if result.constraint_name != constraint_name {
61                        self.curr = Some(result);
62                        return Some(Constraint::References(References {
63                            name: constraint_name,
64                            columns,
65                            table,
66                            foreign_columns,
67                            on_update,
68                            on_delete,
69                        }));
70                    }
71
72                    if result.column_name.is_some() && result.referential_key_column_name.is_some()
73                    {
74                        columns.push(result.column_name.unwrap());
75                        foreign_columns.push(result.referential_key_column_name.unwrap());
76                    }
77                }
78
79                Some(Constraint::References(References {
80                    name: constraint_name,
81                    columns,
82                    table,
83                    foreign_columns,
84                    on_update,
85                    on_delete,
86                }))
87            }
88
89            "PRIMARY KEY" => {
90                let mut columns = vec![result.column_name.unwrap()];
91
92                for result in self.results.by_ref() {
93                    if result.constraint_name != constraint_name {
94                        self.curr = Some(result);
95                        return Some(Constraint::PrimaryKey(PrimaryKey {
96                            name: constraint_name,
97                            columns,
98                        }));
99                    }
100
101                    columns.push(result.column_name.unwrap());
102                }
103
104                Some(Constraint::PrimaryKey(PrimaryKey {
105                    name: constraint_name,
106                    columns,
107                }))
108            }
109
110            "UNIQUE" => {
111                let mut columns = vec![result.column_name.unwrap()];
112
113                for result in self.results.by_ref() {
114                    if result.constraint_name != constraint_name {
115                        self.curr = Some(result);
116                        return Some(Constraint::Unique(Unique {
117                            name: constraint_name,
118                            columns,
119                        }));
120                    }
121
122                    columns.push(result.column_name.unwrap());
123                }
124
125                Some(Constraint::Unique(Unique {
126                    name: constraint_name,
127                    columns,
128                }))
129            }
130
131            _ => {
132                // FIXME: Invalid input error handling
133                None
134            }
135        }
136    }
137}