use std::{
collections::{HashMap, hash_map::Entry},
iter,
};
use crate::{
catalog::{CatalogManager, system::catalog::SystemCatalog},
common::symbol::Symbol,
executor::ExecutionError,
storage::{Storage, TableHeap},
};
pub struct Executor {
pub catalog: CatalogManager,
pub session_user: Symbol,
pub storage: Option<Storage>,
pub table_heaps: HashMap<(Symbol, Symbol, Symbol), TableHeap>,
pub system_catalog: Option<SystemCatalog>,
}
impl Executor {
pub fn new(catalog: CatalogManager, session_user: Symbol, storage: Storage) -> Self {
let data_dir = storage.data_dir().to_path_buf();
let system_catalog = SystemCatalog::new(data_dir);
system_catalog.init().ok();
let mut catalog = catalog;
if let Ok(databses) = system_catalog.load_all(&mut catalog.interner) {
for db_entry in databses {
catalog.catalog.databases.insert(db_entry.name, db_entry);
}
let max_oid =
catalog
.catalog
.databases
.values()
.flat_map(|db| {
iter::once(db.oid).chain(db.schemas.values().flat_map(|s| {
iter::once(s.oid).chain(s.tables.values().map(|t| t.oid))
}))
})
.max()
.unwrap_or(0);
catalog.catalog.set_next_oid(max_oid + 1);
}
Self {
catalog,
session_user,
storage: Some(storage),
table_heaps: HashMap::new(),
system_catalog: Some(system_catalog),
}
}
pub fn new_in_memory(catalog: CatalogManager, session_user: Symbol) -> Self {
Self {
catalog,
session_user,
storage: None,
table_heaps: HashMap::new(),
system_catalog: None,
}
}
pub fn get_or_open_table_heap(
&mut self,
db: Symbol,
schema: Symbol,
table: Symbol,
) -> Result<&mut TableHeap, ExecutionError> {
match self.table_heaps.entry((db, schema, table)) {
Entry::Occupied(entry) => Ok(entry.into_mut()),
Entry::Vacant(entry) => {
let db_name = self.catalog.interner.resolve(db);
let schema_name = self.catalog.interner.resolve(schema);
let table_name = self.catalog.interner.resolve(table);
let storage = self.storage.as_ref().ok_or_else(|| {
ExecutionError::Storage("storage engine not initialized".to_string())
})?;
let heap = TableHeap::open(storage, db_name, schema_name, table_name)
.map_err(|e| ExecutionError::Storage(e.to_string()))?;
Ok(entry.insert(heap))
}
}
}
}