use std::collections::BTreeMap;
use uqa_sql::ast::ColumnType;
use uqa_sql::SQLError;
use uqa_storage::CatalogFacade;
use crate::{Engine, StorageBackendResult};
const DOMAINS_METADATA_KEY: &str = "sql_domains_json";
pub(crate) use uqa_sql::catalog::domain::StoredDomain;
impl Engine {
pub(crate) fn domain_default_expression(&self, ty: &ColumnType) -> Option<uqa_sql::ast::Expr> {
uqa_sql::catalog::domain::domain_default_expression(self, ty)
}
pub(crate) fn try_column_insert_default_expr(
&self,
table: &str,
column: &str,
) -> StorageBackendResult<Option<uqa_sql::ast::Expr>> {
if let Some(default) = self.try_column_default_expr(table, column)? {
return Ok(Some(default));
}
let columns = self.try_describe_table(table)?.unwrap_or_default();
let Some(column) = columns.iter().find(|definition| definition.name == column) else {
return Ok(None);
};
Ok(self.domain_default_expression(&column.ty).or_else(|| {
matches!(column.ty, ColumnType::Domain { .. })
.then_some(uqa_sql::ast::Expr::Literal(uqa_core::Value::Null))
}))
}
pub(crate) fn domain_by_oid(&self, oid: u32) -> Option<StoredDomain> {
self.durable
.domains
.read()
.values()
.find(|domain| domain.oid == oid)
.cloned()
}
pub(crate) fn publish_domain(&self, domain: StoredDomain) -> Result<(), SQLError> {
let mut registry = self.durable.domains.write();
let mut next = registry.clone();
next.insert(domain.identity.qualified_name(), domain);
self.persist_domains(&next)?;
*registry = next;
drop(registry);
self.note_catalog_registry_changed();
Ok(())
}
pub(crate) fn persist_domains(
&self,
registry: &BTreeMap<String, StoredDomain>,
) -> Result<(), SQLError> {
if let Some(catalog) = &self.storage.catalog {
let json = serde_json::to_string(registry).map_err(|error| {
SQLError::Internal(format!("serialize domain catalog: {error}"))
})?;
catalog
.set_metadata(DOMAINS_METADATA_KEY, &json)
.map_err(|error| SQLError::Internal(format!("persist domain catalog: {error}")))?;
}
Ok(())
}
pub(crate) fn restore_domains_from_catalog(
&self,
catalog: &dyn CatalogFacade,
) -> StorageBackendResult<()> {
let registry = catalog
.get_metadata(DOMAINS_METADATA_KEY)?
.map(|json| serde_json::from_str(&json))
.transpose()?
.unwrap_or_default();
*self.durable.domains.write() = registry;
Ok(())
}
}
impl uqa_sql::catalog::domain::DomainCatalog for Engine {
fn domain_by_oid(&self, oid: u32) -> Option<StoredDomain> {
Engine::domain_by_oid(self, oid)
}
}