uqa_sql/schema/sequences/
owner_migration.rs1use super::implicit::stored_owner_names_current;
9use uqa_core::{
10 catalog_sequence::{SequenceOwner, SequenceOwnerDependency},
11 RelationIdentity,
12};
13pub fn resolve_migrated_sequence_reference(
14 reference: &str,
15 sequences: &[RelationIdentity],
16) -> Result<RelationIdentity, String> {
17 let (schema, name) = RelationIdentity::parse_reference(reference)?;
18 let candidates = sequences
19 .iter()
20 .filter(|candidate| {
21 candidate.name == name
22 && schema
23 .as_ref()
24 .is_none_or(|schema| candidate.schema == *schema)
25 })
26 .cloned()
27 .collect::<Vec<_>>();
28 match candidates.as_slice() {
29 [target] => Ok(target.clone()),
30 [] => Err(format!(
31 "implicit sequence owner references missing sequence `{reference}`"
32 )),
33 _ => Err(format!(
34 "implicit sequence owner reference `{reference}` is ambiguous"
35 )),
36 }
37}
38pub fn collect_migrated_sequence_owner(
39 relation: &RelationIdentity,
40 table_object_id: [u8; 16],
41 column: &crate::ast::ColumnDef,
42 sequence_relations: &[RelationIdentity],
43 valid_owners: &mut std::collections::BTreeSet<([u8; 16], [u8; 16])>,
44 inferred: &mut std::collections::BTreeMap<RelationIdentity, SequenceOwner>,
45) -> Result<(), String> {
46 let relation_name = relation.qualified_name();
47 let column_object_id = column.object_id.ok_or_else(|| {
48 format!(
49 "column `{relation_name}`.`{}` has no object identity during sequence-owner migration",
50 column.name
51 )
52 })?;
53 valid_owners.insert((table_object_id, column_object_id));
54 let Some(provenance) = column.auto_increment.as_ref() else {
55 return Ok(());
56 };
57 let Some(named_owner) = provenance.owner.as_ref() else {
58 return Ok(());
59 };
60 if !stored_owner_names_current(relation, column, named_owner) {
61 return Ok(());
62 }
63 let Some(sequence) = provenance.sequence.as_deref() else {
64 return Ok(());
65 };
66 let sequence = resolve_migrated_sequence_reference(sequence, sequence_relations)?;
67 let owner = SequenceOwner {
68 table_object_id,
69 column_object_id,
70 dependency: if provenance.is_identity() {
71 SequenceOwnerDependency::Internal
72 } else {
73 SequenceOwnerDependency::Automatic
74 },
75 };
76 if inferred
77 .insert(sequence.clone(), owner)
78 .is_some_and(|old| old != owner)
79 {
80 return Err(format!(
81 "sequence `{}` has conflicting implicit owners",
82 sequence.qualified_name()
83 ));
84 }
85 Ok(())
86}
87
88#[cfg(test)]
89mod tests;