diff --git a/Plugins/Alice-Database/Cargo.toml b/Plugins/Alice-Database/Cargo.toml index 04a5102..b45c44a 100644 --- a/Plugins/Alice-Database/Cargo.toml +++ b/Plugins/Alice-Database/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "Alice-Database_DBMS" -version = "1.2.0" +version = "1.2.2" edition = "2021" -include = ["**/*.rs", "Cargo.toml","proto/*.proto"] +include = ["**/*.rs", "Cargo.toml","proto/*.proto", "src/syntax/*.pest", "src/test.decl"] license = "MIT" description = "The Alice-Database is a comprehensive data management solution designed to integrate seamlessly with the Kingdom System. This plugin provides robust functionality for creating, updating, and deleting collections and documents, ensuring efficient and reliable data storage and retrieva" repository = "https://github.com/0xBLCKLPTN/Kingdom-System/tree/main/Plugins/Alice-Database" @@ -13,6 +13,8 @@ homepage = "https://github.com/0xBLCKLPTN/Kingdom-System" chrono = "0.4.38" env_logger = "0.11.5" log = "0.4.22" +pest = "2.7.14" +pest_derive = "2.7.14" prost = "0.13.3" rand = "0.8.5" ring = "0.17.8" diff --git a/Plugins/Alice-Database/src/cli.rs b/Plugins/Alice-Database/src/cli.rs new file mode 100644 index 0000000..0fad280 --- /dev/null +++ b/Plugins/Alice-Database/src/cli.rs @@ -0,0 +1,27 @@ +use std::io::{self, Write}; +use crate::instance::*; + +pub fn cli(instance_manager: &mut InstanceManager) { + loop { + print!("[ Instance Manager ] (type 'exit' to quit)=: "); + io::stdout().flush().unwrap(); + + let mut input = String::new(); + + match io::stdin().read_line(&mut input) { + Ok(_) => { + let trimmed_input = input.trim(); + + if trimmed_input.eq_ignore_ascii_case("exit") { + println!("Exiting..."); + break; + } + + instance_manager.wrapped_execute_cmd(trimmed_input); + } + Err(error) => { + println!("Error reading input: {}", error); + } + } + } +} diff --git a/Plugins/Alice-Database/src/command_executor.rs b/Plugins/Alice-Database/src/command_executor.rs new file mode 100644 index 0000000..61b39a8 --- /dev/null +++ b/Plugins/Alice-Database/src/command_executor.rs @@ -0,0 +1,30 @@ + +/* MIT License + +Copyright (c) 2024 Daniil Ermolaev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. */ + +use pest_derive::Parser; +use pest::Parser; + +#[derive(Parser)] +#[grammar = "syntax/instance_manager.pest"] +pub struct IMPestParser; + diff --git a/Plugins/Alice-Database/src/grpc.rs b/Plugins/Alice-Database/src/grpc.rs deleted file mode 100644 index d2b7996..0000000 --- a/Plugins/Alice-Database/src/grpc.rs +++ /dev/null @@ -1,71 +0,0 @@ -use tonic::{transport::Server, Request, Response, Status}; -use uuid::Uuid; -use std::path::PathBuf; -use std::sync::{Arc, Mutex}; - -// Import generated gRPC code -pub mod instance { - tonic::include_proto!("instance"); -} - -use instance::{InstanceService, CreateInstanceRequest, CreateInstanceResponse, - GetInstanceRequest, GetInstanceResponse, Instance}; - -// Engines enum represents the types of engines -#[derive(Debug, Clone)] -pub enum Engines { - JSONEngine(JSONEngine), -} - -// Your JSONEngine structure -#[derive(Debug, Clone)] -pub struct JSONEngine { - // Add fields necessary for your JSON engine -} - -impl JSONEngine { - pub fn new(_root_path: &PathBuf) -> Self { - // Initialize your JSONEngine as needed - Self {} - } -} - -// Instance structure -#[derive(Debug, Clone, Default)] -pub struct Instance { - pub name: String, - pub engine: Engines, -} - -// InstanceManager struct to manage instances -#[derive(Debug, Default)] -pub struct InstanceManager { - pub name: String, - pub instances: Vec, -} - -impl InstanceManager { - pub fn new() -> Self { - let name = Uuid::new_v4().to_string(); - let instances: Vec = vec![]; - Self { name, instances } - } - - pub fn create_instance(&mut self, engine_type: &str, root_path: &PathBuf) -> String { - let instance_name: String = Uuid::new_v4().to_string(); - - let engine = match engine_type { - "json_engine" => Engines::JSONEngine(JSONEngine::new(root_path)), - _ => panic!("Engine not found"), - }; - - let instance = Instance { engine, name: instance_name.clone() }; - self.instances.push(instance); - instance_name - } - - pub fn get_instance(&self, instance_name: &str) -> Option<&Instance> { - self.instances.iter().find(|i| i.name == instance_name) - } -} - diff --git a/Plugins/Alice-Database/src/grpc_server.rs b/Plugins/Alice-Database/src/grpc_server.rs index d1ffa6c..3c6b1ba 100644 --- a/Plugins/Alice-Database/src/grpc_server.rs +++ b/Plugins/Alice-Database/src/grpc_server.rs @@ -58,7 +58,7 @@ impl InstanceService for GRPCInstanceManager let engine_type = request.into_inner().engine_type; let mut im = self.instance_manager.lock().unwrap(); - let id = im.create_instance(&engine_type); + let id = im.create_instance(&engine_type).unwrap(); Ok( Response::new( CreateInstanceResponse { instance: id } ) diff --git a/Plugins/Alice-Database/src/instance.rs b/Plugins/Alice-Database/src/instance.rs index 1d8fe41..e0a06e0 100644 --- a/Plugins/Alice-Database/src/instance.rs +++ b/Plugins/Alice-Database/src/instance.rs @@ -22,12 +22,23 @@ SOFTWARE. */ use crate::Engines; use uuid::Uuid; -use std::path::PathBuf; +use std::path::{PathBuf, Path}; +use std::fs::File; +use std::io::{self, BufRead}; use crate::JSONEngine; use std::collections::HashMap; use ring::{rand::{SecureRandom, SystemRandom}, hmac}; use rand::rngs::OsRng; - +use crate::IMPestParser; +use pest_derive::Parser; +use pest::Parser; +use crate::Rule; + +macro_rules! adbprint { + ($($arg:tt)*) => { + println!("[ INSTANCE MANAGER ]=: {}", format!($($arg)*)); + }; +} #[derive(Debug, Clone)] pub struct Instance { @@ -53,16 +64,20 @@ impl InstanceManager { Self {name, instances, root_path: root_path.to_owned(), authenticated_apps} } - pub fn create_instance(&mut self, engine_type: &str) -> String { + pub fn create_instance(&mut self, engine_type: &str) -> Result> { let instance_name: String = Uuid::new_v4().to_string(); let mut engine = match engine_type { "json_engine" => Engines::JSONEngine(JSONEngine::new(&self.root_path)), - _ => panic!("Engine not found"), + _ => { + println!("Engine not found."); + return Err(Box::new(std::io::Error::new( + std::io::ErrorKind::InvalidInput, "Engine type not found"))); + } }; let mut instance = Instance {engine, name: instance_name.clone()}; self.instances.push(instance); - instance_name + Ok(instance_name) } pub fn get_instance(&self, instance_name: &str) -> Option<&Instance> { self.instances.iter().find(|i| i.name == instance_name) @@ -87,6 +102,68 @@ impl InstanceManager { } pub fn get_all_apps(&self) { - println!("{:#?}", self.authenticated_apps); + adbprint!("{:#?}", self.authenticated_apps); + } + + pub fn execute_cmd(&mut self, command: &str) -> Result<(), Box> { + match IMPestParser::parse(Rule::sql_statements, command) { + Ok(pairs) => { + for pair in pairs { + for inner_pair in pair.into_inner() { + match inner_pair.as_rule() { + Rule::create_instance => { + let inner = inner_pair.into_inner().as_str().split(" ENGINE ").collect::>(); + let instance_id = &self.create_instance(&inner[1]); + match instance_id { + Ok(message) => adbprint!("NEW INSTANCE ID: {}", message), + Err(e) => adbprint!("{:#?}",e) + } + }, + Rule::get_instance => { + let inner = inner_pair.into_inner().as_str(); + adbprint!("{:#?}", inner); + }, + Rule::get_instances => { + adbprint!("{:#?}", self.instances); + }, + Rule::print_addbms => { + adbprint!("{:#?}", self); + } + _ => unreachable!("I don't know this command"), + } + } + } + Ok(()) + } + Err(e) => { + adbprint!("Error parsing command: {}", e); + Err(Box::new(e)) + } + } + } + + pub fn wrapped_execute_cmd(&mut self, command: &str) -> Result<(), Box> { + match &self.execute_cmd(command) { + Ok(_) => println!(""), + Err(e) => adbprint!("Error! {}", e), + } + Ok(()) + } + + pub fn execute_decl_file

(&mut self, filename: P) -> Result<(), io::Error> + where + P: AsRef { + let file = File::open(filename)?; + let reader = io::BufReader::new(file); + let mut lines: Vec = Vec::new(); + + for line in reader.lines() { + self.wrapped_execute_cmd(line?.replace("\n", "").as_str()); + } + Ok(()) } } + + + + diff --git a/Plugins/Alice-Database/src/main.rs b/Plugins/Alice-Database/src/main.rs index 1a4d87a..78853a0 100644 --- a/Plugins/Alice-Database/src/main.rs +++ b/Plugins/Alice-Database/src/main.rs @@ -38,21 +38,20 @@ pub mod engines; pub mod grpc_server; pub mod instance; pub mod utils; +pub mod command_executor; +pub mod cli; use json_engine::*; use engines::*; use grpc_server::*; use instance::*; use utils::*; - +use command_executor::*; +use cli::cli; +/* gRPC #[tokio::main] async fn main() -> Result<(), Box> { - print_ascii(); - - let root_path = match prepare() { - Ok(k) => k, - _ => panic!("Errors in prepare function."), - }; + let root_path: PathBuf = get_root_path(); let instance_manager = GRPCInstanceManager { instance_manager: Arc::new(Mutex::new(InstanceManager::new(&root_path))), @@ -67,3 +66,14 @@ async fn main() -> Result<(), Box> { Ok(()) } +*/ + +#[tokio::main] +async fn main() -> Result<(), Box> { + let root_path: PathBuf = get_root_path(); + + let mut im = InstanceManager::new(&root_path); + //let k = im.execute_decl_file(Path::new("./test.decl")); + cli(&mut im); + Ok(()) +} diff --git a/Plugins/Alice-Database/src/syntax/instance_manager.pest b/Plugins/Alice-Database/src/syntax/instance_manager.pest new file mode 100644 index 0000000..097d3f6 --- /dev/null +++ b/Plugins/Alice-Database/src/syntax/instance_manager.pest @@ -0,0 +1,19 @@ +alpha = { 'a'..'z' | 'A'..'Z' } +digit = { '0'..'9' } +ident = { !digit ~ (alpha | digit | "_")+ } + +item = { ident } +items = { item ~ (( "," | "," ) ~ item)* } + +create_instance = { "CREATE INSTANCE " ~ ident ~ " ENGINE " ~ ident } +get_instance = { "GET INSTANCE " ~ ident } +get_instances = { "GET INSTANCES" } +delete_instance = { "DELETE INSTANCE " ~ ident } + +print_addbms = { "PRINTALLDDBMS" } + +sql_statement = { + create_instance | get_instance | get_instances | delete_instance | print_addbms +} + +sql_statements = _{ sql_statement ~ ((";" ~ sql_statement) | (";" ~ sql_statement))* ~ ";"? } diff --git a/Plugins/Alice-Database/src/test.decl b/Plugins/Alice-Database/src/test.decl new file mode 100644 index 0000000..210da32 --- /dev/null +++ b/Plugins/Alice-Database/src/test.decl @@ -0,0 +1,3 @@ +CREATE INSTANCE new_instance ENGINE json_engine; +GET INSTANCES; +PRINTALLDDBMS; diff --git a/Plugins/Alice-Database/src/utils.rs b/Plugins/Alice-Database/src/utils.rs index d504de5..d604c65 100644 --- a/Plugins/Alice-Database/src/utils.rs +++ b/Plugins/Alice-Database/src/utils.rs @@ -34,7 +34,17 @@ const ADB_DATA_DIR: &str = "ADB_Data"; const JSON_ENGINE_DIR: &str = "json_engine"; const ADB_LOGS_DIR: &str = "ADB_Logs"; +pub fn get_root_path() -> PathBuf { + let root_path = match prepare() { + Ok(k) => k, + _ => panic!("Errors while preparing..."), + }; + return root_path; +} + + pub fn prepare() -> std::io::Result { + print_ascii(); // Get the home directory let home_dir = env::home_dir().expect("Failed to get home directory"); let base_path = home_dir.join(ROOT_DIR);