use crate::functions::{
RegisteredSQLFunction, SQLAggregateFunction, SQLFunctionOptions, SQLScalarFunction,
SQLTableFunction,
};
use parking_lot::{Mutex, RwLock};
use std::collections::BTreeMap;
use uqa_core::CancellationToken;
use uqa_sql::SQLError;
pub trait QueryMemorySettings: Send + Sync {
fn work_mem_bytes(&self) -> Result<usize, SQLError>;
}
#[derive(Clone, Copy)]
pub struct QueryRuntimeView<'a> {
pub cancellation: &'a CancellationToken,
pub settings: &'a dyn QueryMemorySettings,
pub scalar_functions:
&'a RwLock<BTreeMap<String, RegisteredSQLFunction<dyn SQLScalarFunction>>>,
pub table_functions: &'a RwLock<BTreeMap<String, RegisteredSQLFunction<dyn SQLTableFunction>>>,
pub aggregate_functions:
&'a RwLock<BTreeMap<String, RegisteredSQLFunction<dyn SQLAggregateFunction>>>,
pub notices: &'a Mutex<Vec<(String, String)>>,
}
impl QueryRuntimeView<'_> {
pub fn check_cancelled(&self) -> Result<(), SQLError> {
Ok(self.cancellation.check()?)
}
pub fn cancellation_token(&self) -> uqa_core::CancellationToken {
self.cancellation.clone()
}
pub fn work_mem_bytes(&self) -> Result<usize, SQLError> {
self.settings.work_mem_bytes()
}
pub fn lookup_scalar_function(
&self,
name: &str,
) -> Option<RegisteredSQLFunction<dyn SQLScalarFunction>> {
self.scalar_functions
.read()
.get(&name.to_ascii_lowercase())
.cloned()
}
pub fn has_scalar_functions(&self) -> bool {
!self.scalar_functions.read().is_empty()
}
pub fn has_scalar_function(&self, name: &str) -> bool {
self.scalar_functions
.read()
.contains_key(&name.to_ascii_lowercase())
}
pub fn lookup_table_function(
&self,
name: &str,
) -> Option<RegisteredSQLFunction<dyn SQLTableFunction>> {
self.table_functions
.read()
.get(&name.to_ascii_lowercase())
.cloned()
}
pub fn has_table_function(&self, name: &str) -> bool {
self.table_functions
.read()
.contains_key(&name.to_ascii_lowercase())
}
pub fn lookup_aggregate_function(
&self,
name: &str,
) -> Option<RegisteredSQLFunction<dyn SQLAggregateFunction>> {
self.aggregate_functions
.read()
.get(&name.to_ascii_lowercase())
.cloned()
}
pub fn has_aggregate_function(&self, name: &str) -> bool {
self.aggregate_functions
.read()
.contains_key(&name.to_ascii_lowercase())
}
pub fn registered_function_options(&self, name: &str) -> [Option<SQLFunctionOptions>; 3] {
let name = name.to_ascii_lowercase();
[
self.scalar_functions
.read()
.get(&name)
.map(|registration| registration.options),
self.table_functions
.read()
.get(&name)
.map(|registration| registration.options),
self.aggregate_functions
.read()
.get(&name)
.map(|registration| registration.options),
]
}
pub fn push_diagnostic(&self, level: impl Into<String>, message: impl Into<String>) {
self.notices.lock().push((level.into(), message.into()));
}
}