uqa_sql/schema/table_creation/
keys.rs1use crate::ast::{ColumnDef, ColumnType, CreateTable, TableKeyConstraint, TableKeyConstraintKind};
10use crate::schema::columns::POSTGRES_SYSTEM_COLUMNS;
11use crate::schema::constraint_metadata::{
12 identity::materialize_key_identity, materialize_foreign_key_identity, CatalogIdentityAllocator,
13 ConstraintMetadataError,
14};
15use crate::schema::indexes::names::{ConstraintIndexNamer, IndexNameCatalog};
16use crate::schema::indexes::unique::{
17 validate_partitioned_key_constraint, validate_partitioned_unique_key, PartitionedUniqueKey,
18};
19use crate::schema::inheritance::InheritanceContext;
20use crate::schema::keys::definition::{
21 index_order, missing_key_column, multiple_primary_keys, repeated_key_column,
22 validate_key_definition, validate_overlaps_column, validate_overlaps_key_length, KeyRelation,
23};
24use crate::SQLError;
25
26#[cfg(test)]
27mod tests;
28
29#[derive(Debug, Clone, PartialEq, Default)]
31pub struct InheritedDefinitions {
32 pub expressions: Vec<String>,
34 pub not_nulls: Vec<super::not_nulls::InheritedNotNull>,
36 pub keys: usize,
38 pub foreign_keys: usize,
40 pub unique_indexes: Vec<Vec<crate::ast::IndexKey>>,
42}
43
44pub fn transform_declared_keys(
46 context: &InheritanceContext<'_>,
47 table: &mut CreateTable,
48) -> Result<(), SQLError> {
49 let mut columns = KeyColumns {
50 context,
51 declared: &table.columns,
52 parents: &table.hierarchy.parents,
53 inherited: Vec::new(),
54 };
55 let mut primary_key = false;
56 for key in &table.key_constraints {
57 if key.kind == TableKeyConstraintKind::PrimaryKey {
58 if primary_key {
59 return Err(multiple_primary_keys(&table.qualifier));
60 }
61 primary_key = true;
62 }
63 validate_declared_key(&mut columns, key)?;
64 }
65 table.key_constraints = index_order(std::mem::take(&mut table.key_constraints));
66 for column in &mut table.columns {
68 column.primary_key = false;
69 column.unique = false;
70 }
71 Ok(())
72}
73
74struct KeyColumns<'s, 'c> {
76 context: &'s InheritanceContext<'c>,
77 declared: &'s [ColumnDef],
78 parents: &'s [String],
79 inherited: Vec<Vec<ColumnDef>>,
80}
81
82enum KeyColumn {
83 Column(ColumnType),
84 System,
85}
86
87impl KeyColumns<'_, '_> {
88 fn find(&mut self, name: &str) -> Result<Option<KeyColumn>, SQLError> {
89 if let Some(column) = self.declared.iter().find(|column| column.name == name) {
90 return Ok(Some(KeyColumn::Column(column.ty.clone())));
91 }
92 if POSTGRES_SYSTEM_COLUMNS.contains(&name) {
93 return Ok(Some(KeyColumn::System));
94 }
95 for (position, requested) in self.parents.iter().enumerate() {
96 if position == self.inherited.len() {
97 let parent = self.context.catalog.resolve_parent(requested)?;
98 let columns = self
99 .context
100 .partitions
101 .catalog
102 .try_describe_table(&parent)
103 .map_err(|error| {
104 SQLError::Internal(format!("read inherited row type: {error}"))
105 })?
106 .ok_or_else(|| SQLError::UnknownTable(parent.clone()))?;
107 self.inherited.push(columns);
108 }
109 if let Some(column) = self.inherited[position]
110 .iter()
111 .find(|column| column.name == name)
112 {
113 return Ok(Some(KeyColumn::Column(column.ty.clone())));
114 }
115 }
116 Ok(None)
117 }
118}
119
120fn validate_declared_key(
121 columns: &mut KeyColumns<'_, '_>,
122 key: &TableKeyConstraint,
123) -> Result<(), SQLError> {
124 for (position, name) in key.columns.iter().enumerate() {
125 let Some(column) = columns.find(name)? else {
126 return Err(missing_key_column(name));
127 };
128 if key.columns[..position].contains(name) {
129 return Err(repeated_key_column(key.kind, name));
130 }
131 if key.without_overlaps && position + 1 == key.columns.len() {
132 let ty = match &column {
133 KeyColumn::Column(ty) => Some(ty),
134 KeyColumn::System => None,
135 };
136 validate_overlaps_column(name, ty)?;
137 }
138 }
139 validate_overlaps_key_length(key)?;
140 for name in &key.included_columns {
141 if columns.find(name)?.is_none() {
142 return Err(missing_key_column(name));
143 }
144 }
145 Ok(())
146}
147
148pub fn declare_primary_key_not_null(columns: &mut [ColumnDef], keys: &[TableKeyConstraint]) {
150 for key in keys
151 .iter()
152 .filter(|key| key.kind == TableKeyConstraintKind::PrimaryKey)
153 {
154 for name in &key.columns {
155 let Some(column) = columns.iter_mut().find(|column| column.name == *name) else {
156 continue;
157 };
158 if column.not_null && column.not_null_is_local {
159 continue;
160 }
161 if column.not_null {
162 column.not_null_name = None;
163 column.not_null_identity = None;
164 }
165 column.not_null = true;
166 column.not_null_is_local = true;
167 column.not_null_validated = true;
168 }
169 }
170}
171
172pub fn clone_parent_keys<'a>(
174 catalog: &'a dyn IndexNameCatalog,
175 table: &mut CreateTable,
176 inherited: &InheritedDefinitions,
177 allocate: &mut CatalogIdentityAllocator<'_>,
178) -> Result<ConstraintIndexNamer<'a>, SQLError> {
179 let mut indexes = ConstraintIndexNamer::new(catalog, &table.name)?;
180 indexes.occupy(
181 table
182 .checks
183 .iter()
184 .filter(|check| !check.is_local)
185 .filter_map(|check| check.name.clone()),
186 );
187 let partition = table.hierarchy.partition_spec.as_ref();
188 for key in &mut table.key_constraints[..inherited.keys] {
189 if let Some(partition) = partition {
190 validate_partitioned_key_constraint(&table.name, key, partition)?;
191 }
192 indexes.name(key)?;
193 materialize_key_identity(key, allocate).map_err(ConstraintMetadataError::into_sql_error)?;
194 }
195 for foreign_key in &mut table.foreign_keys[..inherited.foreign_keys] {
196 materialize_foreign_key_identity(
197 &mut foreign_key.object_id,
198 &mut foreign_key.catalog_identity,
199 allocate,
200 )
201 .map_err(ConstraintMetadataError::into_sql_error)?;
202 }
203 if let Some(partition) = partition {
204 for keys in &inherited.unique_indexes {
205 let columns = keys
206 .iter()
207 .map(crate::ast::IndexKey::column)
208 .collect::<Vec<_>>();
209 validate_partitioned_unique_key(
210 &table.name,
211 &PartitionedUniqueKey {
212 constraint_type: TableKeyConstraintKind::Unique,
213 columns: &columns,
214 without_overlaps: false,
215 },
216 partition,
217 )?;
218 }
219 }
220 Ok(indexes)
221}
222
223pub fn define_declared_keys(
225 mut indexes: ConstraintIndexNamer<'_>,
226 table: &mut CreateTable,
227 inherited: &InheritedDefinitions,
228 allocate: &mut CatalogIdentityAllocator<'_>,
229) -> Result<(), SQLError> {
230 indexes.occupy(
231 table
232 .columns
233 .iter()
234 .flat_map(|column| [column.not_null_name.clone(), column.check_name.clone()])
235 .chain(table.checks.iter().map(|check| check.name.clone()))
236 .flatten(),
237 );
238 let inherited_primary_key = table.key_constraints[..inherited.keys]
239 .iter()
240 .any(|key| key.kind == TableKeyConstraintKind::PrimaryKey);
241 let partition = table.hierarchy.partition_spec.as_ref();
242 let declared = &mut table.key_constraints[inherited.keys..];
243 for key in declared.iter_mut() {
244 validate_key_definition(
245 &KeyRelation {
246 table: &table.name,
247 columns: &table.columns,
248 partition,
249 has_primary_key: inherited_primary_key,
250 },
251 key,
252 )?;
253 indexes.name(key)?;
254 materialize_key_identity(key, allocate).map_err(ConstraintMetadataError::into_sql_error)?;
255 }
256 mark_single_column_keys(&mut table.columns, &table.key_constraints[inherited.keys..]);
257 Ok(())
258}
259
260fn mark_single_column_keys(columns: &mut [ColumnDef], keys: &[TableKeyConstraint]) {
262 for key in keys {
263 let [name] = key.columns.as_slice() else {
264 continue;
265 };
266 let Some(column) = columns.iter_mut().find(|column| column.name == *name) else {
267 continue;
268 };
269 match key.kind {
270 TableKeyConstraintKind::PrimaryKey => column.primary_key = true,
271 TableKeyConstraintKind::Unique => column.unique = true,
272 }
273 }
274}