use super::{CatalogReadView, RelationNameResolution};
use std::sync::Arc;
use uqa_sql::catalog::analysis::{AnalysisCatalog, TableDefinition, ViewDefinition};
use uqa_sql::{ColumnType, SQLError};
impl AnalysisCatalog for CatalogReadView {
fn relation_dependency(
&self,
resolution: &RelationNameResolution,
name: &str,
) -> Result<Option<u32>, SQLError> {
let Some((canonical, kind)) = self
.relation_kind_resolution(resolution, name)?
.into_found()
else {
return Ok(None);
};
super::projection::resolved_relation_oid(self, resolution, &canonical, kind)
.and_then(|oid| {
u32::try_from(oid)
.map_err(|_| SQLError::Internal(format!("invalid relation OID {oid}")))
})
.map(Some)
}
fn prepared_dependency_snapshot(
&self,
dependencies: &uqa_sql::prepared::dependencies::PreparedAnalysisDependencies,
) -> Result<Option<uqa_sql::prepared::dependencies::PreparedDependencySnapshot>, SQLError> {
super::prepared_dependencies::capture(self, dependencies).map(Some)
}
fn effective_search_path(
&self,
resolution: &RelationNameResolution,
) -> Result<Option<uqa_sql::catalog::resolution::EffectiveSearchPath>, SQLError> {
let role = &resolution.current_user;
Ok(Some(uqa_sql::catalog::resolution::EffectiveSearchPath {
schemas: super::namespaces::current_schema_names(self, resolution, role, true),
creation_namespace: super::namespaces::current_schema_name(self, resolution, role),
}))
}
fn table_resolved(
&self,
resolution: &RelationNameResolution,
name: &str,
) -> Result<Option<TableDefinition>, SQLError> {
CatalogReadView::table_resolved(self, resolution, name).map(|table| {
table.map(|table| TableDefinition {
columns: table.columns.clone(),
columns_declared: table.columns_declared,
})
})
}
fn table_name_resolved(
&self,
resolution: &RelationNameResolution,
name: &str,
) -> Result<Option<String>, SQLError> {
CatalogReadView::table_name_resolved(self, resolution, name)
}
fn view_resolved(
&self,
resolution: &RelationNameResolution,
name: &str,
) -> Result<Option<ViewDefinition>, SQLError> {
CatalogReadView::view_resolved(self, resolution, name).map(|view| {
view.map(|view| ViewDefinition {
query: view.query.clone(),
output_columns: view.output_columns.clone(),
materialized: view.kind == crate::catalog::view::StoredViewKind::Materialized,
materialized_column_types: view.materialized_column_types.clone(),
})
})
}
fn foreign_table_resolved(
&self,
resolution: &RelationNameResolution,
name: &str,
) -> Result<Option<TableDefinition>, SQLError> {
CatalogReadView::foreign_table_resolved(self, resolution, name).map(|table| {
table.map(|table| TableDefinition {
columns: Arc::new(table.columns.clone()),
columns_declared: true,
})
})
}
fn sequence_exists(
&self,
resolution: &RelationNameResolution,
name: &str,
) -> Result<bool, SQLError> {
CatalogReadView::sequence_resolved(self, resolution, name)
.map(|sequence| sequence.is_some())
}
fn virtual_relation_schema(
&self,
resolution: &RelationNameResolution,
name: &str,
) -> Result<Option<Vec<(String, ColumnType)>>, SQLError> {
super::schema::virtual_relation_schema(self, resolution, name)
}
fn sql_functions(
&self,
resolution: &RelationNameResolution,
name: &str,
) -> Result<Option<Vec<Arc<uqa_sql::routines::SQLUserFunction>>>, SQLError> {
CatalogReadView::sql_functions(self, resolution, name)
}
fn unopenable_relation(
&self,
resolution: &RelationNameResolution,
name: &str,
) -> Result<Option<uqa_sql::catalog::analysis::UnopenableRelation>, SQLError> {
Ok(
match self
.relation_kind_resolution(resolution, name)?
.into_found()
{
Some((canonical, "composite type")) => {
let relation = uqa_core::RelationIdentity::from_legacy_name(&canonical)
.map_err(SQLError::Internal)?;
Some(uqa_sql::catalog::analysis::UnopenableRelation {
name: relation.name,
kinds: "composite types",
})
}
_ => None,
},
)
}
}