generalization on the way, needs fixes
This commit is contained in:
@@ -1,10 +1,12 @@
|
|||||||
// src/steel/execution.rs
|
// src/steel/handlers/execution.rs
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use sqlx::{PgPool, Row};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ScriptOperation {
|
pub enum ScriptOperation {
|
||||||
SetToColumn { source: String },
|
SetToLocalColumn { source: String },
|
||||||
// Future operations can be added here
|
SetToExternalColumn { table: String, column: String },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -12,6 +14,10 @@ pub enum ScriptExecutionError {
|
|||||||
ParseError(String),
|
ParseError(String),
|
||||||
MissingSourceColumn(String),
|
MissingSourceColumn(String),
|
||||||
Mismatch { expected: String, actual: String },
|
Mismatch { expected: String, actual: String },
|
||||||
|
InvalidReference(String),
|
||||||
|
MissingLinkKey(String),
|
||||||
|
DatabaseError(String),
|
||||||
|
MissingExternalData(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ScriptExecutionError {
|
impl fmt::Display for ScriptExecutionError {
|
||||||
@@ -24,6 +30,10 @@ impl fmt::Display for ScriptExecutionError {
|
|||||||
"Value does not match script expectation. Expected: {}, Actual: {}",
|
"Value does not match script expectation. Expected: {}, Actual: {}",
|
||||||
expected, actual
|
expected, actual
|
||||||
),
|
),
|
||||||
|
Self::InvalidReference(msg) => write!(f, "Invalid reference: {}", msg),
|
||||||
|
Self::MissingLinkKey(key) => write!(f, "Missing link key: {}", key),
|
||||||
|
Self::DatabaseError(msg) => write!(f, "Database error: {}", msg),
|
||||||
|
Self::MissingExternalData(msg) => write!(f, "External data not found: {}", msg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,7 +70,57 @@ pub fn parse_script(script: &str, expected_target: &str) -> Result<ScriptOperati
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ScriptOperation::SetToColumn {
|
// Check if source is an external reference
|
||||||
source: source.to_string(),
|
if source.starts_with('@') {
|
||||||
})
|
let (table, column) = source.split_once('.')
|
||||||
|
.ok_or_else(|| ScriptExecutionError::InvalidReference(
|
||||||
|
format!("Invalid external reference format: {}", source)
|
||||||
|
))?;
|
||||||
|
Ok(ScriptOperation::SetToExternalColumn {
|
||||||
|
table: table.to_string(),
|
||||||
|
column: column.to_string(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Ok(ScriptOperation::SetToLocalColumn {
|
||||||
|
source: source.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn resolve_value(
|
||||||
|
db_pool: &PgPool,
|
||||||
|
profile_id: i64,
|
||||||
|
current_table: &str,
|
||||||
|
current_data: &HashMap<String, String>,
|
||||||
|
source: &str,
|
||||||
|
) -> Result<String, ScriptExecutionError> {
|
||||||
|
if let Some((table, column)) = source.split_once('.') {
|
||||||
|
// External table reference
|
||||||
|
let external_table = table.strip_prefix('@')
|
||||||
|
.ok_or_else(|| ScriptExecutionError::InvalidReference(format!("Invalid external reference: {}", source)))?;
|
||||||
|
|
||||||
|
// Get linking key (assuming firma is the common key)
|
||||||
|
let firma = current_data.get("firma")
|
||||||
|
.ok_or_else(|| ScriptExecutionError::MissingLinkKey("firma".into()))?;
|
||||||
|
|
||||||
|
// Query external table
|
||||||
|
let query = format!("SELECT {} FROM \"{}\" WHERE firma = $1 AND profile_id = $2", column, external_table);
|
||||||
|
|
||||||
|
let result: Option<String> = sqlx::query(&query)
|
||||||
|
.bind(firma)
|
||||||
|
.bind(profile_id)
|
||||||
|
.fetch_optional(db_pool)
|
||||||
|
.await
|
||||||
|
.map_err(|e| ScriptExecutionError::DatabaseError(e.to_string()))?
|
||||||
|
.and_then(|row| row.try_get(0).ok());
|
||||||
|
|
||||||
|
result.ok_or_else(|| ScriptExecutionError::MissingExternalData(
|
||||||
|
format!("No data found for {} in {}", column, external_table)
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
// Local column reference
|
||||||
|
current_data.get(source)
|
||||||
|
.cloned()
|
||||||
|
.ok_or_else(|| ScriptExecutionError::MissingSourceColumn(source.into()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ pub fn validate_script(script: &str) -> Result<(), ScriptValidationError> {
|
|||||||
if script.trim().is_empty() {
|
if script.trim().is_empty() {
|
||||||
return Err(ScriptValidationError::EmptyScript);
|
return Err(ScriptValidationError::EmptyScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we get here, the script passed basic validation
|
// If we get here, the script passed basic validation
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ use crate::steel::validation::script::validate_script;
|
|||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
// Add these imports for the execution module and ScriptOperation
|
// Add these imports for the execution module and ScriptOperation
|
||||||
use crate::steel::handlers::execution;
|
use crate::steel::handlers::execution::{self, ScriptOperation};
|
||||||
use crate::steel::handlers::ScriptOperation;
|
|
||||||
|
|
||||||
const SYSTEM_COLUMNS: &[&str] = &["id", "deleted", "created_at"];
|
const SYSTEM_COLUMNS: &[&str] = &["id", "deleted", "created_at"];
|
||||||
|
|
||||||
@@ -61,7 +60,8 @@ pub async fn post_table_script(
|
|||||||
|
|
||||||
// Ensure the operation is valid (additional checks if needed)
|
// Ensure the operation is valid (additional checks if needed)
|
||||||
match operation {
|
match operation {
|
||||||
ScriptOperation::SetToColumn { .. } => {}, // Use directly without 'execution::'
|
ScriptOperation::SetToLocalColumn { .. } => {},
|
||||||
|
ScriptOperation::SetToExternalColumn { .. } => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call validation functions
|
// Call validation functions
|
||||||
|
|||||||
Reference in New Issue
Block a user