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 {
17        column,
18        key_constraints,
19        ..
20    } = action
21    {
22        // A child does not inherit the indexes of its parent's keys; a partition receives copies from the parent's partitioned indexes.
23        key_constraints.clear();
24        column.primary_key = false;
25        column.unique = false;
26        column.not_null_is_local = !column.not_null;
27        column.not_null_identity = None;
28        column.default_catalog_oid = None;
29        if is_partition {
30            if let Some(reference) = &mut column.references {
31                reference.catalog_identity = None;
32            }
33        } else {
34            column.references = None;
35        }
36        column.check_is_local = column.check.is_none();
37        column.check_object_id = None;
38        column.check_catalog_oid = None;
39        if column.check_no_inherit {
40            column.check = None;
41            column.check_name = None;
42            column.check_is_local = true;
43            column.check_no_inherit = false;
44        }
45    }
46    if let AlterTableAction::AddCheckConstraint { constraint } = action {
47        constraint.is_local = false;
48        constraint.object_id = None;
49        constraint.catalog_oid = None;
50    }
51}
52
53pub fn materialize_recursive_action_names(
54    relation: &RelationIdentity,
55    columns: &mut Vec<ColumnDef>,
56    constraints: &mut TableConstraintSet,
57    action: &mut AlterTableAction,
58    allocate: &mut CatalogIdentityAllocator<'_>,
59    names: &super::constraint_metadata::ConstraintNameScope,
60) -> Result<(), SQLError> {
61    match action {
62        AlterTableAction::AddColumn { column, checks, .. } => {
63            columns.push(column.clone());
64            let existing_checks = constraints.checks.len();
65            constraints.checks.extend(checks.iter().cloned());
66            super::constraint_metadata::materialize_constraint_metadata_with_names(
67                relation,
68                columns,
69                constraints,
70                allocate,
71                names,
72            )
73            .map_err(|error| {
74                crate::catalog::errors::storage_error("ALTER TABLE ADD COLUMN", &error)
75            })?;
76            *column = columns
77                .pop()
78                .ok_or_else(|| SQLError::Internal("new column disappeared".into()))?;
79            *checks = constraints.checks.split_off(existing_checks);
80        }
81        AlterTableAction::AddCheckConstraint { constraint }
82            if !constraint.no_inherit && constraint.name.is_none() =>
83        {
84            constraints.checks.push(constraint.clone());
85            super::constraint_metadata::materialize_constraint_metadata_with_names(
86                relation,
87                columns,
88                constraints,
89                allocate,
90                names,
91            )
92            .map_err(|error| {
93                crate::catalog::errors::storage_error("ALTER TABLE ADD CONSTRAINT", &error)
94            })?;
95            *constraint = constraints
96                .checks
97                .pop()
98                .ok_or_else(|| SQLError::Internal("new CHECK constraint disappeared".into()))?;
99        }
100        AlterTableAction::AddNotNullConstraint {
101            name,
102            column,
103            validated,
104            no_inherit: false,
105        } if name.is_none() => {
106            if let Some(definition) = columns
107                .iter_mut()
108                .find(|definition| definition.name == *column && !definition.not_null)
109            {
110                definition.not_null = true;
111                definition.not_null_explicit = true;
112                definition.not_null_validated = *validated;
113                super::constraint_metadata::materialize_constraint_metadata_with_names(
114                    relation,
115                    columns,
116                    constraints,
117                    allocate,
118                    names,
119                )
120                .map_err(|error| {
121                    crate::catalog::errors::storage_error("ALTER TABLE ADD CONSTRAINT", &error)
122                })?;
123                *name = columns
124                    .iter()
125                    .find(|definition| definition.name == *column)
126                    .and_then(|definition| definition.not_null_name.clone());
127            }
128        }
129        _ => {}
130    }
131    Ok(())
132}
133
134pub mod ordering;
135pub mod syntax;
136pub mod targets;