execution properly working, time to code the funcitons that are called from within the steel script
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
// src/steel/server/execution.rs
|
// src/steel/server/execution.rs
|
||||||
|
// src/steel/server/execution.rs
|
||||||
use steel::steel_vm::engine::Engine;
|
use steel::steel_vm::engine::Engine;
|
||||||
use steel::steel_vm::register_fn::RegisterFn;
|
use steel::steel_vm::register_fn::RegisterFn;
|
||||||
use steel::rvals::SteelVal;
|
use steel::rvals::SteelVal;
|
||||||
@@ -20,90 +21,79 @@ pub enum ExecutionError {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
String(String),
|
Strings(Vec<String>),
|
||||||
|
Numbers(Vec<i64>),
|
||||||
|
Mixed(Vec<SteelVal>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute_script(
|
pub fn execute_script(
|
||||||
script: String,
|
script: String,
|
||||||
target_type: &str,
|
target_type: &str,
|
||||||
current_data: HashMap<String, String>,
|
db_pool: Option<Arc<PgPool>>,
|
||||||
) -> Result<Value, ExecutionError> {
|
|
||||||
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<PgPool>,
|
|
||||||
current_data: HashMap<String, String>,
|
current_data: HashMap<String, String>,
|
||||||
) -> Result<Value, ExecutionError> {
|
) -> Result<Value, ExecutionError> {
|
||||||
let mut vm = Engine::new();
|
let mut vm = Engine::new();
|
||||||
let handle = Handle::current();
|
let handle = Handle::current();
|
||||||
|
|
||||||
|
// Clone data for closures
|
||||||
let data = current_data.clone();
|
let data = current_data.clone();
|
||||||
|
|
||||||
|
// Register steel_get_column (current table access)
|
||||||
vm.register_fn("steel_get_column", move |column: String| {
|
vm.register_fn("steel_get_column", move |column: String| {
|
||||||
data.get(&column)
|
data.get(&column)
|
||||||
.map(|s| SteelVal::StringV(s.clone().into()))
|
.map(|s| SteelVal::StringV(s.clone().into()))
|
||||||
.ok_or_else(|| SteelVal::StringV(format!("Column {} not found", column).into()))
|
.ok_or_else(|| SteelVal::StringV(format!("Column {} not found", column).into()))
|
||||||
});
|
});
|
||||||
|
|
||||||
let pool = db_pool.clone();
|
// Register steel_get_column_with_index (related table indexed access)
|
||||||
vm.register_fn("steel_query_sql", move |query: String| {
|
let indexed_data = current_data.clone();
|
||||||
let pool = pool.clone();
|
vm.register_fn("steel_get_column_with_index",
|
||||||
let query = query.clone();
|
move |table: String, index: i64, column: String| {
|
||||||
let handle = handle.clone();
|
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 {
|
// Register SQL function if pool exists
|
||||||
sqlx::query_scalar::<_, i64>(&query)
|
if let Some(pool) = db_pool {
|
||||||
.fetch_one(&*pool)
|
let pool_clone = pool.clone();
|
||||||
.await
|
vm.register_fn("steel_query_sql", move |query: String| {
|
||||||
.map(|v| SteelVal::IntV(v as isize))
|
let pool = pool_clone.clone();
|
||||||
.map_err(|e| SteelVal::StringV(format!("SQL error: {}", e).into()))
|
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)
|
let results = vm.compile_and_run_raw_program(script)
|
||||||
.map_err(|e| ExecutionError::RuntimeError(e.to_string()))?;
|
.map_err(|e| ExecutionError::RuntimeError(e.to_string()))?;
|
||||||
|
|
||||||
let last_result = results.last()
|
// Process results based on target type
|
||||||
.ok_or_else(|| ExecutionError::TypeConversionError("Script returned no values".to_string()))?;
|
|
||||||
|
|
||||||
match target_type {
|
match target_type {
|
||||||
"STRING" => {
|
"STRINGS" => {
|
||||||
if let SteelVal::StringV(s) = last_result {
|
let mut strings = Vec::new();
|
||||||
Ok(Value::String(s.to_string()))
|
for result in results {
|
||||||
} else {
|
if let SteelVal::StringV(s) = result {
|
||||||
Err(ExecutionError::TypeConversionError(
|
strings.push(s.to_string());
|
||||||
format!("Expected string, got {:?}", last_result)
|
} else {
|
||||||
))
|
return Err(ExecutionError::TypeConversionError(
|
||||||
|
format!("Expected string, got {:?}", result)
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
Ok(Value::Strings(strings))
|
||||||
|
},
|
||||||
_ => Err(ExecutionError::UnsupportedType(target_type.to_string())),
|
_ => Err(ExecutionError::UnsupportedType(target_type.to_string())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user