From bd45f5db103ce0df35eae7ad7849e43a3f77b20c Mon Sep 17 00:00:00 2001 From: Daniil Ermolaev Date: Fri, 25 Oct 2024 22:30:20 +0500 Subject: [PATCH 1/4] pest parser connected --- .../Alice-Database/src/command_executor.rs | 43 +++++++++++ Plugins/Alice-Database/src/grpc.rs | 71 ------------------- Plugins/Alice-Database/src/main.rs | 27 +++++-- .../src/syntax/instance_manager.pest | 19 +++++ Plugins/Alice-Database/src/utils.rs | 10 +++ 5 files changed, 93 insertions(+), 77 deletions(-) create mode 100644 Plugins/Alice-Database/src/command_executor.rs delete mode 100644 Plugins/Alice-Database/src/grpc.rs create mode 100644 Plugins/Alice-Database/src/syntax/instance_manager.pest diff --git a/Plugins/Alice-Database/src/command_executor.rs b/Plugins/Alice-Database/src/command_executor.rs new file mode 100644 index 0000000..38bccee --- /dev/null +++ b/Plugins/Alice-Database/src/command_executor.rs @@ -0,0 +1,43 @@ +use pest_derive::Parser; +use pest::Parser; + +#[derive(Parser)] +#[grammar = "syntax/instance_manager.pest"] +struct InstanceManagerIdentParser; + +pub trait IMCommandExecutor { + fn execute(&mut self, command: &str) -> Result<(), Box> { + // Attempt to parse the command and handle any parsing errors + match InstanceManagerIdentParser::parse(Rule::sql_statements, command) { + Ok(pairs) => { + // Process parsed pairs + for pair in pairs { + for inner_pair in pair.into_inner() { + match inner_pair.as_rule() { + Rule::create_instance => { + println!("Creating new instance..."); + }, + Rule::get_instance => { + println!("Retrieving instance..."); + }, + Rule::get_instances => { + println!("Retrieving all instances..."); + }, + Rule::delete_instance => { + println!("Deleting instance..."); + }, + _ => println!("Unrecognized command."), + } + } + } + Ok(()) + } + // Handle parsing errors without panicking + Err(e) => { + println!("Error parsing command: {}", e); + Err(Box::new(e)) // Return the error wrapped in a Box + } + } + } +} + 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/main.rs b/Plugins/Alice-Database/src/main.rs index 1a4d87a..b937a35 100644 --- a/Plugins/Alice-Database/src/main.rs +++ b/Plugins/Alice-Database/src/main.rs @@ -38,21 +38,19 @@ pub mod engines; pub mod grpc_server; pub mod instance; pub mod utils; +pub mod command_executor; use json_engine::*; use engines::*; use grpc_server::*; use instance::*; use utils::*; +use command_executor::*; +/* 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 +65,20 @@ async fn main() -> Result<(), Box> { Ok(()) } +*/ + +impl IMCommandExecutor for InstanceManager {} + +#[tokio::main] +async fn main() -> Result<(), Box> { + let root_path: PathBuf = get_root_path(); + + let mut im = InstanceManager::new(&root_path); + match im.execute("CREATE INSTANCE instance_q;") { + Ok(_) => println!("Done!"), + Err(e) => println!("Something went wrong."), + } + println!("New command"); + im.execute("GET ALL INSTANCES"); + 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..13514a9 --- /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 ALL INSTANCES" } +delete_instance = { "DELETE INSTANCE " ~ ident } + +print_addbms = { "PRINTALLDDBMS" } + +sql_statement = { + create_instance | get_instance | get_instances | delete_instance +} + +sql_statements = _{ sql_statement ~ ((";" ~ sql_statement) | (";" ~ sql_statement))* ~ ";"? } 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); From 0e35476ec3ca80bb4d47478c709ac036ba3ab4df Mon Sep 17 00:00:00 2001 From: Daniil Ermolaev Date: Fri, 25 Oct 2024 22:31:42 +0500 Subject: [PATCH 2/4] license to command_executor.rs --- Plugins/Alice-Database/Cargo.toml | 4 +++- .../Alice-Database/src/command_executor.rs | 23 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Plugins/Alice-Database/Cargo.toml b/Plugins/Alice-Database/Cargo.toml index 04a5102..9e33b22 100644 --- a/Plugins/Alice-Database/Cargo.toml +++ b/Plugins/Alice-Database/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "Alice-Database_DBMS" -version = "1.2.0" +version = "1.2.1" edition = "2021" include = ["**/*.rs", "Cargo.toml","proto/*.proto"] license = "MIT" @@ -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/command_executor.rs b/Plugins/Alice-Database/src/command_executor.rs index 38bccee..d5a7d11 100644 --- a/Plugins/Alice-Database/src/command_executor.rs +++ b/Plugins/Alice-Database/src/command_executor.rs @@ -1,3 +1,26 @@ + +/* 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; From 08415308ad7b34a3d2d4fecb347fc3585e793cc5 Mon Sep 17 00:00:00 2001 From: Daniil Ermolaev Date: Fri, 25 Oct 2024 22:33:27 +0500 Subject: [PATCH 3/4] add pest files to cargo --- Plugins/Alice-Database/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Alice-Database/Cargo.toml b/Plugins/Alice-Database/Cargo.toml index 9e33b22..99c3546 100644 --- a/Plugins/Alice-Database/Cargo.toml +++ b/Plugins/Alice-Database/Cargo.toml @@ -2,7 +2,7 @@ name = "Alice-Database_DBMS" version = "1.2.1" edition = "2021" -include = ["**/*.rs", "Cargo.toml","proto/*.proto"] +include = ["**/*.rs", "Cargo.toml","proto/*.proto", "src/syntax/*.pest"] 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" From c07302d3b906014e04d5e898e2396dd56f56e01f Mon Sep 17 00:00:00 2001 From: Daniil Ermolaev Date: Sat, 26 Oct 2024 10:15:32 +0500 Subject: [PATCH 4/4] declarative and pest support for instance manager --- Plugins/Alice-Database/Cargo.toml | 4 +- Plugins/Alice-Database/src/cli.rs | 27 ++++++ .../Alice-Database/src/command_executor.rs | 38 +------- Plugins/Alice-Database/src/grpc_server.rs | 2 +- Plugins/Alice-Database/src/instance.rs | 89 +++++++++++++++++-- Plugins/Alice-Database/src/main.rs | 13 +-- .../src/syntax/instance_manager.pest | 4 +- Plugins/Alice-Database/src/test.decl | 3 + 8 files changed, 123 insertions(+), 57 deletions(-) create mode 100644 Plugins/Alice-Database/src/cli.rs create mode 100644 Plugins/Alice-Database/src/test.decl diff --git a/Plugins/Alice-Database/Cargo.toml b/Plugins/Alice-Database/Cargo.toml index 99c3546..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.1" +version = "1.2.2" edition = "2021" -include = ["**/*.rs", "Cargo.toml","proto/*.proto", "src/syntax/*.pest"] +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" 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 index d5a7d11..61b39a8 100644 --- a/Plugins/Alice-Database/src/command_executor.rs +++ b/Plugins/Alice-Database/src/command_executor.rs @@ -26,41 +26,5 @@ use pest::Parser; #[derive(Parser)] #[grammar = "syntax/instance_manager.pest"] -struct InstanceManagerIdentParser; - -pub trait IMCommandExecutor { - fn execute(&mut self, command: &str) -> Result<(), Box> { - // Attempt to parse the command and handle any parsing errors - match InstanceManagerIdentParser::parse(Rule::sql_statements, command) { - Ok(pairs) => { - // Process parsed pairs - for pair in pairs { - for inner_pair in pair.into_inner() { - match inner_pair.as_rule() { - Rule::create_instance => { - println!("Creating new instance..."); - }, - Rule::get_instance => { - println!("Retrieving instance..."); - }, - Rule::get_instances => { - println!("Retrieving all instances..."); - }, - Rule::delete_instance => { - println!("Deleting instance..."); - }, - _ => println!("Unrecognized command."), - } - } - } - Ok(()) - } - // Handle parsing errors without panicking - Err(e) => { - println!("Error parsing command: {}", e); - Err(Box::new(e)) // Return the error wrapped in a Box - } - } - } -} +pub struct IMPestParser; 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 b937a35..78853a0 100644 --- a/Plugins/Alice-Database/src/main.rs +++ b/Plugins/Alice-Database/src/main.rs @@ -39,6 +39,7 @@ pub mod grpc_server; pub mod instance; pub mod utils; pub mod command_executor; +pub mod cli; use json_engine::*; use engines::*; @@ -46,7 +47,7 @@ use grpc_server::*; use instance::*; use utils::*; use command_executor::*; - +use cli::cli; /* gRPC #[tokio::main] async fn main() -> Result<(), Box> { @@ -67,18 +68,12 @@ async fn main() -> Result<(), Box> { } */ -impl IMCommandExecutor for InstanceManager {} - #[tokio::main] async fn main() -> Result<(), Box> { let root_path: PathBuf = get_root_path(); let mut im = InstanceManager::new(&root_path); - match im.execute("CREATE INSTANCE instance_q;") { - Ok(_) => println!("Done!"), - Err(e) => println!("Something went wrong."), - } - println!("New command"); - im.execute("GET ALL INSTANCES"); + //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 index 13514a9..097d3f6 100644 --- a/Plugins/Alice-Database/src/syntax/instance_manager.pest +++ b/Plugins/Alice-Database/src/syntax/instance_manager.pest @@ -7,13 +7,13 @@ items = { item ~ (( "," | "," ) ~ item)* } create_instance = { "CREATE INSTANCE " ~ ident ~ " ENGINE " ~ ident } get_instance = { "GET INSTANCE " ~ ident } -get_instances = { "GET ALL INSTANCES" } +get_instances = { "GET INSTANCES" } delete_instance = { "DELETE INSTANCE " ~ ident } print_addbms = { "PRINTALLDDBMS" } sql_statement = { - create_instance | get_instance | get_instances | delete_instance + 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;