uqa_sql/schema/constraint_changes/
names.rs1use super::{ConstraintLocation, ForeignKeyLocation};
10use crate::ast::{
11 ColumnDef, ForeignKey, ReferencedPartitionConstraint, TableCheck, TableConstraintSet,
12 TableKeyConstraint,
13};
14
15#[derive(Clone, Copy)]
16pub struct NamedConstraint<'a> {
17 pub name: &'a str,
18 pub object_id: Option<[u8; 16]>,
19 pub location: ConstraintLocation,
20}
21
22#[cfg(test)]
23mod tests;
24
25#[derive(Clone, Copy)]
26pub struct ConstraintNames<'a> {
27 pub columns: &'a [ColumnDef],
28 pub checks: &'a [TableCheck],
29 pub foreign_keys: &'a [ForeignKey],
30 pub keys: &'a [TableKeyConstraint],
31}
32
33impl<'a> ConstraintNames<'a> {
34 pub fn from_definition(columns: &'a [ColumnDef], constraints: &'a TableConstraintSet) -> Self {
35 Self {
36 columns,
37 checks: &constraints.checks,
38 foreign_keys: &constraints.foreign_keys,
39 keys: &constraints.key_constraints,
40 }
41 }
42
43 pub fn entries(self) -> impl Iterator<Item = NamedConstraint<'a>> {
44 let not_null = self
45 .columns
46 .iter()
47 .enumerate()
48 .filter_map(|(position, column)| {
49 column.not_null.then_some(())?;
50 Some(NamedConstraint {
51 name: column.not_null_name.as_deref()?,
52 object_id: column.not_null_identity.map(|id| id.object_id),
53 location: ConstraintLocation::NotNull(position),
54 })
55 });
56 let column_checks = self
57 .columns
58 .iter()
59 .enumerate()
60 .filter_map(|(position, column)| {
61 column.check.as_ref()?;
62 Some(NamedConstraint {
63 name: column.check_name.as_deref()?,
64 object_id: column.check_object_id,
65 location: ConstraintLocation::ColumnCheck(position),
66 })
67 });
68 let column_foreign_keys =
69 self.columns
70 .iter()
71 .enumerate()
72 .filter_map(|(position, column)| {
73 let key = column.references.as_ref()?;
74 Some(NamedConstraint {
75 name: key.name.as_deref()?,
76 object_id: key.catalog_identity.map(|id| id.object_id),
77 location: ConstraintLocation::ColumnForeignKey(position),
78 })
79 });
80 let checks = self
81 .checks
82 .iter()
83 .enumerate()
84 .filter_map(|(position, check)| {
85 Some(NamedConstraint {
86 name: check.name.as_deref()?,
87 object_id: check.object_id,
88 location: ConstraintLocation::TableCheck(position),
89 })
90 });
91 let foreign_keys = self
92 .foreign_keys
93 .iter()
94 .enumerate()
95 .filter_map(|(position, key)| {
96 Some(NamedConstraint {
97 name: key.name.as_deref()?,
98 object_id: key.catalog_identity.map(|id| id.object_id),
99 location: ConstraintLocation::TableForeignKey(position),
100 })
101 });
102 let keys = self.keys.iter().enumerate().filter_map(|(position, key)| {
103 Some(NamedConstraint {
104 name: key.name.as_deref()?,
105 object_id: key.catalog_identity.map(|id| id.object_id),
106 location: ConstraintLocation::Key(position),
107 })
108 });
109 let column_derived = self
110 .columns
111 .iter()
112 .enumerate()
113 .filter_map(|(position, column)| Some((position, column.references.as_ref()?)))
114 .flat_map(|(position, reference)| {
115 derived_entries(
116 ForeignKeyLocation::Column(position),
117 &reference.referenced_partitions,
118 )
119 });
120 let table_derived =
121 self.foreign_keys
122 .iter()
123 .enumerate()
124 .flat_map(|(position, foreign_key)| {
125 derived_entries(
126 ForeignKeyLocation::Table(position),
127 &foreign_key.referenced_partitions,
128 )
129 });
130 not_null
131 .chain(column_checks)
132 .chain(column_foreign_keys)
133 .chain(checks)
134 .chain(foreign_keys)
135 .chain(keys)
136 .chain(column_derived)
137 .chain(table_derived)
138 }
139}
140
141fn derived_entries(
143 foreign_key: ForeignKeyLocation,
144 constraints: &[ReferencedPartitionConstraint],
145) -> impl Iterator<Item = NamedConstraint<'_>> {
146 constraints
147 .iter()
148 .enumerate()
149 .map(move |(index, constraint)| NamedConstraint {
150 name: &constraint.name,
151 object_id: Some(constraint.catalog_identity.object_id),
152 location: ConstraintLocation::ReferencedPartition(foreign_key, index),
153 })
154}