Skip to main content

uqa_sql/schema/sequences/
implicit_ownership.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Resolve declared SERIAL and IDENTITY owners against the loaded sequence namespace.
8use super::implicit::stored_owner_names_current;
9use crate::ast::ColumnDef;
10use uqa_core::RelationIdentity;
11
12pub trait StoredSequenceNames {
13    fn stored_sequence_name(&self, reference: &str) -> Result<String, String>;
14}
15pub struct BoundImplicitSequenceOwner {
16    pub sequence: String,
17    pub table_object_id: [u8; 16],
18    pub column_object_id: [u8; 16],
19    pub identity: bool,
20}
21pub fn bind_implicit_sequence_owners(
22    catalog: &dyn StoredSequenceNames,
23    table_name: &str,
24    table_object_id: [u8; 16],
25    columns: &[ColumnDef],
26) -> Result<Vec<BoundImplicitSequenceOwner>, String> {
27    let relation = RelationIdentity::from_legacy_name(table_name)?;
28    let mut bindings = Vec::new();
29    for column in columns {
30        let Some(provenance) = column.auto_increment.as_ref() else {
31            continue;
32        };
33        let Some(named_owner) = provenance.owner.as_ref() else {
34            continue;
35        };
36        if !stored_owner_names_current(&relation, column, named_owner) {
37            continue;
38        }
39        let Some(sequence) = provenance.sequence.as_deref() else {
40            continue;
41        };
42        let sequence = catalog.stored_sequence_name(sequence)?;
43        let column_object_id = column.object_id.ok_or_else(|| {
44            format!(
45                "column `{table_name}`.`{}` has no object identity",
46                column.name
47            )
48        })?;
49        bindings.push(BoundImplicitSequenceOwner {
50            sequence,
51            table_object_id,
52            column_object_id,
53            identity: provenance.is_identity(),
54        });
55    }
56    Ok(bindings)
57}
58
59/// Remove legacy named owner markers for one canonically identified sequence.
60pub fn clear_auto_increment_owner_markers(
61    columns: &mut [crate::ast::ColumnDef],
62    target: &uqa_core::RelationIdentity,
63) -> bool {
64    let mut changed = false;
65    for column in columns {
66        let Some(provenance) = column.auto_increment.as_mut() else {
67            continue;
68        };
69        if provenance.owner.is_some()
70            && provenance.sequence.as_deref().is_some_and(|reference| {
71                crate::schema::dependencies::rewrites::stored_relation_reference_matches(
72                    reference, target,
73                )
74            })
75        {
76            provenance.owner = None;
77            changed = true;
78        }
79    }
80    changed
81}