Skip to main content

uqa_sql/ast/types/
references.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Catalog names carried by references to user-defined types. Identity is the OID; a rename or schema move gives every reference the type's current name.
8
9use super::ColumnType;
10use uqa_core::RelationIdentity;
11
12impl ColumnType {
13    /// Give every reference to the user-defined type `oid`, including array elements and domain bases, the type's current schema and name. Returns whether a reference changed.
14    pub fn rename_user_type(&mut self, oid: u32, identity: &RelationIdentity) -> bool {
15        match self {
16            ColumnType::Enum(reference) if reference.oid == oid => {
17                let changed =
18                    reference.schema != identity.schema || reference.name != identity.name;
19                reference.schema.clone_from(&identity.schema);
20                reference.name.clone_from(&identity.name);
21                changed
22            }
23            ColumnType::Composite(reference) if reference.oid == oid => {
24                let changed =
25                    reference.schema != identity.schema || reference.name != identity.name;
26                reference.schema.clone_from(&identity.schema);
27                reference.name.clone_from(&identity.name);
28                changed
29            }
30            ColumnType::Domain {
31                schema,
32                name,
33                oid: domain_oid,
34                base,
35                ..
36            } => {
37                let mut changed = base.rename_user_type(oid, identity);
38                if *domain_oid == oid {
39                    changed |= *schema != identity.schema || *name != identity.name;
40                    schema.clone_from(&identity.schema);
41                    name.clone_from(&identity.name);
42                }
43                changed
44            }
45            ColumnType::Array(element) => element.rename_user_type(oid, identity),
46            _ => false,
47        }
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use crate::ast::{ColumnType, EnumTypeReference};
54    use uqa_core::RelationIdentity;
55
56    #[test]
57    fn renames_follow_type_identity_through_arrays_and_domain_bases() {
58        let mood = ColumnType::Enum(EnumTypeReference {
59            schema: "public".into(),
60            name: "mood".into(),
61            oid: 20_000,
62            array_oid: 20_001,
63        });
64        let mut column = ColumnType::Array(Box::new(ColumnType::Domain {
65            schema: "public".into(),
66            name: "good_mood".into(),
67            oid: 20_002,
68            array_oid: None,
69            base: Box::new(mood),
70        }));
71        let feeling = RelationIdentity::new("other", "feeling");
72        assert!(column.rename_user_type(20_000, &feeling));
73        assert!(!column.rename_user_type(20_000, &feeling));
74        let ColumnType::Array(element) = &column else {
75            panic!("array column");
76        };
77        let ColumnType::Domain { name, base, .. } = element.as_ref() else {
78            panic!("domain element");
79        };
80        assert_eq!(name, "good_mood");
81        assert!(
82            matches!(base.as_ref(), ColumnType::Enum(reference) if reference.schema == "other" && reference.name == "feeling")
83        );
84        assert!(!column.rename_user_type(30_000, &feeling));
85    }
86}