use crate::lib::ast::ddl::{CreateDatabaseQuery, DDLStatement, SQLStatement};
use crate::lib::ast::predule::OtherStatement;
use crate::lib::errors::execute_error::ExecuteError;
use crate::lib::executor::predule::{ExecuteResult, GlobalConfig};
use crate::lib::logger::predule::Logger;
use crate::lib::optimizer::predule::Optimizer;
use crate::lib::utils::predule::set_system_env;
use path_absolutize::*;
use std::error::Error;
use std::path::PathBuf;
pub struct Executor {}
impl Default for Executor {
fn default() -> Self {
Self::new()
}
}
impl Executor {
pub fn new() -> Self {
Self {}
}
pub async fn init(&self, path: String) -> Result<(), Box<dyn Error>> {
let mut path_buf = PathBuf::new();
path_buf.push(path);
path_buf.push(".rrdb.config");
#[allow(non_snake_case)]
let RRDB_BASE_PATH = path_buf.absolutize()?.to_str().unwrap().to_string();
set_system_env("RRDB_BASE_PATH", &RRDB_BASE_PATH);
let base_path = path_buf.clone();
(match tokio::fs::create_dir(base_path.clone()).await {
Ok(_) => Ok(()),
Err(error) => {
if error.kind() == std::io::ErrorKind::AlreadyExists {
Ok(())
} else {
Err(error)
}
}
})?;
let mut global_path = base_path.clone();
global_path.push("global.config");
let global_info = GlobalConfig::default();
let global_config = toml::to_string(&global_info).unwrap();
tokio::fs::write(global_path, global_config.as_bytes()).await?;
self.create_database(CreateDatabaseQuery::builder().set_name("rrdb".into()))
.await?;
Ok(())
}
pub async fn process_query(
&self,
mut statement: SQLStatement,
) -> Result<ExecuteResult, Box<dyn Error + Send>> {
Logger::info(format!("AST echo: {:?}", statement));
let optimizer = Optimizer::new();
optimizer.optimize(&mut statement);
let result = match statement {
SQLStatement::DDL(DDLStatement::CreateDatabaseQuery(query)) => {
self.create_database(query).await
}
SQLStatement::DDL(DDLStatement::AlterDatabase(query)) => {
self.alter_database(query).await
}
SQLStatement::DDL(DDLStatement::DropDatabaseQuery(query)) => {
self.drop_database(query).await
}
SQLStatement::DDL(DDLStatement::CreateTableQuery(query)) => {
self.create_table(query).await
}
SQLStatement::DDL(DDLStatement::AlterTableQuery(query)) => {
self.alter_table(query).await
}
SQLStatement::DDL(DDLStatement::DropTableQuery(query)) => self.drop_table(query).await,
SQLStatement::Other(OtherStatement::ShowDatabases(query)) => {
self.show_databases(query).await
}
SQLStatement::Other(OtherStatement::UseDatabase(query)) => {
self.use_databases(query).await
}
SQLStatement::Other(OtherStatement::ShowTables(query)) => self.show_tables(query).await,
SQLStatement::Other(OtherStatement::DescTable(query)) => self.desc_table(query).await,
_ => unimplemented!("no execute implementation"),
};
match result {
Ok(result) => Ok(result),
Err(error) => Err(ExecuteError::boxed(error.to_string())),
}
}
}