use super::{CatalogIndexRow, Engine, StorageBackendResult};
pub(crate) use uqa_sql::catalog::is_virtual_system_schema;
impl Engine {
pub fn list_catalog_indexes(&self) -> StorageBackendResult<Vec<CatalogIndexRow>> {
self.with_catalog_read_snapshot(Self::catalog_indexes_in_execution)
}
pub(crate) fn catalog_indexes_in_execution(
&self,
) -> StorageBackendResult<Vec<CatalogIndexRow>> {
if let Some(snapshot) = self.query_catalog_snapshot.as_ref() {
let mut out = snapshot
.catalog_indexes
.values()
.cloned()
.collect::<Vec<_>>();
out.sort_by(|a, b| a.relation.cmp(&b.relation));
return Ok(out);
}
self.synchronize_catalog_registries()?;
let mut out: Vec<CatalogIndexRow> = self
.durable
.catalog_indexes
.read()
.values()
.cloned()
.collect();
out.sort_by(|a, b| a.relation.cmp(&b.relation));
Ok(out)
}
pub fn register_schema(&self, name: &str, if_not_exists: bool) -> StorageBackendResult<bool> {
self.with_implicit_storage_transaction(|engine| {
uqa_execution::schema::namespaces::register_api_schema(
&engine.schema_creation_context(),
name,
if_not_exists,
)
.map_err(|error| uqa_storage::StorageBackendError::backend("CREATE SCHEMA", error))
})
}
pub fn drop_schema(&self, name: &str) -> StorageBackendResult<bool> {
self.with_implicit_storage_transaction(|engine| {
uqa_execution::schema::namespaces::removal::drop_empty_schema(
&engine.empty_schema_removal_context(),
name,
)
})
}
pub fn has_schema(&self, name: &str) -> StorageBackendResult<bool> {
self.with_catalog_read_snapshot(|engine| {
engine.synchronize_catalog_registries()?;
Ok(engine.durable.schemas.read().contains_key(name))
})
}
pub fn has_namespace(&self, name: &str) -> StorageBackendResult<bool> {
self.with_catalog_read_snapshot(|engine| engine.has_namespace_in_execution(name))
}
pub(crate) fn has_namespace_in_execution(&self, name: &str) -> StorageBackendResult<bool> {
self.synchronize_catalog_registries()?;
Ok(is_virtual_system_schema(name)
|| self.durable.schemas.read().contains_key(name)
|| self.durable.graphs.read().contains_key(name))
}
pub(crate) fn validate_stored_schema_name(name: &str) -> StorageBackendResult<()> {
crate::capabilities::validate_stored_schema_name(name)
}
pub(crate) fn schema_is_empty(&self, schema: &str) -> bool {
!self
.storage
.tables
.read()
.keys()
.any(|relation| relation.schema == schema)
&& !self
.durable
.views
.read()
.keys()
.any(|relation| relation.schema == schema)
&& !self
.durable
.sequences
.read()
.keys()
.any(|relation| relation.schema == schema)
&& !self
.durable
.foreign_tables
.read()
.keys()
.any(|relation| relation.schema == schema)
&& !self
.durable
.catalog_indexes
.read()
.keys()
.any(|relation| relation.schema == schema)
&& !self
.durable
.domains
.read()
.values()
.any(|domain| domain.identity.schema == schema)
&& !self.durable.sql_user_functions.read().keys().any(|name| {
uqa_sql::schema::namespaces::removal::routine_name_occupies_schema(name, schema)
})
}
pub fn list_schemas(&self) -> StorageBackendResult<Vec<String>> {
self.with_catalog_read_snapshot(|engine| {
if let Some(snapshot) = engine.query_catalog_snapshot.as_ref() {
return Ok(snapshot.schemas.keys().cloned().collect());
}
engine.synchronize_catalog_registries()?;
Ok(engine.durable.schemas.read().keys().cloned().collect())
})
}
pub fn tables_in_schema(&self, schema: &str) -> StorageBackendResult<Vec<String>> {
self.with_catalog_read_snapshot(|engine| engine.schema_tables_in_execution(schema))
}
pub(crate) fn schema_tables_in_execution(
&self,
schema: &str,
) -> StorageBackendResult<Vec<String>> {
self.synchronize_table_catalog()?;
let mut out: Vec<String> = Vec::new();
for relation in self.storage.tables.read().keys() {
if relation.schema == schema {
out.push(relation.name.clone());
}
}
out.sort_unstable();
Ok(out)
}
pub fn list_sequences(&self) -> StorageBackendResult<Vec<String>> {
self.with_catalog_read_snapshot(|engine| Ok(engine.query_sequence_snapshot()?.names()))
}
}