use crate::error::{Result, SqlError}; use crate::metadata::MetadataManager; use crate::parser::{SqlStatement, parse_sql}; use crate::storage::StorageManager; use crate::types::QueryResult; use flaredb_client::RdbClient; use std::sync::Arc; use tokio::sync::Mutex; /// SQL execution result #[derive(Debug)] pub enum ExecutionResult { DdlSuccess(String), DmlSuccess(u64), Query(QueryResult), } /// SQL executor pub struct SqlExecutor { metadata_manager: Arc, storage_manager: Arc, } impl SqlExecutor { pub fn new(client: Arc>) -> Self { let metadata_manager = Arc::new(MetadataManager::new(client.clone())); let storage_manager = Arc::new(StorageManager::new(client)); Self { metadata_manager, storage_manager, } } /// Execute a SQL statement pub async fn execute(&self, sql: &str) -> Result { let statement = parse_sql(sql)?; self.execute_statement(&statement).await } async fn execute_statement(&self, statement: &SqlStatement) -> Result { match statement { SqlStatement::CreateTable { table_name, columns, primary_key, } => { self.metadata_manager .create_table(table_name.clone(), columns.clone(), primary_key.clone()) .await?; Ok(ExecutionResult::DdlSuccess(format!( "Table '{}' created", table_name ))) } SqlStatement::DropTable { table_name } => { self.metadata_manager.drop_table(table_name).await?; Ok(ExecutionResult::DdlSuccess(format!( "Table '{}' dropped", table_name ))) } SqlStatement::Insert { table_name, columns, values, } => { let table = self.metadata_manager.get_table_metadata(table_name).await?; self.storage_manager .insert_row(&table, columns, values) .await?; Ok(ExecutionResult::DmlSuccess(1)) } SqlStatement::Select { table_name, columns, where_clause, } => { let table = self.metadata_manager.get_table_metadata(table_name).await?; let result = self .storage_manager .query_rows(&table, columns, where_clause.as_ref()) .await?; Ok(ExecutionResult::Query(result)) } SqlStatement::Update { .. } => { Err(SqlError::InvalidOperation("UPDATE not yet implemented".to_string())) } SqlStatement::Delete { .. } => { Err(SqlError::InvalidOperation("DELETE not yet implemented".to_string())) } } } } #[cfg(test)] mod tests { use super::*; #[tokio::test] #[ignore] // Requires FlareDB server async fn test_create_and_query_table() { let client = RdbClient::connect_direct("127.0.0.1:8001".to_string(), "sqltest".to_string()).await.unwrap(); let executor = SqlExecutor::new(Arc::new(Mutex::new(client))); // Create table let result = executor .execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)") .await .unwrap(); match result { ExecutionResult::DdlSuccess(msg) => { assert!(msg.contains("created")); } _ => panic!("Expected DdlSuccess"), } // Insert data let result = executor .execute("INSERT INTO users (id, name) VALUES (1, 'Alice')") .await .unwrap(); match result { ExecutionResult::DmlSuccess(count) => { assert_eq!(count, 1); } _ => panic!("Expected DmlSuccess"), } // Query data let result = executor .execute("SELECT * FROM users WHERE id = 1") .await .unwrap(); match result { ExecutionResult::Query(query_result) => { assert_eq!(query_result.row_count(), 1); } _ => panic!("Expected Query result"), } } }