pub mod query_result;
pub mod session;
pub mod single_user;
use std::sync::Arc;
use glaredb_error::Result;
use session::Session;
use crate::catalog::context::{DatabaseContext, SYSTEM_CATALOG};
use crate::catalog::create::{
CreateAggregateFunctionInfo,
CreateScalarFunctionInfo,
CreateSchemaInfo,
CreateTableFunctionInfo,
OnConflict,
};
use crate::catalog::database::{AccessMode, Database};
use crate::catalog::system::{DEFAULT_SCHEMA, new_system_catalog};
use crate::catalog::{Catalog, Schema};
use crate::extension::Extension;
use crate::runtime::pipeline::PipelineRuntime;
use crate::runtime::system::SystemRuntime;
use crate::storage::storage_manager::StorageManager;
#[derive(Debug)]
pub struct Engine<P: PipelineRuntime, R: SystemRuntime> {
system_catalog: Arc<Database>,
executor: P,
runtime: R,
}
impl<P, R> Engine<P, R>
where
P: PipelineRuntime,
R: SystemRuntime,
{
pub fn new(executor: P, runtime: R) -> Result<Self> {
let system_catalog = Arc::new(Database {
name: SYSTEM_CATALOG.to_string(),
mode: AccessMode::ReadOnly,
catalog: Arc::new(new_system_catalog()?),
storage: Arc::new(StorageManager::empty()),
attach_info: None,
});
Ok(Engine {
system_catalog,
executor,
runtime,
})
}
pub fn new_base_database_context(&self) -> Result<DatabaseContext> {
DatabaseContext::new(self.system_catalog.clone())
}
pub fn new_session(&self) -> Result<Session<P, R>> {
let context = self.new_base_database_context()?;
Ok(Session::new(
context,
self.executor.clone(),
self.runtime.clone(),
))
}
pub fn register_extension<E>(&self, _ext: E) -> Result<()>
where
E: Extension + 'static,
{
if let Some(functions) = E::FUNCTIONS {
let schema = self
.system_catalog
.catalog
.create_schema(&CreateSchemaInfo {
name: functions.namespace.to_string(),
on_conflict: OnConflict::Error,
})?;
for scalar in functions.scalar {
schema.create_scalar_function(&CreateScalarFunctionInfo {
name: scalar.name.to_string(),
implementation: scalar,
on_conflict: OnConflict::Error,
})?;
for alias in scalar.aliases {
schema.create_scalar_function(&CreateScalarFunctionInfo {
name: alias.to_string(),
implementation: scalar,
on_conflict: OnConflict::Error,
})?;
}
}
for agg in functions.aggregate {
schema.create_aggregate_function(&CreateAggregateFunctionInfo {
name: agg.name.to_string(),
implementation: agg,
on_conflict: OnConflict::Error,
})?;
for alias in agg.aliases {
schema.create_aggregate_function(&CreateAggregateFunctionInfo {
name: alias.to_string(),
implementation: agg,
on_conflict: OnConflict::Error,
})?;
}
}
let default_schema = self
.system_catalog
.catalog
.get_schema(DEFAULT_SCHEMA)?
.expect("default schema to exist");
for table_func in functions.table {
schema.create_table_function(&CreateTableFunctionInfo {
name: table_func.function.name.to_string(),
implementation: table_func.function,
infer_scan: None,
on_conflict: OnConflict::Error,
})?;
for alias in table_func.function.aliases {
schema.create_table_function(&CreateTableFunctionInfo {
name: alias.to_string(),
implementation: table_func.function,
infer_scan: None,
on_conflict: OnConflict::Error,
})?;
}
if let Some(alias_in_default) = table_func.aliases_in_default {
for alias in alias_in_default.aliases {
default_schema.create_table_function(&CreateTableFunctionInfo {
name: alias.to_string(),
implementation: table_func.function,
infer_scan: alias_in_default.infer_scan,
on_conflict: OnConflict::Error,
})?;
}
}
}
}
Ok(())
}
}