use super::namespaces::SchemaStatementWriter;
use crate::catalog::domain::{self, DomainRegistryPublication};
use uqa_sql::{
ast::CreateDomain,
catalog::domain::StoredDomain,
schema::constraint_metadata::{CatalogObjectAllocator, CatalogOidClass},
SQLError,
};
pub trait DomainDeclarationBinding {
fn bind_domain_declaration(&self, definition: &mut CreateDomain) -> Result<(), SQLError>;
}
pub struct DomainCreationContext<'a> {
pub creation: crate::schema::namespaces::relations::RelationCreationContext<'a>,
pub identities: crate::catalog::identity::CatalogIdentityReservationContext<'a>,
pub writer: &'a dyn SchemaStatementWriter,
pub bindings: &'a dyn DomainDeclarationBinding,
pub allocate_identity: fn() -> Result<[u8; 16], SQLError>,
pub publication: &'a dyn DomainRegistryPublication,
pub enums: &'a dyn crate::catalog::enum_type::EnumRegistryPublication,
pub composites: &'a dyn crate::catalog::composite_type::CompositeRegistryPublication,
pub changes: &'a dyn super::namespaces::NamespaceCatalogChanges,
}
pub fn create_domain(
context: &DomainCreationContext<'_>,
mut definition: CreateDomain,
) -> Result<(), SQLError> {
let owner = context.creation.bind_owner()?;
context.writer.prepare_writer()?;
definition.name = context.creation.persistent_name(&definition.name)?;
super::types::arrays::displace_array_type(
&context.creation,
super::types::arrays::UserTypeRegistries {
enums: context.enums,
domains: context.publication,
composites: context.composites,
},
&uqa_core::RelationIdentity::from_legacy_name(&definition.name)
.map_err(SQLError::Internal)?,
)?;
let identity = context.creation.reserve_type_name(&definition.name)?;
let array_name = super::types::arrays::reserve_array_name(
&context.creation,
&identity.schema,
&identity.name,
)?;
context.bindings.bind_domain_declaration(&mut definition)?;
let object_id = (context.allocate_identity)()?;
let mut allocator = context
.identities
.allocator(crate::catalog::identity::allocate_catalog_object_id);
let mut type_oid = || {
allocator
.allocate_catalog_oid(CatalogOidClass::Type, &object_id)
.map_err(|error| {
uqa_sql::catalog::errors::storage_error("domain catalog identity", &error)
})
.and_then(|oid| {
u32::try_from(oid)
.map_err(|_| SQLError::Internal(format!("invalid domain OID {oid}")))
})
};
let array_oid = type_oid()?;
let oid = type_oid()?;
uqa_sql::schema::domains::constraints::materialize(&mut definition, &mut allocator).map_err(
|error| uqa_sql::catalog::errors::storage_error("domain constraint identity", &error),
)?;
context.creation.retain_owner(&owner)?;
let before = context.publication.domain_registry().clone();
let mut registry = before.clone();
registry.insert(
identity.qualified_name(),
StoredDomain {
object_id,
oid,
array_oid: Some(array_oid),
identity,
owner: owner.identity(),
definition,
array_name: Some(array_name),
usage_acl: None,
},
);
domain::publish(context.publication, &before, registry)?;
context.changes.catalog_registry_changed();
Ok(())
}
pub mod alteration;
pub mod dependencies;
pub mod removal;
mod validation;