From fa6aad03dd4f05c51609f97baa8353e7f834f7cc Mon Sep 17 00:00:00 2001 From: Daniil Ermolaev Date: Sat, 26 Oct 2024 14:14:25 +0500 Subject: [PATCH] Log Engine supported now. --- Plugins/Alice-Database/Cargo.toml | 2 +- Plugins/Alice-Database/proto/instance.proto | 5 +- Plugins/Alice-Database/src/engines.rs | 2 + Plugins/Alice-Database/src/grpc_server.rs | 7 +- Plugins/Alice-Database/src/instance.rs | 126 +++++---- Plugins/Alice-Database/src/json_engine.rs | 4 +- Plugins/Alice-Database/src/lib.rs | 249 ------------------ Plugins/Alice-Database/src/log_engine.rs | 214 +++++++++++++++ Plugins/Alice-Database/src/main.rs | 2 + .../src/syntax/instance_manager.pest | 9 +- 10 files changed, 314 insertions(+), 306 deletions(-) delete mode 100644 Plugins/Alice-Database/src/lib.rs create mode 100644 Plugins/Alice-Database/src/log_engine.rs diff --git a/Plugins/Alice-Database/Cargo.toml b/Plugins/Alice-Database/Cargo.toml index b45c44a..74b5e6a 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.2" +version = "1.2.3" edition = "2021" include = ["**/*.rs", "Cargo.toml","proto/*.proto", "src/syntax/*.pest", "src/test.decl"] license = "MIT" diff --git a/Plugins/Alice-Database/proto/instance.proto b/Plugins/Alice-Database/proto/instance.proto index f5f5487..a3cbfdf 100644 --- a/Plugins/Alice-Database/proto/instance.proto +++ b/Plugins/Alice-Database/proto/instance.proto @@ -10,8 +10,9 @@ message Instance { message CreateInstanceRequest { string engine_type = 1; - string root_path = 2; - Token token = 3; + string name = 2; + string root_path = 3; + Token token = 4; } message CreateInstanceResponse { diff --git a/Plugins/Alice-Database/src/engines.rs b/Plugins/Alice-Database/src/engines.rs index 9326703..807ebbe 100644 --- a/Plugins/Alice-Database/src/engines.rs +++ b/Plugins/Alice-Database/src/engines.rs @@ -21,8 +21,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ use crate::json_engine::JSONEngine; +use crate::log_engine::LOGEngine; #[derive(Debug, Clone)] pub enum Engines { + LOGEngine(LOGEngine), JSONEngine(JSONEngine), } diff --git a/Plugins/Alice-Database/src/grpc_server.rs b/Plugins/Alice-Database/src/grpc_server.rs index 3c6b1ba..5d1e4d6 100644 --- a/Plugins/Alice-Database/src/grpc_server.rs +++ b/Plugins/Alice-Database/src/grpc_server.rs @@ -55,10 +55,11 @@ impl InstanceService for GRPCInstanceManager async fn create_instance( &self, request: Request, ) -> Result, Status> { - - let engine_type = request.into_inner().engine_type; + let inner = request.into_inner(); + let engine_type = inner.engine_type; + let name = inner.name; let mut im = self.instance_manager.lock().unwrap(); - let id = im.create_instance(&engine_type).unwrap(); + let id = im.create_instance(&engine_type, &name).unwrap(); Ok( Response::new( CreateInstanceResponse { instance: id } ) diff --git a/Plugins/Alice-Database/src/instance.rs b/Plugins/Alice-Database/src/instance.rs index e0a06e0..06db191 100644 --- a/Plugins/Alice-Database/src/instance.rs +++ b/Plugins/Alice-Database/src/instance.rs @@ -25,10 +25,8 @@ use uuid::Uuid; use std::path::{PathBuf, Path}; use std::fs::File; use std::io::{self, BufRead}; -use crate::JSONEngine; +use crate::{JSONEngine, LOGEngine}; use std::collections::HashMap; -use ring::{rand::{SecureRandom, SystemRandom}, hmac}; -use rand::rngs::OsRng; use crate::IMPestParser; use pest_derive::Parser; use pest::Parser; @@ -54,51 +52,46 @@ pub struct InstanceManager { pub authenticated_apps: HashMap, } - impl InstanceManager { pub fn new(root_path: &PathBuf) -> Self { let name = Uuid::new_v4().to_string(); - - let mut instances: Vec = vec![]; - let mut authenticated_apps: HashMap = HashMap::new(); - Self {name, instances, root_path: root_path.to_owned(), authenticated_apps} + Self { + name, + instances: vec![], + root_path: root_path.to_owned(), + authenticated_apps: HashMap::new(), + } } - 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 { + pub fn create_instance(&mut self, engine_type: &str, name: &str) -> Result> { + let new_name = name.to_string(); + let engine = match engine_type { "json_engine" => Engines::JSONEngine(JSONEngine::new(&self.root_path)), + "log_engine" => Engines::LOGEngine(LOGEngine::new(&self.root_path)), _ => { println!("Engine not found."); return Err(Box::new(std::io::Error::new( - std::io::ErrorKind::InvalidInput, "Engine type not found"))); + std::io::ErrorKind::InvalidInput, "Engine type not found"))); } }; - let mut instance = Instance {engine, name: instance_name.clone()}; + let instance = Instance { engine, name: new_name.clone() }; self.instances.push(instance); - Ok(instance_name) + Ok(new_name) } + pub fn get_instance(&self, instance_name: &str) -> Option<&Instance> { self.instances.iter().find(|i| i.name == instance_name) } - // Method to mutate the engine of an existing instance - pub fn get_mutable_engine(&mut self, instance_name: &str) -> Option<&mut JSONEngine> { - for instance in &mut self.instances { - if instance.name == instance_name { - if let Engines::JSONEngine(ref mut engine) = instance.engine { - return Some(engine); - } - } - } - None + pub fn get_mutable_engine(&mut self, instance_name: &str) -> Option<&mut Engines> { + self.instances.iter_mut().find(|instance| instance.name == instance_name) + .map(|instance| &mut instance.engine) } pub fn sign_up(&mut self, app_name: String) -> String { let key = Uuid::new_v4().to_string(); - &self.authenticated_apps.insert(app_name, key.clone()); - return key; + self.authenticated_apps.insert(app_name, key.clone()); + key } pub fn get_all_apps(&self) { @@ -113,22 +106,66 @@ impl InstanceManager { 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]); + let instance_id = self.create_instance(inner[1], inner[0]); match instance_id { Ok(message) => adbprint!("NEW INSTANCE ID: {}", message), - Err(e) => adbprint!("{:#?}",e) + Err(e) => adbprint!("{:#?}", e), } }, Rule::get_instance => { let inner = inner_pair.into_inner().as_str(); - adbprint!("{:#?}", inner); + adbprint!("{:#?}", self.get_instance(inner)); }, Rule::get_instances => { adbprint!("{:#?}", self.instances); }, Rule::print_addbms => { adbprint!("{:#?}", self); + }, + Rule::create_collection => { + let inner = inner_pair.into_inner().as_str().split(" INSTANCE WITH NAME ").collect::>(); + if let Some(engine) = self.get_mutable_engine(inner[0]) { + match engine { + Engines::JSONEngine(json_engine) => { + json_engine.add_collection(inner[1]); // Call method for JSONEngine + }, + Engines::LOGEngine(log_engine) => { + log_engine.add_collection(inner[1]); // Call method for LOGEngine + }, + // You can add more engine variants here if needed + } + } else { + adbprint!("Instance not found: {}", inner[0]); + } } + + Rule::create_document => { + let inner = inner_pair.into_inner().as_str().split(" INSTANCE IN COLLECTION ").collect::>(); + let inner_two = inner[1].split(" WITH NAME ").collect::>(); + + if let Some(engine) = self.get_mutable_engine(inner[0]) { + match engine { + Engines::JSONEngine(json_engine) => { + if let Some(collection) = json_engine.get_collection_mut(inner_two[0]) { + collection.add_document(inner_two[1], ""); + adbprint!("DOCUMENT {} CREATED IN {}.{} C.I", inner_two[1], inner_two[0], inner[0]); + } else { + adbprint!("Collection not found in JSONEngine: {}", inner_two[0]); + } + }, + Engines::LOGEngine(log_engine) => { + if let Some(collection) = log_engine.get_collection_mut(inner_two[0]) { + collection.add_document(inner_two[1], ""); + adbprint!("DOCUMENT {} CREATED IN {}.{} C.I", inner_two[1], inner_two[0], inner[0]); + } else { + adbprint!("Collection not found in LOGEngine: {}", inner_two[0]); + } + }, + } + } else { + adbprint!("Instance not found: {}", inner[0]); + } + }, _ => unreachable!("I don't know this command"), } } @@ -143,27 +180,22 @@ impl InstanceManager { } pub fn wrapped_execute_cmd(&mut self, command: &str) -> Result<(), Box> { - match &self.execute_cmd(command) { - Ok(_) => println!(""), - Err(e) => adbprint!("Error! {}", e), - } - Ok(()) + self.execute_cmd(command) + .map_err(|e| { adbprint!("Error! {}", e); e }) } 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()); + P: AsRef, + { + let file = File::open(filename)?; + let reader = io::BufReader::new(file); + + for line in reader.lines() { + if let Err(e) = self.wrapped_execute_cmd(&line?.replace("\n", "")) { + adbprint!("Failed to execute line: {}", e); } - Ok(()) + } + Ok(()) } } - - - - diff --git a/Plugins/Alice-Database/src/json_engine.rs b/Plugins/Alice-Database/src/json_engine.rs index 066c57b..5397822 100644 --- a/Plugins/Alice-Database/src/json_engine.rs +++ b/Plugins/Alice-Database/src/json_engine.rs @@ -29,6 +29,7 @@ use serde_json::{json, Value, Result as JsonResult}; use log::{info, error, trace}; use simplelog::*; +use uuid::Uuid; use chrono::Local; const ROOT_DIR: &str = "Alice-Database-Data"; @@ -78,7 +79,8 @@ impl Collection { let collection_path = Path::new(&self.path()).join(&self.name); fs::create_dir_all(&collection_path)?; - let doc_path = collection_path.join(name); // Correctly construct the document path + let doc_path = collection_path.join(&name.clone()); // Correctly construct the document path + let mut file = fs::File::create(&doc_path)?; file.write_all(content.as_bytes())?; diff --git a/Plugins/Alice-Database/src/lib.rs b/Plugins/Alice-Database/src/lib.rs deleted file mode 100644 index 65fc1a6..0000000 --- a/Plugins/Alice-Database/src/lib.rs +++ /dev/null @@ -1,249 +0,0 @@ -/* 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 std::fs; -use std::io::{self, Read, Write}; -use std::path::{PathBuf, Path}; -use serde_json::{json, Value, Result as JsonResult}; -use log::{info, error, trace}; -use simplelog::*; -use chrono::Local; -use std::env; // Import this for getting the home directory - -pub mod json_engine; -use json_engine::*; - -// Define constants for the root path and log path -const ROOT_DIR: &str = "Alice-Database-Data"; -const ADB_DATA_DIR: &str = "ADB_Data"; -const JSON_ENGINE_DIR: &str = "json_engine"; -const ADB_LOGS_DIR: &str = "ADB_Logs"; - -fn prepare() -> std::io::Result { - // Get the home directory - let home_dir = env::home_dir().expect("Failed to get home directory"); - let base_path = home_dir.join(ROOT_DIR); - let adb_data_path = base_path.join(ADB_DATA_DIR); - let adb_logs_path = base_path.join(ADB_LOGS_DIR); - - // Ensure the base and log directories exist - fs::create_dir_all(&adb_data_path).expect("Failed to create ADB_Data directory"); - fs::create_dir_all(&adb_logs_path).expect("Failed to create ADB_Logs directory"); - - // Define the data path for JSON documents - let root_path = adb_data_path.join(JSON_ENGINE_DIR); - - // Ensure the JSON engine directory exists - fs::create_dir_all(&root_path).expect("Failed to create json_engine directory"); - // Generate a unique log filename using timestamp - let timestamp = Local::now().format("%Y-%m-%d_%H-%M-%S").to_string(); - let log_file_path = format!("{}/{}.adb.log", adb_logs_path.display(), timestamp); - - // Set up logging configuration - let log_config = ConfigBuilder::new().build(); - - CombinedLogger::init( - vec![ - TermLogger::new(LevelFilter::Trace, log_config.clone(), TerminalMode::Mixed, ColorChoice::Auto), - WriteLogger::new(LevelFilter::Trace, log_config.clone(), fs::File::create(log_file_path).unwrap()), - ] - ).unwrap(); - Ok(root_path.clone()) - -} - -fn print_ascii() { - println!(r" - @---------------------------------------------------------------@ - | ______ __ __ ______ ______ | - | /\ __ \ /\ \ /\ \ /\ ___\ /\ ___\ | - | \ \ __ \ \ \ \____ \ \ \ \ \ \____ \ \ __\ | - | \ \_\ \_\ \ \_____\ \ \_\ \ \_____\ \ \_____\ | - | \/_/\/_/ \/_____/ \/_/ \/_____/ \/_____/ | - | | - | _____ ______ | - | /\ __-. /\ == \ | - | \ \ \/\ \ \ \ __< | - | \ \____- \ \_____\ | - | \/____/ \/_____/ | - | | - @---------------------------------------------------------------@ - ") -} - - -/// The main entry point for the application. -fn main() -> std::io::Result<()> { - print_ascii(); - let root_path = match prepare() { - Ok(k) => k, - _ => panic!("Errors in prepare function."), - }; - - trace!("Starting Collection Manager..."); - - let mut manager = JSONEngine::new(&root_path); - - // Create a new collection - let collection_name = "collection1"; // Example collection name - if let Some(_) = manager.add_collection(collection_name) { - trace!("Created collection: {}", collection_name); - } - - // Create a new document within the created collection - let document_name = "document5.json"; // Example document name - let document_content = json!({ - "code": 200, - "success": true, - "payload": { - "features": [ - "serde", - "json" - ], - "homepage": null - } - }); - - // Convert JSON Value to String - let document_content_str = serde_json::to_string(&document_content).expect("Failed to convert JSON to string"); - - if let Some(collection) = manager.get_collection_mut(collection_name) { - if let Err(e) = collection.add_document(document_name, &document_content_str) { - error!("Failed to add document: {}", e); - } else { - trace!("Created document: {} in collection: {}", document_name, collection_name); - } - } - - // Example of accessing the document - if let Some(doc) = manager.get_document(collection_name, document_name) { - println!("Found document: {:?}", doc); - trace!("Successfully found document: {}", doc.name); - } else { - println!("Document '{}' not found in collection '{}'", document_name, collection_name); - error!("Document '{}' not found in collection '{}'", document_name, collection_name); - } - - // Example of updating 'homepage' in the 'payload' field - if let Some(doc) = manager.get_document_mut(collection_name, document_name) { - // New value for 'payload.homepage' - let new_homepage_value = json!("https://new-homepage-url.com"); - - if let Err(e) = doc.update_nested_field("payload", "homepage", &new_homepage_value) { - error!("Failed to update 'homepage' in 'payload': {}", e); - } else { - trace!("Updated 'homepage' in document: {}", document_name); - } - } - - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - use std::env; - use std::fs; - use std::path::{Path, PathBuf}; - use serde_json::json; - const TEST_ROOT_DIR: &str = "Alice-Database-Data-Test"; - const TEST_ADB_DATA_DIR: &str = "ADB_Data"; - const TEST_JSON_ENGINE_DIR: &str = "json_engine"; - - // Setup a temporary test directory - fn setup_test_dir() -> PathBuf { - let home_dir = env::temp_dir(); - let test_dir = home_dir.join(TEST_ROOT_DIR); - fs::create_dir_all(&test_dir).expect("Failed to create test directory"); - test_dir - } - - #[test] - fn test_create_and_add_document() { - let root_path = setup_test_dir(); - let mut manager = JSONEngine::new(&root_path); - - // Create a collection - manager.add_collection("test_collection").unwrap(); - let collection = manager.get_collection_mut("test_collection").unwrap(); - - // Add a document - let doc_content = json!({"code": 200, "success": true}).to_string(); - let result = collection.add_document("test_document.json", &doc_content); - assert!(result.is_ok()); - - // Verify the document is added - assert_eq!(collection.documents.len(), 1); - assert_eq!(collection.documents[0].name, "test_document.json"); - } - - #[test] - fn test_update_document() { - let root_path = setup_test_dir(); - let mut manager = JSONEngine::new(&root_path); - - // Create a collection and add a document - manager.add_collection("test_collection").unwrap(); - let collection = manager.get_collection_mut("test_collection").unwrap(); - let doc_content = json!({ - "code": 200, - "success": true, - "payload": { - "homepage": null - } - }).to_string(); - collection.add_document("test_document.json", &doc_content).unwrap(); - - // Update the homepage field - let doc = collection.get_document_mut("test_document.json").unwrap(); - let new_homepage_value = json!("https://new-homepage-url.com"); - - let update_result = doc.update_nested_field("payload", "homepage", &new_homepage_value); - assert!(update_result.is_ok()); - - // Check the updated value - assert_eq!(doc.json_value.as_ref().unwrap()["payload"]["homepage"], new_homepage_value); - } - - #[test] - fn test_delete_document() { - let root_path = setup_test_dir(); - let mut manager = JSONEngine::new(&root_path); - - // Create a collection and add a document - manager.add_collection("test_collection").unwrap(); - let collection = manager.get_collection_mut("test_collection").unwrap(); - collection.add_document("test_document.json", "{\"key\":\"value\"}").unwrap(); - - // Ensure the document exists before deletion - assert_eq!(collection.documents.len(), 1); - - // Delete the document - let delete_result = collection.delete_document("test_document.json"); - assert!(delete_result.is_ok()); - - // Verify the document was deleted - assert_eq!(collection.documents.len(), 0); - } - -} diff --git a/Plugins/Alice-Database/src/log_engine.rs b/Plugins/Alice-Database/src/log_engine.rs new file mode 100644 index 0000000..4d0c629 --- /dev/null +++ b/Plugins/Alice-Database/src/log_engine.rs @@ -0,0 +1,214 @@ + +use std::fs::*; +use std::io::{self, Read, Write}; +use std::path::{Path, PathBuf}; +use std::fs; +use std::env; +use log::error; + +const ROOT_DIR: &str = "Alice-Database-Data"; +const ADB_DATA_DIR: &str = "ADB_Data"; +const LOG_ENGINE_DIR: &str = "log_engine"; + +#[derive(Debug, Clone)] +pub struct Document { + pub name: String, + pub path: PathBuf, + pub data: String, +} + +#[derive(Debug, Clone)] +pub struct Collection { + pub name: String, + pub documents: Vec, +} + +impl Collection { + // Method to get a document by name + pub fn get_document(&self, name: &str) -> Option<&Document> { + self.documents.iter().find(|doc| doc.name == name) + } + + /// Retrieve a mutable reference to a document by its name. + /// + /// # Parameters + /// - `name`: The name of the document to retrieve. + /// + /// # Returns + /// An `Option` containing a mutable reference to the `Document` if found, + /// or `None` if not found. + pub fn get_document_mut(&mut self, name: &str) -> Option<&mut Document> { + self.documents.iter_mut().find(|doc| doc.name == name) + } + + // Method to add a new document to the collection + pub fn add_document(&mut self, name: &str, content: &str) -> io::Result<()> { + let collection_path = Path::new(&self.path()).join(&self.name); + fs::create_dir_all(&collection_path)?; + + let doc_path = collection_path.join(&name.clone()); // Correctly construct the document path + + let mut file = fs::File::create(&doc_path)?; + file.write_all(content.as_bytes())?; + + // Create a new Document instance + let new_document = Document { + name: name.to_string(), + path: doc_path.clone(), + data: content.to_string(), + }; + self.documents.push(new_document); + Ok(()) + } + + // Method to delete a document from the collection + pub fn delete_document(&mut self, name: &str) -> io::Result<()> { + if let Some(doc) = self.documents.iter().find(|doc| doc.name == name) { + fs::remove_file(&doc.path)?; + self.documents.retain(|doc| doc.name != name); + Ok(()) + } else { + Err(io::Error::new(io::ErrorKind::NotFound, "Document not found")) + } + } + + fn path(&self) -> PathBuf { + let home_dir = env::home_dir().expect("Failed to get home directory"); + home_dir.join(ROOT_DIR).join(ADB_DATA_DIR).join(LOG_ENGINE_DIR) + } +} + +#[derive(Debug, Clone)] +pub struct LOGEngine { + pub collections: Vec, +} +impl LOGEngine { + /// Create a new `JSONEngine`. + /// + /// # Parameters + /// - `root`: The path to the root directory for data storage. + /// + /// # Returns + /// A new instance of `JSONEngine`. + pub fn new(root: &Path, ) -> Self { + let collections = get_exists_collections(root); + LOGEngine { collections } + } + + + /// Retrieve a mutable reference to a collection by its name. + /// + /// # Parameters + /// - `name`: The name of the collection to retrieve. + /// + /// # Returns + /// An `Option` containing a mutable reference to the `Collection`, if found. + pub fn get_collection_mut(&mut self, name: &str) -> Option<&mut Collection> { + self.collections.iter_mut().find(|col| col.name == name) + } + + /// Add a new collection. + /// + /// # Parameters + /// - `name`: The name of the collection to create. + /// + /// # Returns + /// An `Option` containing a mutable reference to the newly added `Collection`. + pub fn add_collection(&mut self, name: &str) -> Option<&mut Collection> { + let collection_path = Path::new(&self.root_path()).join(name); + fs::create_dir_all(&collection_path).ok()?; // Create the directory for new collection + + let new_collection = Collection { + name: name.to_string(), + documents: vec![], + }; + + self.collections.push(new_collection); + self.collections.last_mut() // Return a mutable reference to the newly added collection + } + + /// Get a collection by name. + /// + /// # Parameters + /// - `name`: The name of the collection to retrieve. + /// + /// # Returns + /// An `Option` containing a reference to the `Collection`, if found. + pub fn get_collection(&self, name: &str) -> Option<&Collection> { + self.collections.iter().find(|col| col.name == name) + } + + /// Get a document from a specific collection. + /// + /// # Parameters + /// - `collection_name`: The name of the collection the document belongs to. + /// - `document_name`: The name of the document to retrieve. + /// + /// # Returns + /// An `Option` containing a reference to the `Document`, if found. + pub fn get_document(&self, collection_name: &str, document_name: &str) -> Option<&Document> { + self.get_collection(collection_name)?.get_document(document_name) + } + + fn root_path(&self) -> PathBuf { + let home_dir = env::home_dir().expect("Failed to get home directory"); + home_dir.join(ROOT_DIR).join(ADB_DATA_DIR).join(LOG_ENGINE_DIR) + } +} + + +// Functions for handling file operations and collections +fn get_documents_in_collection(path: &Path) -> Vec { + let entries = fs::read_dir(path).unwrap(); + let mut documents: Vec = vec![]; + + for entry in entries { + let entry = entry.unwrap(); + let entry_path = entry.path(); + if entry_path.is_file() { + let name = entry_path.file_name().unwrap().to_string_lossy().into_owned(); + let data = read_file_data(&entry_path).unwrap_or_default(); + let document = Document { + name, + path: entry_path.clone(), + data, + }; + documents.push(document); + } + } + documents +} + +fn read_file_data(path: &Path) -> io::Result { + let mut file = fs::File::open(path)?; + let mut contents = String::new(); + file.read_to_string(&mut contents)?; + Ok(contents) +} + +fn get_exists_collections(path: &Path) -> Vec { + let mut collections: Vec = vec![]; + + if path.exists() && path.is_dir() { + let entries = fs::read_dir(path).unwrap(); + + for entry in entries { + let entry = entry.unwrap(); + let entry_path = entry.path(); + + if entry_path.is_dir() { + let documents = get_documents_in_collection(&entry_path); + let collection_name = entry_path.file_name().unwrap().to_string_lossy().into_owned(); + let collection = Collection { + name: collection_name, + documents, + }; + collections.push(collection); + } + } + } else { + error!("The specified path does not exist or is not a directory: {:?}", path); + } + + collections +} diff --git a/Plugins/Alice-Database/src/main.rs b/Plugins/Alice-Database/src/main.rs index 78853a0..53975cb 100644 --- a/Plugins/Alice-Database/src/main.rs +++ b/Plugins/Alice-Database/src/main.rs @@ -34,6 +34,7 @@ use simplelog::*; use chrono::Local; pub mod json_engine; +pub mod log_engine; pub mod engines; pub mod grpc_server; pub mod instance; @@ -42,6 +43,7 @@ pub mod command_executor; pub mod cli; use json_engine::*; +use log_engine::*; use engines::*; use grpc_server::*; use instance::*; diff --git a/Plugins/Alice-Database/src/syntax/instance_manager.pest b/Plugins/Alice-Database/src/syntax/instance_manager.pest index 097d3f6..581f9e0 100644 --- a/Plugins/Alice-Database/src/syntax/instance_manager.pest +++ b/Plugins/Alice-Database/src/syntax/instance_manager.pest @@ -1,6 +1,6 @@ alpha = { 'a'..'z' | 'A'..'Z' } digit = { '0'..'9' } -ident = { !digit ~ (alpha | digit | "_")+ } +ident = { (alpha | digit) ~ (alpha | digit | "_" | "-" )+ } item = { ident } items = { item ~ (( "," | "," ) ~ item)* } @@ -9,11 +9,14 @@ create_instance = { "CREATE INSTANCE " ~ ident ~ " ENGINE " ~ ident } get_instance = { "GET INSTANCE " ~ ident } get_instances = { "GET INSTANCES" } delete_instance = { "DELETE INSTANCE " ~ ident } - print_addbms = { "PRINTALLDDBMS" } +create_collection = { "CREATE COLLECTION IN " ~ ident ~ " INSTANCE WITH NAME " ~ ident } +create_document = { "CREATE DOCUMENT IN " ~ ident ~ " INSTANCE IN COLLECTION " ~ ident ~ " WITH NAME " ~ ident} + sql_statement = { - create_instance | get_instance | get_instances | delete_instance | print_addbms + create_instance | get_instance | get_instances | delete_instance | print_addbms | + create_collection | create_document } sql_statements = _{ sql_statement ~ ((";" ~ sql_statement) | (";" ~ sql_statement))* ~ ";"? }