From 50487c126940820f23f8d8f16e2f93b426436c37 Mon Sep 17 00:00:00 2001 From: filipriec Date: Sat, 15 Mar 2025 23:47:40 +0100 Subject: [PATCH] execution properly working, time to code the funcitons that are called from within the steel script --- server/src/steel/server/execution.rs | 110 ++++++++++++--------------- 1 file changed, 50 insertions(+), 60 deletions(-) diff --git a/server/src/steel/server/execution.rs b/server/src/steel/server/execution.rs index 8b33bc0..713eb8d 100644 --- a/server/src/steel/server/execution.rs +++ b/server/src/steel/server/execution.rs @@ -1,4 +1,5 @@ // src/steel/server/execution.rs +// src/steel/server/execution.rs use steel::steel_vm::engine::Engine; use steel::steel_vm::register_fn::RegisterFn; use steel::rvals::SteelVal; @@ -20,90 +21,79 @@ pub enum ExecutionError { #[derive(Debug)] pub enum Value { - String(String), + Strings(Vec), + Numbers(Vec), + Mixed(Vec), } pub fn execute_script( script: String, target_type: &str, - current_data: HashMap, -) -> Result { - let mut vm = Engine::new(); - - let data = current_data.clone(); - vm.register_fn("steel_get_column", move |column: String| { - data.get(&column) - .map(|s| SteelVal::StringV(s.clone().into())) - .ok_or_else(|| SteelVal::StringV(format!("Column {} not found", column).into())) - }); - - let results = vm.compile_and_run_raw_program(script) - .map_err(|e| ExecutionError::RuntimeError(e.to_string()))?; - - let last_result = results.last() - .ok_or_else(|| ExecutionError::TypeConversionError("Script returned no values".to_string()))?; - - match target_type { - "STRING" => { - if let SteelVal::StringV(s) = last_result { - Ok(Value::String(s.to_string())) - } else { - Err(ExecutionError::TypeConversionError( - format!("Expected string, got {:?}", last_result) - )) - } - } - _ => Err(ExecutionError::UnsupportedType(target_type.to_string())), - } -} - -pub fn execute_script_with_sql( - script: String, - target_type: &str, - db_pool: Arc, + db_pool: Option>, current_data: HashMap, ) -> Result { let mut vm = Engine::new(); let handle = Handle::current(); + // Clone data for closures let data = current_data.clone(); + + // Register steel_get_column (current table access) vm.register_fn("steel_get_column", move |column: String| { data.get(&column) .map(|s| SteelVal::StringV(s.clone().into())) .ok_or_else(|| SteelVal::StringV(format!("Column {} not found", column).into())) }); - let pool = db_pool.clone(); - vm.register_fn("steel_query_sql", move |query: String| { - let pool = pool.clone(); - let query = query.clone(); - let handle = handle.clone(); + // Register steel_get_column_with_index (related table indexed access) + let indexed_data = current_data.clone(); + vm.register_fn("steel_get_column_with_index", + move |table: String, index: i64, column: String| { + let key = format!("{}.{}", table, column); + indexed_data.get(&key) + .and_then(|s| s.split(',').nth(index as usize)) + .map(|v| SteelVal::StringV(v.trim().to_string().into())) + .ok_or_else(|| SteelVal::StringV( + format!("Index {} not found for {}.{}", index, table, column).into() + )) + }); - handle.block_on(async move { - sqlx::query_scalar::<_, i64>(&query) - .fetch_one(&*pool) - .await - .map(|v| SteelVal::IntV(v as isize)) - .map_err(|e| SteelVal::StringV(format!("SQL error: {}", e).into())) - }) - }); + // Register SQL function if pool exists + if let Some(pool) = db_pool { + let pool_clone = pool.clone(); + vm.register_fn("steel_query_sql", move |query: String| { + let pool = pool_clone.clone(); + let handle = handle.clone(); + + handle.block_on(async move { + sqlx::query_scalar::<_, i64>(&query) + .fetch_one(&*pool) + .await + .map(|v| SteelVal::IntV(v as isize)) + .map_err(|e| SteelVal::StringV(format!("SQL error: {}", e).into())) + }) + }); + } + // Execute all expressions in script let results = vm.compile_and_run_raw_program(script) .map_err(|e| ExecutionError::RuntimeError(e.to_string()))?; - let last_result = results.last() - .ok_or_else(|| ExecutionError::TypeConversionError("Script returned no values".to_string()))?; - + // Process results based on target type match target_type { - "STRING" => { - if let SteelVal::StringV(s) = last_result { - Ok(Value::String(s.to_string())) - } else { - Err(ExecutionError::TypeConversionError( - format!("Expected string, got {:?}", last_result) - )) + "STRINGS" => { + let mut strings = Vec::new(); + for result in results { + if let SteelVal::StringV(s) = result { + strings.push(s.to_string()); + } else { + return Err(ExecutionError::TypeConversionError( + format!("Expected string, got {:?}", result) + )); + } } - } + Ok(Value::Strings(strings)) + }, _ => Err(ExecutionError::UnsupportedType(target_type.to_string())), } }