Skip to main content

uqa_sql/schema/
table_alteration.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Bind inherited ALTER declarations and their durable constraint identities.
8use super::constraint_metadata::CatalogIdentityAllocator;
9use crate::{
10    ast::{AlterTableAction, ColumnDef, TableConstraintSet},
11    SQLError,
12};
13use uqa_core::RelationIdentity;
14
15pub fn normalize_inherited_action(action: &mut AlterTableAction, is_partition: bool) {
16    if let AlterTableAction::AddColumn { column, .. } = action {
17        column.not_null_is_local = !column.not_null;
18        column.not_null_identity = None;
19        if is_partition {
20            if let Some(reference) = &mut column.references {
21                reference.catalog_identity = None;
22            }
23        } else {
24            column.references = None;
25        }
26        column.check_is_local = column.check.is_none();
27        column.check_object_id = None;
28        column.check_catalog_oid = None;
29        if column.check_no_inherit {
30            column.check = None;
31            column.check_name = None;
32            column.check_is_local = true;
33            column.check_no_inherit = false;
34        }
35    }
36    if let AlterTableAction::AddCheckConstraint { constraint } = action {
37        constraint.is_local = false;
38        constraint.object_id = None;
39        constraint.catalog_oid = None;
40    }
41}
42
43pub fn materialize_recursive_action_names(
44    relation: &RelationIdentity,
45    columns: &mut Vec<ColumnDef>,
46    constraints: &mut TableConstraintSet,
47    action: &mut AlterTableAction,
48    allocate: &mut CatalogIdentityAllocator<'_>,
49    names: &super::constraint_metadata::ConstraintNameScope,
50) -> Result<(), SQLError> {
51    match action {
52        AlterTableAction::AddColumn { column, checks, .. } => {
53            columns.push(column.clone());
54            let existing_checks = constraints.checks.len();
55            constraints.checks.extend(checks.iter().cloned());
56            super::constraint_metadata::materialize_constraint_metadata_with_names(
57                relation,
58                columns,
59                constraints,
60                allocate,
61                names,
62            )
63            .map_err(|error| {
64                crate::catalog::errors::storage_error("ALTER TABLE ADD COLUMN", &error)
65            })?;
66            *column = columns
67                .pop()
68                .ok_or_else(|| SQLError::Internal("new column disappeared".into()))?;
69            *checks = constraints.checks.split_off(existing_checks);
70        }
71        AlterTableAction::AddCheckConstraint { constraint }
72            if !constraint.no_inherit && constraint.name.is_none() =>
73        {
74            constraints.checks.push(constraint.clone());
75            super::constraint_metadata::materialize_constraint_metadata_with_names(
76                relation,
77                columns,
78                constraints,
79                allocate,
80                names,
81            )
82            .map_err(|error| {
83                crate::catalog::errors::storage_error("ALTER TABLE ADD CONSTRAINT", &error)
84            })?;
85            *constraint = constraints
86                .checks
87                .pop()
88                .ok_or_else(|| SQLError::Internal("new CHECK constraint disappeared".into()))?;
89        }
90        AlterTableAction::AddNotNullConstraint {
91            name,
92            column,
93            validated,
94            no_inherit: false,
95        } if name.is_none() => {
96            if let Some(definition) = columns
97                .iter_mut()
98                .find(|definition| definition.name == *column && !definition.not_null)
99            {
100                definition.not_null = true;
101                definition.not_null_explicit = true;
102                definition.not_null_validated = *validated;
103                super::constraint_metadata::materialize_constraint_metadata_with_names(
104                    relation,
105                    columns,
106                    constraints,
107                    allocate,
108                    names,
109                )
110                .map_err(|error| {
111                    crate::catalog::errors::storage_error("ALTER TABLE ADD CONSTRAINT", &error)
112                })?;
113                *name = columns
114                    .iter()
115                    .find(|definition| definition.name == *column)
116                    .and_then(|definition| definition.not_null_name.clone());
117            }
118        }
119        _ => {}
120    }
121    Ok(())
122}
123
124pub mod syntax;
125pub mod targets;