use crate::Engine;
use uqa_sql::{
ast::{ColumnDef, ColumnType},
binding::{snapshot::BindingSnapshot, stored_relations::StoredQueryNamespace},
plpgsql::PlpgsqlCatalog,
routines::{
compilation::{RoutineCompilationCatalog, RoutineCompilationContext, RoutineParserCatalog},
declaration::RoutineTypeCatalog,
merge_columns::StoredMergeColumnCatalog,
regclass::RoutineRegclassCatalog,
},
SQLError,
};
impl Engine {
pub(crate) fn routine_compilation_context(&self) -> RoutineCompilationContext<'_> {
RoutineCompilationContext {
types: self,
parsers: self,
catalog: self,
routines: self,
relations: self,
sequences: self,
merge: self,
regroles: self,
}
}
}
impl RoutineTypeCatalog for Engine {
fn try_describe_table(&self, name: &str) -> Result<Option<Vec<ColumnDef>>, String> {
Engine::describe_table_in_execution(self, name).map_err(|error| error.to_string())
}
fn resolve_catalog_column_type(&self, name: &str) -> Option<ColumnType> {
uqa_execution::catalog::projection::resolve_catalog_column_type(
&self.catalog_execution(),
name,
)
}
fn resolve_catalog_column_type_name(&self, name: &str) -> Result<ColumnType, SQLError> {
uqa_execution::catalog::projection::resolve_catalog_column_type_name(
&self.catalog_execution(),
name,
)
}
fn resolve_catalog_user_type_by_oid(&self, oid: u32) -> Option<ColumnType> {
uqa_execution::catalog::projection::resolve_catalog_user_type_by_oid(
&self.catalog_execution(),
oid,
)
}
fn format_type(&self, ty: &ColumnType) -> Result<String, SQLError> {
uqa_execution::catalog::projection::format_type_name(&self.catalog_execution(), ty)
}
fn format_type_oid(&self, oid: u32) -> Result<String, SQLError> {
uqa_execution::catalog::projection::format_type_object(
&self.catalog_execution(),
i64::from(oid),
)
.map_err(SQLError::Internal)?
.ok_or_else(|| SQLError::Internal(format!("cache lookup failed for type {oid}")))
}
fn composite_types(&self) -> Option<&dyn uqa_sql::expr::composites::CompositeTypeCatalog> {
Some(self)
}
fn require_type_usage(&self, ty: &ColumnType) -> Result<(), SQLError> {
uqa_execution::catalog::security::type_inquiry::require_type_usage(
&self.catalog_execution(),
ty,
)
}
}
impl uqa_execution::routines::invocation::bodies::RoutineBodySession for Engine {
fn retain_routine_body(
&self,
function: &uqa_sql::routines::SQLUserFunction,
body: uqa_sql::routines::CompiledFunctionBody,
) -> Result<(), SQLError> {
self.session.routine_bodies.retain(function, body)
}
}
impl StoredMergeColumnCatalog for Engine {
fn stored_merge_target_definitions(&self, table: &str) -> Option<Vec<ColumnDef>> {
self.table_entries()
.into_iter()
.find(|(name, _)| name == table)
.map(|(_, table)| table.columns.read().clone())
}
}
impl RoutineParserCatalog for Engine {
fn parser_settings(&self) -> uqa_sql::parser::ParserSettings {
Engine::parser_settings(self)
}
fn parser_notice(&self, notice: uqa_sql::SQLNotice) {
self.runtime.notices.push(notice);
}
fn plpgsql_catalog(&self) -> Result<PlpgsqlCatalog, SQLError> {
uqa_execution::catalog::projection::plpgsql_catalog(&self.catalog_execution())
}
}
impl RoutineCompilationCatalog for Engine {
fn has_registered_aggregate_function(&self, name: &str) -> bool {
Engine::has_registered_aggregate_function(self, name)
}
fn binding_snapshot(&self) -> Result<BindingSnapshot, SQLError> {
let scope = super::query_scope::new_for_catalog_binding(self);
uqa_execution::query::binding::binding_context(&scope).map(Into::into)
}
fn stored_query_namespace(&self) -> StoredQueryNamespace {
StoredQueryNamespace {
temporary_schema: self.temporary_schema_name(),
transition_relations:
uqa_execution::mutation::triggers::current_transition_relation_names(),
}
}
}
impl RoutineRegclassCatalog for Engine {
fn resolve_routine_regclass(&self, reference: &str) -> Result<Option<i64>, SQLError> {
uqa_execution::catalog::projection::resolve_regclass_oid(
&self.catalog_execution(),
reference,
)
}
}
use uqa_core::RelationIdentity;
use uqa_execution::routines::{
compilation::{RoutineCompilationSession, StoredRoutineCompilationContext},
definition::RoutineDefinitionContext,
rewrites::{self, RoutineRewriteContext},
};
impl Engine {
pub(crate) fn routine_definition_context(&self) -> RoutineDefinitionContext<'_> {
RoutineDefinitionContext {
compilation: self.stored_routine_compilation_context(),
sources: self,
regclasses: self,
}
}
pub(crate) fn stored_routine_compilation_context(&self) -> StoredRoutineCompilationContext<'_> {
StoredRoutineCompilationContext {
analysis: self.routine_compilation_context(),
session: self,
}
}
pub(crate) fn routine_rewrite_context(&self) -> RoutineRewriteContext<'_> {
RoutineRewriteContext {
registry: self,
publication: self,
compilation: self.stored_routine_compilation_context(),
columns: self.stored_column_binding_context(),
changes: self,
}
}
pub(crate) fn rewrite_routine_relation_references(
&self,
from: &RelationIdentity,
to: &RelationIdentity,
) -> Result<(), SQLError> {
rewrites::rewrite_routine_relation_references(&self.routine_rewrite_context(), from, to)
}
pub(crate) fn rewrite_routine_column_references(
&self,
relation: &RelationIdentity,
from: &str,
to: &str,
) -> Result<(), SQLError> {
rewrites::rewrite_routine_column_references(
&self.routine_rewrite_context(),
relation,
from,
to,
)
}
}
impl RoutineCompilationSession for Engine {
fn routine_search_path(&self) -> Vec<String> {
crate::session::effective_search_path(&self.session.state.read())
}
fn replace_routine_search_path(&self, path: Vec<String>) -> Vec<String> {
std::mem::replace(&mut self.session.state.write().search_path, path)
}
fn restore_routine_search_path(&self, path: Vec<String>) {
self.session.state.write().search_path = path;
}
fn routine_settings_scope(
&self,
settings: &[(String, String)],
) -> Result<Box<dyn RoutineConfigurationGuard + '_>, SQLError> {
let scope = self.routine_invocation_state_guard(!settings.is_empty(), false);
for (name, value) in settings {
self.set_configured_parameter(name, value)?;
}
Ok(Box::new(scope))
}
}
use uqa_execution::routines::{
catalog::RoutineMutationContext,
configuration::{RoutineConfigurationGuard, RoutineConfigurationSession},
registration::RoutineRegistrationContext,
};
use uqa_sql::routines::registration::RoutineSupportAuthority;
impl RoutineSupportAuthority for Engine {
fn current_user_is_superuser(&self) -> bool {
Engine::current_user_is_superuser(self)
}
}
impl RoutineConfigurationGuard for crate::roles::RoutineSessionStateGuard<'_> {}
impl RoutineConfigurationSession for Engine {
fn routine_configuration_guard(&self) -> Box<dyn RoutineConfigurationGuard + '_> {
Box::new(self.routine_config_state_guard())
}
fn set_routine_variable(&self, name: &str, value: &str) -> Result<(), SQLError> {
self.set_variable(name, value)
}
fn show_routine_variable(&self, name: &str) -> Result<String, SQLError> {
self.show_variable(name)
}
fn routine_variable_name(&self, name: &str) -> Result<String, SQLError> {
self.session_execution_view()
.show_parameter(name)
.map(|(name, _)| name)
}
fn load_language_library(&self, language: &str) {
self.load_language(language);
}
}
impl Engine {
pub(crate) fn routine_mutation_context(&self) -> RoutineMutationContext<'_> {
RoutineMutationContext {
writer: self,
names: self,
roles: self,
registry: self,
publication: self,
changes: self,
}
}
pub(crate) fn routine_registration_context(&self) -> RoutineRegistrationContext<'_> {
RoutineRegistrationContext {
catalog: self.routine_mutation_context(),
namespace: self.relation_creation_context(),
definition: self.routine_definition_context(),
support: self,
configuration: self,
overloads: uqa_sql::routines::resolution::RoutineOverloadContext { catalog: self },
session: self,
bodies: self,
}
}
}