From 4a43097773aea9133c802d7515d60c13bab807b9 Mon Sep 17 00:00:00 2001 From: filipriec Date: Sat, 8 Mar 2025 16:25:36 +0100 Subject: [PATCH] generalization on the way, needs fixes --- server/src/steel/handlers/execution.rs | 72 +++++++++++++++++-- server/src/steel/validation/script.rs | 2 +- .../handlers/post_table_script.rs | 6 +- 3 files changed, 70 insertions(+), 10 deletions(-) diff --git a/server/src/steel/handlers/execution.rs b/server/src/steel/handlers/execution.rs index 0981d98..c8418ab 100644 --- a/server/src/steel/handlers/execution.rs +++ b/server/src/steel/handlers/execution.rs @@ -1,10 +1,12 @@ -// src/steel/execution.rs +// src/steel/handlers/execution.rs use std::fmt; +use std::collections::HashMap; +use sqlx::{PgPool, Row}; #[derive(Debug)] pub enum ScriptOperation { - SetToColumn { source: String }, - // Future operations can be added here + SetToLocalColumn { source: String }, + SetToExternalColumn { table: String, column: String }, } #[derive(Debug)] @@ -12,6 +14,10 @@ pub enum ScriptExecutionError { ParseError(String), MissingSourceColumn(String), Mismatch { expected: String, actual: String }, + InvalidReference(String), + MissingLinkKey(String), + DatabaseError(String), + MissingExternalData(String), } impl fmt::Display for ScriptExecutionError { @@ -24,6 +30,10 @@ impl fmt::Display for ScriptExecutionError { "Value does not match script expectation. 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, + source: &str, +) -> Result { + 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 = 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())) + } } diff --git a/server/src/steel/validation/script.rs b/server/src/steel/validation/script.rs index bcc2257..cd834f6 100644 --- a/server/src/steel/validation/script.rs +++ b/server/src/steel/validation/script.rs @@ -21,7 +21,7 @@ pub fn validate_script(script: &str) -> Result<(), ScriptValidationError> { if script.trim().is_empty() { return Err(ScriptValidationError::EmptyScript); } - + // If we get here, the script passed basic validation Ok(()) } diff --git a/server/src/table_script/handlers/post_table_script.rs b/server/src/table_script/handlers/post_table_script.rs index d10e92f..4663fcb 100644 --- a/server/src/table_script/handlers/post_table_script.rs +++ b/server/src/table_script/handlers/post_table_script.rs @@ -6,8 +6,7 @@ use crate::steel::validation::script::validate_script; use serde_json::Value; // Add these imports for the execution module and ScriptOperation -use crate::steel::handlers::execution; -use crate::steel::handlers::ScriptOperation; +use crate::steel::handlers::execution::{self, ScriptOperation}; 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) match operation { - ScriptOperation::SetToColumn { .. } => {}, // Use directly without 'execution::' + ScriptOperation::SetToLocalColumn { .. } => {}, + ScriptOperation::SetToExternalColumn { .. } => {}, } // Call validation functions