use crate::Engine;
use uqa_execution::schema::domains::{DomainCreationContext, DomainDeclarationBinding};
use uqa_sql::catalog::roles::RoleReference;
use uqa_sql::{ast::CreateDomain, catalog::domain::StoredDomain, SQLError};
impl Engine {
pub(crate) fn domain_alter_context(
&self,
) -> uqa_execution::schema::domains::alteration::DomainAlterContext<
'_,
crate::session::StatementReadSnapshot,
> {
use uqa_execution::schema::domains::alteration::{
DomainAlterContext, DomainValidationInputs,
};
DomainAlterContext {
types: self.type_lifecycle_context(),
bindings: self,
deletion: self,
validation: DomainValidationInputs {
catalog: self.catalog_execution(),
tables: self,
locks: self,
identities: self,
composites: self,
expressions: self,
cancellation: self.cancellation_token(),
plan_check: |expression| {
uqa_planner::optimizer::optimize_scalar_expression(
expression,
&uqa_planner::OptimizerConfig::new(
uqa_execution::scalar::eval_constant_scalar,
),
)
},
},
}
}
pub(crate) fn domain_creation_context(&self) -> DomainCreationContext<'_> {
DomainCreationContext {
creation: self.relation_creation_context(),
identities: self.catalog_identity_reservation_context(),
writer: self,
bindings: self,
allocate_identity: || {
crate::new_nonzero_catalog_identity("domain", "object identity")
.map_err(|error| SQLError::Internal(error.to_string()))
},
publication: self,
enums: self,
composites: self,
changes: self,
}
}
}
impl uqa_execution::schema::domains::alteration::DomainConstraintBinding for Engine {
fn bind_added_check(
&self,
definition: &CreateDomain,
check: uqa_sql::ast::DomainCheck,
) -> Result<uqa_sql::ast::DomainCheck, SQLError> {
let scope = super::query_scope::new_for_catalog_binding(self);
let binding = uqa_execution::query::binding::binding_context(&scope)?;
let names = self
.schema_publication_context()
.constraint_names()
.automatic_names(&definition.name)?;
uqa_sql::schema::domains::prepare_added_check(
&uqa_sql::schema::SchemaBindingContext {
catalog: self,
binding: &binding,
},
definition,
check,
&names,
)
}
fn bind_added_not_null(
&self,
definition: &CreateDomain,
constraint: uqa_sql::ast::DomainNotNull,
) -> Result<uqa_sql::ast::DomainNotNull, SQLError> {
let names = self
.schema_publication_context()
.constraint_names()
.automatic_names(&definition.name)?;
uqa_sql::schema::domains::prepare_added_not_null(definition, constraint, &names)
}
}
impl DomainDeclarationBinding for Engine {
fn bind_domain_declaration(&self, definition: &mut CreateDomain) -> Result<(), SQLError> {
let scope = super::query_scope::new_for_catalog_binding(self);
let binding = uqa_execution::query::binding::binding_context(&scope)?;
let names = self
.schema_publication_context()
.constraint_names()
.automatic_names(&definition.name)?;
uqa_sql::schema::domains::prepare_domain_definition(
&uqa_sql::schema::SchemaBindingContext {
catalog: self,
binding: &binding,
},
self,
definition,
&names,
)
}
}
use std::collections::BTreeMap;
use uqa_execution::schema::domains::dependencies::{
DomainDependencyCatalog, DomainDependencyContext, DomainRegistryPublication,
};
impl Engine {
pub(crate) fn domain_dependency_context(&self) -> DomainDependencyContext<'_> {
DomainDependencyContext {
catalog: self,
publication: self,
enums: self,
composites: self,
changes: self,
}
}
}
impl DomainDependencyCatalog for Engine {
fn domain_definitions(&self) -> BTreeMap<String, StoredDomain> {
self.durable.domains.read().clone()
}
}
impl DomainRegistryPublication for Engine {
fn domain_registry(&self) -> uqa_execution::catalog::domain::DomainRegistryRead<'_> {
Box::new(self.durable.domains.read())
}
fn domain_catalog(&self) -> Option<&dyn uqa_storage::CatalogFacade> {
self.storage.catalog.as_deref()
}
fn publish_domain_definitions(&self, registry: BTreeMap<String, StoredDomain>) {
*self.durable.domains.write() = registry;
}
}
use uqa_execution::schema::domains::removal::{DomainDropNotices, DomainRemovalContext};
use uqa_sql::catalog::security::BoundSchemaSecurity;
use uqa_sql::schema::domains::removal::{
TypeObjectAuthority, TypeObjectBinding, TypeObjectCatalog,
};
impl Engine {
pub(crate) fn domain_removal_context(&self) -> DomainRemovalContext<'_> {
DomainRemovalContext {
refresh: self,
binding: TypeObjectBinding {
catalog: self,
authority: self,
session: self,
},
deletion: self,
notices: self,
}
}
}
impl TypeObjectCatalog for Engine {
fn schema_security(&self, name: &str) -> Option<BoundSchemaSecurity> {
self.schema_security_for_privilege(name)
}
fn resolve_drop_type_oid(&self, name: &str) -> Result<Option<i64>, SQLError> {
uqa_execution::catalog::projection::resolve_type_object_oid(&self.catalog_execution(), name)
}
fn format_drop_type(&self, oid: i64) -> Result<Option<String>, String> {
uqa_execution::catalog::projection::format_type_object(&self.catalog_execution(), oid)
}
fn enum_by_type_oid(&self, oid: u32) -> Option<uqa_sql::catalog::enum_type::StoredEnum> {
self.durable
.enums
.read()
.values()
.find(|definition| definition.oid == oid || definition.array_oid == oid)
.cloned()
}
fn composite_by_type_oid(
&self,
oid: u32,
) -> Option<uqa_sql::catalog::composite_type::StoredComposite> {
self.durable
.composites
.read()
.values()
.find(|definition| definition.oid == oid || definition.array_oid == oid)
.cloned()
}
fn user_array_element(&self, oid: u32) -> Option<u32> {
self.durable.domains.read().values().find_map(|domain| {
(uqa_sql::catalog::type_metadata::pg_type_array_oid(&domain.column_type())
== i64::from(oid))
.then_some(domain.oid)
})
}
fn row_type_relation(
&self,
oid: u32,
) -> Option<uqa_sql::schema::domains::removal::RowTypeRelation> {
uqa_execution::catalog::projection::row_type_relation(&self.catalog_execution(), oid)
.ok()
.flatten()
}
}
impl TypeObjectAuthority for Engine {
fn schema_usage(&self, schema: &str, role: &RoleReference) -> bool {
self.schema_has_privilege_for_role(
schema,
role,
uqa_sql::catalog::security::schema::SchemaAclPrivilege::Usage,
)
}
fn current_user_has_role_privileges(
&self,
role: &dyn uqa_sql::catalog::roles::identity::RoleSubject,
) -> bool {
Engine::current_user_has_role_privileges(self, role)
}
}
impl DomainDropNotices for Engine {
fn domain_drop_notice(&self, notice: uqa_sql::SQLNotice) {
self.push_sql_notice(notice);
}
}
impl uqa_execution::schema::domains::alteration::DomainValidationTables for Engine {
fn latest_table_snapshot(
&self,
name: &str,
) -> Result<std::sync::Arc<dyn uqa_execution::query::table_read::TableRead>, SQLError> {
let table = self.require_table(name)?;
self.detach_query_table(&table, &table, None)
.map(|table| table as std::sync::Arc<dyn uqa_execution::query::table_read::TableRead>)
}
}