use super::env::Environment;
use super::interpreter::PlSqlInterpreter;
use super::parser::PlSqlParser;
use crate::core::{Result, Value};
use crate::functions::backends::ScriptingBackend;
use crate::functions::FunctionRegistry;
use std::sync::Arc;
pub struct PlSqlBackend {
function_registry: Arc<FunctionRegistry>,
}
impl PlSqlBackend {
pub fn new(function_registry: Arc<FunctionRegistry>) -> Self {
Self { function_registry }
}
}
impl ScriptingBackend for PlSqlBackend {
fn name(&self) -> &'static str {
"plsql"
}
fn supported_languages(&self) -> &[&'static str] {
&["sql", "plsql", "pl/sql"]
}
fn validate_code(&self, code: &str) -> Result<()> {
let mut parser = PlSqlParser::new(code);
match parser.parse() {
Ok(_) => Ok(()),
Err(e) => Err(e),
}
}
fn execute(&self, code: &str, args: &[Value], param_names: &[&str]) -> Result<Value> {
let mut parser = PlSqlParser::new(code);
let block = parser.parse()?;
let mut env = Environment::new();
for (i, arg) in args.iter().enumerate() {
env.define_global(param_names[i], arg.clone());
}
let interpreter = PlSqlInterpreter::new(self.function_registry.clone(), None);
if let Some(val) = interpreter.execute(&block, &mut env)? {
Ok(val)
} else {
Ok(Value::Null(crate::core::DataType::Null))
}
}
fn execute_procedure(
&self,
code: &str,
args: &mut [Value],
param_names: &[&str],
_modes: &[&str],
_runner: Option<&dyn crate::functions::backends::SqlRunner>,
) -> Result<()> {
let mut parser = PlSqlParser::new(code);
let block = parser.parse()?;
let mut env = Environment::new();
for (i, arg) in args.iter().enumerate() {
env.define_global(param_names[i], arg.clone());
}
let interpreter = PlSqlInterpreter::new(self.function_registry.clone(), _runner);
interpreter.execute(&block, &mut env)?;
for (i, arg) in args.iter_mut().enumerate() {
if let Some(val) = env.get(param_names[i]) {
*arg = val.clone();
} else {
println!(
"Warning: {} not found in environment to write back",
param_names[i]
);
}
}
Ok(())
}
}