Skip to main content

glaredb_core/engine/
mod.rs

1pub mod query_result;
2pub mod session;
3pub mod single_user;
4
5use std::sync::Arc;
6
7use glaredb_error::Result;
8use session::Session;
9
10use crate::catalog::context::{DatabaseContext, SYSTEM_CATALOG};
11use crate::catalog::create::{
12    CreateAggregateFunctionInfo,
13    CreateScalarFunctionInfo,
14    CreateSchemaInfo,
15    CreateTableFunctionInfo,
16    OnConflict,
17};
18use crate::catalog::database::{AccessMode, Database};
19use crate::catalog::system::{DEFAULT_SCHEMA, new_system_catalog};
20use crate::catalog::{Catalog, Schema};
21use crate::extension::Extension;
22use crate::runtime::pipeline::PipelineRuntime;
23use crate::runtime::system::SystemRuntime;
24use crate::storage::storage_manager::StorageManager;
25
26#[derive(Debug)]
27pub struct Engine<P: PipelineRuntime, R: SystemRuntime> {
28    system_catalog: Arc<Database>,
29    executor: P,
30    runtime: R,
31}
32
33impl<P, R> Engine<P, R>
34where
35    P: PipelineRuntime,
36    R: SystemRuntime,
37{
38    pub fn new(executor: P, runtime: R) -> Result<Self> {
39        let system_catalog = Arc::new(Database {
40            name: SYSTEM_CATALOG.to_string(),
41            mode: AccessMode::ReadOnly,
42            catalog: Arc::new(new_system_catalog()?),
43            storage: Arc::new(StorageManager::empty()),
44            attach_info: None,
45        });
46
47        Ok(Engine {
48            system_catalog,
49            executor,
50            runtime,
51        })
52    }
53
54    /// Creates a new database context that contains only the system catalog and
55    /// a temporary catalog.
56    ///
57    /// This should be the base of all session catalogs.
58    pub fn new_base_database_context(&self) -> Result<DatabaseContext> {
59        DatabaseContext::new(self.system_catalog.clone())
60    }
61
62    /// Create a new session.
63    pub fn new_session(&self) -> Result<Session<P, R>> {
64        let context = self.new_base_database_context()?;
65        Ok(Session::new(
66            context,
67            self.executor.clone(),
68            self.runtime.clone(),
69        ))
70    }
71
72    /// Register a new extension for this engine.
73    pub fn register_extension<E>(&self, _ext: E) -> Result<()>
74    where
75        E: Extension + 'static,
76    {
77        if let Some(functions) = E::FUNCTIONS {
78            // Create a new schema for these functions.
79            let schema = self
80                .system_catalog
81                .catalog
82                .create_schema(&CreateSchemaInfo {
83                    name: functions.namespace.to_string(),
84                    on_conflict: OnConflict::Error,
85                })?;
86
87            // Register scalar functions.
88            for scalar in functions.scalar {
89                schema.create_scalar_function(&CreateScalarFunctionInfo {
90                    name: scalar.name.to_string(),
91                    implementation: scalar,
92                    on_conflict: OnConflict::Error,
93                })?;
94
95                for alias in scalar.aliases {
96                    schema.create_scalar_function(&CreateScalarFunctionInfo {
97                        name: alias.to_string(),
98                        implementation: scalar,
99                        on_conflict: OnConflict::Error,
100                    })?;
101                }
102            }
103
104            // Register aggregate functions.
105            for agg in functions.aggregate {
106                schema.create_aggregate_function(&CreateAggregateFunctionInfo {
107                    name: agg.name.to_string(),
108                    implementation: agg,
109                    on_conflict: OnConflict::Error,
110                })?;
111
112                for alias in agg.aliases {
113                    schema.create_aggregate_function(&CreateAggregateFunctionInfo {
114                        name: alias.to_string(),
115                        implementation: agg,
116                        on_conflict: OnConflict::Error,
117                    })?;
118                }
119            }
120
121            let default_schema = self
122                .system_catalog
123                .catalog
124                .get_schema(DEFAULT_SCHEMA)?
125                .expect("default schema to exist");
126
127            // Register table functions.
128            for table_func in functions.table {
129                schema.create_table_function(&CreateTableFunctionInfo {
130                    name: table_func.function.name.to_string(),
131                    implementation: table_func.function,
132                    infer_scan: None,
133                    on_conflict: OnConflict::Error,
134                })?;
135
136                for alias in table_func.function.aliases {
137                    schema.create_table_function(&CreateTableFunctionInfo {
138                        name: alias.to_string(),
139                        implementation: table_func.function,
140                        infer_scan: None,
141                        on_conflict: OnConflict::Error,
142                    })?;
143                }
144
145                // Special case aliases in default.
146                if let Some(alias_in_default) = table_func.aliases_in_default {
147                    for alias in alias_in_default.aliases {
148                        default_schema.create_table_function(&CreateTableFunctionInfo {
149                            name: alias.to_string(),
150                            implementation: table_func.function,
151                            infer_scan: alias_in_default.infer_scan,
152                            on_conflict: OnConflict::Error,
153                        })?;
154                    }
155                }
156            }
157        }
158
159        Ok(())
160    }
161}