Skip to main content

uqa_sql/schema/constraint_changes/
names.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Names and independent catalog identities from a borrowed relation declaration.
8
9use super::ConstraintLocation;
10use crate::ast::{ColumnDef, ForeignKey, TableCheck, TableConstraintSet, TableKeyConstraint};
11
12#[derive(Clone, Copy)]
13pub struct NamedConstraint<'a> {
14    pub name: &'a str,
15    pub object_id: Option<[u8; 16]>,
16    pub location: ConstraintLocation,
17}
18
19#[cfg(test)]
20mod tests;
21
22#[derive(Clone, Copy)]
23pub struct ConstraintNames<'a> {
24    pub columns: &'a [ColumnDef],
25    pub checks: &'a [TableCheck],
26    pub foreign_keys: &'a [ForeignKey],
27    pub keys: &'a [TableKeyConstraint],
28}
29
30impl<'a> ConstraintNames<'a> {
31    pub fn from_definition(columns: &'a [ColumnDef], constraints: &'a TableConstraintSet) -> Self {
32        Self {
33            columns,
34            checks: &constraints.checks,
35            foreign_keys: &constraints.foreign_keys,
36            keys: &constraints.key_constraints,
37        }
38    }
39
40    pub fn entries(self) -> impl Iterator<Item = NamedConstraint<'a>> {
41        let not_null = self
42            .columns
43            .iter()
44            .enumerate()
45            .filter_map(|(position, column)| {
46                column.not_null.then_some(())?;
47                Some(NamedConstraint {
48                    name: column.not_null_name.as_deref()?,
49                    object_id: column.not_null_identity.map(|id| id.object_id),
50                    location: ConstraintLocation::NotNull(position),
51                })
52            });
53        let column_checks = self
54            .columns
55            .iter()
56            .enumerate()
57            .filter_map(|(position, column)| {
58                column.check.as_ref()?;
59                Some(NamedConstraint {
60                    name: column.check_name.as_deref()?,
61                    object_id: column.check_object_id,
62                    location: ConstraintLocation::ColumnCheck(position),
63                })
64            });
65        let column_foreign_keys =
66            self.columns
67                .iter()
68                .enumerate()
69                .filter_map(|(position, column)| {
70                    let key = column.references.as_ref()?;
71                    Some(NamedConstraint {
72                        name: key.name.as_deref()?,
73                        object_id: key.catalog_identity.map(|id| id.object_id),
74                        location: ConstraintLocation::ColumnForeignKey(position),
75                    })
76                });
77        let checks = self
78            .checks
79            .iter()
80            .enumerate()
81            .filter_map(|(position, check)| {
82                Some(NamedConstraint {
83                    name: check.name.as_deref()?,
84                    object_id: check.object_id,
85                    location: ConstraintLocation::TableCheck(position),
86                })
87            });
88        let foreign_keys = self
89            .foreign_keys
90            .iter()
91            .enumerate()
92            .filter_map(|(position, key)| {
93                Some(NamedConstraint {
94                    name: key.name.as_deref()?,
95                    object_id: key.catalog_identity.map(|id| id.object_id),
96                    location: ConstraintLocation::TableForeignKey(position),
97                })
98            });
99        let keys = self.keys.iter().enumerate().filter_map(|(position, key)| {
100            Some(NamedConstraint {
101                name: key.name.as_deref()?,
102                object_id: key.catalog_identity.map(|id| id.object_id),
103                location: ConstraintLocation::Key(position),
104            })
105        });
106        not_null
107            .chain(column_checks)
108            .chain(column_foreign_keys)
109            .chain(checks)
110            .chain(foreign_keys)
111            .chain(keys)
112    }
113}