uqa_sql/schema/inheritance/
detachment.rs1use crate::ast::{ColumnDef, TableConstraintSet};
10use crate::catalog::constraints::{
11 constraint_identities_match, foreign_key_identity, ConstraintIdentity,
12};
13use crate::SQLError;
14use std::collections::BTreeMap;
15
16pub type ConstraintIdentityChange = (ConstraintIdentity, ConstraintIdentity);
17
18pub fn split_foreign_key_families(
19 table: &str,
20 columns: &mut [ColumnDef],
21 constraints: &mut TableConstraintSet,
22 replacements: &BTreeMap<[u8; 16], [u8; 16]>,
23) -> Result<Vec<ConstraintIdentityChange>, SQLError> {
24 let mut changes = Vec::new();
25 for column in columns {
26 let Some(reference) = column.references.as_ref() else {
27 continue;
28 };
29 let Some(replacement) = reference.object_id.and_then(|id| replacements.get(&id)) else {
30 continue;
31 };
32 let before = foreign_key_identity(
33 table,
34 &crate::schema::foreign_keys::column_foreign_key(column, reference),
35 )?;
36 column
37 .references
38 .as_mut()
39 .expect("selected reference")
40 .object_id = Some(*replacement);
41 let mut after = before.clone();
42 after.object_id = Some(*replacement);
43 changes.push((before, after));
44 }
45 for key in &mut constraints.foreign_keys {
46 let Some(replacement) = key.object_id.and_then(|id| replacements.get(&id)) else {
47 continue;
48 };
49 let before = foreign_key_identity(table, key)?;
50 key.object_id = Some(*replacement);
51 changes.push((before, foreign_key_identity(table, key)?));
52 }
53 for key in &mut constraints.hierarchy.partition_inherited_foreign_keys {
54 if let Some(replacement) = key.object_id.and_then(|id| replacements.get(&id)) {
55 key.object_id = Some(*replacement);
56 }
57 }
58 Ok(changes)
59}
60
61pub fn preserve_split_constraint_modes(
63 named: &mut BTreeMap<ConstraintIdentity, bool>,
64 retained: &[ConstraintIdentity],
65 detached: &[ConstraintIdentityChange],
66) {
67 let changes: Vec<_> = retained
68 .iter()
69 .map(|identity| (identity, identity))
70 .chain(detached.iter().map(|(before, after)| (before, after)))
71 .filter_map(|(before, after)| {
72 named.iter().find_map(|(identity, deferred)| {
73 constraint_identities_match(before, identity).then_some((after.clone(), *deferred))
74 })
75 })
76 .collect();
77 named.extend(changes);
78}
79
80#[cfg(test)]
81mod tests;