sql_splitter/schema/
graph.rs1use super::{Schema, TableId};
9use std::collections::VecDeque;
10
11#[derive(Debug)]
20pub struct SchemaGraph {
21 pub schema: Schema,
23 pub parents: Vec<Vec<TableId>>,
25 pub children: Vec<Vec<TableId>>,
27}
28
29#[derive(Debug)]
31pub struct TopoSortResult {
32 pub order: Vec<TableId>,
34 pub cyclic_tables: Vec<TableId>,
36}
37
38impl SchemaGraph {
39 pub fn from_schema(schema: Schema) -> Self {
41 let n = schema.table_schemas.len();
42 let mut parents: Vec<Vec<TableId>> = vec![Vec::new(); n];
43 let mut children: Vec<Vec<TableId>> = vec![Vec::new(); n];
44
45 for table in &schema.table_schemas {
46 let child_id = table.id;
47
48 for fk in &table.foreign_keys {
49 if let Some(parent_id) = fk.referenced_table_id {
50 if parent_id != child_id {
52 if !parents[child_id.0 as usize].contains(&parent_id) {
54 parents[child_id.0 as usize].push(parent_id);
55 }
56 if !children[parent_id.0 as usize].contains(&child_id) {
58 children[parent_id.0 as usize].push(child_id);
59 }
60 }
61 }
62 }
63 }
64
65 Self {
66 schema,
67 parents,
68 children,
69 }
70 }
71
72 pub fn len(&self) -> usize {
74 self.schema.len()
75 }
76
77 pub fn is_empty(&self) -> bool {
79 self.schema.is_empty()
80 }
81
82 pub fn table_name(&self, id: TableId) -> Option<&str> {
84 self.schema.table(id).map(|t| t.name.as_str())
85 }
86
87 pub fn has_self_reference(&self, id: TableId) -> bool {
89 self.schema
90 .table(id)
91 .map(|t| {
92 t.foreign_keys
93 .iter()
94 .any(|fk| fk.referenced_table_id == Some(id))
95 })
96 .unwrap_or(false)
97 }
98
99 pub fn self_referential_tables(&self) -> Vec<TableId> {
101 (0..self.len())
102 .map(|i| TableId(i as u32))
103 .filter(|&id| self.has_self_reference(id))
104 .collect()
105 }
106
107 pub fn topo_sort(&self) -> TopoSortResult {
112 let n = self.len();
113 if n == 0 {
114 return TopoSortResult {
115 order: Vec::new(),
116 cyclic_tables: Vec::new(),
117 };
118 }
119
120 let mut in_degree: Vec<usize> = vec![0; n];
122 for (i, parents) in self.parents.iter().enumerate() {
123 in_degree[i] = parents.len();
124 }
125
126 let mut queue: VecDeque<TableId> = VecDeque::new();
128 for (i, °) in in_degree.iter().enumerate() {
129 if deg == 0 {
130 queue.push_back(TableId(i as u32));
131 }
132 }
133
134 let mut order = Vec::with_capacity(n);
135
136 while let Some(table_id) = queue.pop_front() {
137 order.push(table_id);
138
139 for &child_id in &self.children[table_id.0 as usize] {
141 in_degree[child_id.0 as usize] -= 1;
142 if in_degree[child_id.0 as usize] == 0 {
143 queue.push_back(child_id);
144 }
145 }
146 }
147
148 let cyclic_tables: Vec<TableId> = in_degree
150 .iter()
151 .enumerate()
152 .filter(|(_, °)| deg > 0)
153 .map(|(i, _)| TableId(i as u32))
154 .collect();
155
156 TopoSortResult {
157 order,
158 cyclic_tables,
159 }
160 }
161
162 pub fn processing_order(&self) -> (Vec<TableId>, Vec<TableId>) {
167 let result = self.topo_sort();
168 (result.order, result.cyclic_tables)
169 }
170
171 pub fn is_ancestor(&self, ancestor: TableId, descendant: TableId) -> bool {
173 if ancestor == descendant {
174 return false;
175 }
176
177 let mut visited = vec![false; self.len()];
178 let mut queue = VecDeque::new();
179 queue.push_back(descendant);
180
181 while let Some(current) = queue.pop_front() {
182 for &parent in &self.parents[current.0 as usize] {
183 if parent == ancestor {
184 return true;
185 }
186 if !visited[parent.0 as usize] {
187 visited[parent.0 as usize] = true;
188 queue.push_back(parent);
189 }
190 }
191 }
192
193 false
194 }
195
196 pub fn ancestors(&self, id: TableId) -> Vec<TableId> {
198 let mut ancestors = Vec::new();
199 let mut visited = vec![false; self.len()];
200 let mut queue = VecDeque::new();
201
202 for &parent in &self.parents[id.0 as usize] {
203 queue.push_back(parent);
204 visited[parent.0 as usize] = true;
205 }
206
207 while let Some(current) = queue.pop_front() {
208 ancestors.push(current);
209 for &parent in &self.parents[current.0 as usize] {
210 if !visited[parent.0 as usize] {
211 visited[parent.0 as usize] = true;
212 queue.push_back(parent);
213 }
214 }
215 }
216
217 ancestors
218 }
219
220 pub fn descendants(&self, id: TableId) -> Vec<TableId> {
222 let mut descendants = Vec::new();
223 let mut visited = vec![false; self.len()];
224 let mut queue = VecDeque::new();
225
226 for &child in &self.children[id.0 as usize] {
227 queue.push_back(child);
228 visited[child.0 as usize] = true;
229 }
230
231 while let Some(current) = queue.pop_front() {
232 descendants.push(current);
233 for &child in &self.children[current.0 as usize] {
234 if !visited[child.0 as usize] {
235 visited[child.0 as usize] = true;
236 queue.push_back(child);
237 }
238 }
239 }
240
241 descendants
242 }
243
244 pub fn root_tables(&self) -> Vec<TableId> {
246 self.parents
247 .iter()
248 .enumerate()
249 .filter(|(_, parents)| parents.is_empty())
250 .map(|(i, _)| TableId(i as u32))
251 .collect()
252 }
253
254 pub fn leaf_tables(&self) -> Vec<TableId> {
256 self.children
257 .iter()
258 .enumerate()
259 .filter(|(_, children)| children.is_empty())
260 .map(|(i, _)| TableId(i as u32))
261 .collect()
262 }
263}